Default disappearing message timeout fixes
This commit is contained in:
parent
c9415dcf67
commit
cd28e71bc6
25 changed files with 456 additions and 164 deletions
|
@ -1805,7 +1805,7 @@
|
||||||
},
|
},
|
||||||
"disappearingMessages": {
|
"disappearingMessages": {
|
||||||
"message": "Disappearing messages",
|
"message": "Disappearing messages",
|
||||||
"description": "Conversation menu option to enable disappearing messages. Title of the settings section for Disappearing Messages"
|
"description": "Conversation menu option to enable disappearing messages. Title of the settings section for Disappearing Messages. Label of the disappearing timer select in group creation flow"
|
||||||
},
|
},
|
||||||
"disappearingMessagesDisabled": {
|
"disappearingMessagesDisabled": {
|
||||||
"message": "Disappearing messages disabled",
|
"message": "Disappearing messages disabled",
|
||||||
|
|
|
@ -56,7 +56,7 @@ const {
|
||||||
} = require('../../ts/components/conversation/StagedLinkPreview');
|
} = require('../../ts/components/conversation/StagedLinkPreview');
|
||||||
const {
|
const {
|
||||||
DisappearingTimeDialog,
|
DisappearingTimeDialog,
|
||||||
} = require('../../ts/components/conversation/DisappearingTimeDialog');
|
} = require('../../ts/components/DisappearingTimeDialog');
|
||||||
|
|
||||||
// State
|
// State
|
||||||
const { createTimeline } = require('../../ts/state/roots/createTimeline');
|
const { createTimeline } = require('../../ts/state/roots/createTimeline');
|
||||||
|
|
|
@ -2366,64 +2366,9 @@ $timer-icons: '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '05',
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module: Timer Notification
|
// Module: Timer Notification
|
||||||
|
|
||||||
.module-timer-notification {
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
@include light-theme {
|
|
||||||
color: $color-gray-60;
|
|
||||||
}
|
|
||||||
@include dark-theme {
|
|
||||||
color: $color-gray-05;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-timer-notification__icon-container {
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
display: inline-flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-timer-notification__icon {
|
|
||||||
height: 20px;
|
|
||||||
width: 20px;
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
@include light-theme {
|
|
||||||
@include color-svg('../images/icons/v2/timer-24.svg', $color-gray-60);
|
|
||||||
}
|
|
||||||
@include dark-theme {
|
|
||||||
@include color-svg('../images/icons/v2/timer-24.svg', $color-gray-05);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-timer-notification__icon--disabled {
|
|
||||||
@include light-theme {
|
|
||||||
@include color-svg(
|
|
||||||
'../images/icons/v2/timer-disabled-24.svg',
|
|
||||||
$color-gray-60
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@include dark-theme {
|
|
||||||
@include color-svg(
|
|
||||||
'../images/icons/v2/timer-disabled-24.svg',
|
|
||||||
$color-gray-05
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.module-timer-notification__icon-label {
|
|
||||||
margin-left: 6px;
|
|
||||||
|
|
||||||
// Didn't seem centered otherwise
|
|
||||||
margin-top: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Module: Universal Timer Notification
|
// Module: Universal Timer Notification
|
||||||
|
|
||||||
|
.module-timer-notification,
|
||||||
.module-universal-timer-notification {
|
.module-universal-timer-notification {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
@ -2433,6 +2378,53 @@ $timer-icons: '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '05',
|
||||||
@include dark-theme {
|
@include dark-theme {
|
||||||
color: $color-gray-05;
|
color: $color-gray-05;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__icon-container {
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
opacity: 0.6;
|
||||||
|
|
||||||
|
@include light-theme {
|
||||||
|
@include color-svg('../images/icons/v2/timer-24.svg', $color-gray-60);
|
||||||
|
}
|
||||||
|
@include dark-theme {
|
||||||
|
@include color-svg('../images/icons/v2/timer-24.svg', $color-gray-05);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--disabled {
|
||||||
|
@include light-theme {
|
||||||
|
@include color-svg(
|
||||||
|
'../images/icons/v2/timer-disabled-24.svg',
|
||||||
|
$color-gray-60
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@include dark-theme {
|
||||||
|
@include color-svg(
|
||||||
|
'../images/icons/v2/timer-disabled-24.svg',
|
||||||
|
$color-gray-05
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__icon-label {
|
||||||
|
margin-left: 4px;
|
||||||
|
|
||||||
|
// Didn't seem centered otherwise
|
||||||
|
margin-top: 1px;
|
||||||
|
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-notification--with-click-handler {
|
.module-notification--with-click-handler {
|
||||||
|
@ -3070,8 +3062,7 @@ button.module-conversation-details__action-button {
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__info,
|
&__info {
|
||||||
&__right-info {
|
|
||||||
@include font-body-2;
|
@include font-body-2;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
|
|
||||||
|
@ -3090,14 +3081,6 @@ button.module-conversation-details__action-button {
|
||||||
min-width: 143px;
|
min-width: 143px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__right-info {
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
@include font-subtitle;
|
|
||||||
|
|
||||||
padding-left: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__actions {
|
&__actions {
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -7005,6 +6988,21 @@ button.module-image__border-overlay:focus {
|
||||||
&__form {
|
&__form {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
|
&__expire-timer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
margin: 0 16px 16px 16px;
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-disappearing-timer-select {
|
||||||
|
width: 144px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
23
stylesheets/components/DisappearingTimerSelect.scss
Normal file
23
stylesheets/components/DisappearingTimerSelect.scss
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
.module-disappearing-timer-select {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&__info {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
margin-top: 4px;
|
||||||
|
padding-left: 14px;
|
||||||
|
|
||||||
|
@include font-subtitle;
|
||||||
|
|
||||||
|
@include light-theme {
|
||||||
|
color: $color-gray-60;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include dark-theme {
|
||||||
|
color: $color-gray-25;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,6 +43,7 @@
|
||||||
@import './components/ConversationHeader.scss';
|
@import './components/ConversationHeader.scss';
|
||||||
@import './components/CustomColorEditor.scss';
|
@import './components/CustomColorEditor.scss';
|
||||||
@import './components/DisappearingTimeDialog.scss';
|
@import './components/DisappearingTimeDialog.scss';
|
||||||
|
@import './components/DisappearingTimerSelect.scss';
|
||||||
@import './components/EditConversationAttributesModal.scss';
|
@import './components/EditConversationAttributesModal.scss';
|
||||||
@import './components/ForwardMessageModal.scss';
|
@import './components/ForwardMessageModal.scss';
|
||||||
@import './components/GradientDial.scss';
|
@import './components/GradientDial.scss';
|
||||||
|
|
|
@ -6,10 +6,10 @@ import { action } from '@storybook/addon-actions';
|
||||||
import { storiesOf } from '@storybook/react';
|
import { storiesOf } from '@storybook/react';
|
||||||
|
|
||||||
import { DisappearingTimeDialog } from './DisappearingTimeDialog';
|
import { DisappearingTimeDialog } from './DisappearingTimeDialog';
|
||||||
import { setup as setupI18n } from '../../../js/modules/i18n';
|
import { setup as setupI18n } from '../../js/modules/i18n';
|
||||||
import enMessages from '../../../_locales/en/messages.json';
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
import { EXPIRE_TIMERS } from '../../test-both/util/expireTimers';
|
import { EXPIRE_TIMERS } from '../test-both/util/expireTimers';
|
||||||
|
|
||||||
const story = storiesOf('Components/DisappearingTimeDialog', module);
|
const story = storiesOf('Components/DisappearingTimeDialog', module);
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
|
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
import { ConfirmationDialog } from '../ConfirmationDialog';
|
import { ConfirmationDialog } from './ConfirmationDialog';
|
||||||
import { Select } from '../Select';
|
import { Select } from './Select';
|
||||||
import { LocalizerType } from '../../types/Util';
|
import { LocalizerType } from '../types/Util';
|
||||||
import { Theme } from '../../util/theme';
|
import { Theme } from '../util/theme';
|
||||||
|
|
||||||
const CSS_MODULE = 'module-disappearing-time-dialog';
|
const CSS_MODULE = 'module-disappearing-time-dialog';
|
||||||
|
|
37
ts/components/DisappearingTimerSelect.stories.tsx
Normal file
37
ts/components/DisappearingTimerSelect.stories.tsx
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { storiesOf } from '@storybook/react';
|
||||||
|
|
||||||
|
import { DisappearingTimerSelect } from './DisappearingTimerSelect';
|
||||||
|
import { setup as setupI18n } from '../../js/modules/i18n';
|
||||||
|
import enMessages from '../../_locales/en/messages.json';
|
||||||
|
|
||||||
|
const story = storiesOf('Components/DisappearingTimerSelect', module);
|
||||||
|
|
||||||
|
const i18n = setupI18n('en', enMessages);
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
initialValue: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const TimerSelectWrap: React.FC<Props> = ({ initialValue }) => {
|
||||||
|
const [value, setValue] = useState(initialValue);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DisappearingTimerSelect
|
||||||
|
i18n={i18n}
|
||||||
|
value={value}
|
||||||
|
onChange={newValue => setValue(newValue)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
story.add('Initial value: 1 day', () => (
|
||||||
|
<TimerSelectWrap initialValue={24 * 3600} />
|
||||||
|
));
|
||||||
|
|
||||||
|
story.add('Initial value 3 days (Custom time)', () => (
|
||||||
|
<TimerSelectWrap initialValue={3 * 24 * 3600} />
|
||||||
|
));
|
106
ts/components/DisappearingTimerSelect.tsx
Normal file
106
ts/components/DisappearingTimerSelect.tsx
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import React, { useState, ReactNode } from 'react';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { LocalizerType } from '../types/Util';
|
||||||
|
import * as expirationTimer from '../util/expirationTimer';
|
||||||
|
import { DisappearingTimeDialog } from './DisappearingTimeDialog';
|
||||||
|
|
||||||
|
import { Select } from './Select';
|
||||||
|
|
||||||
|
const CSS_MODULE = 'module-disappearing-timer-select';
|
||||||
|
|
||||||
|
export type Props = {
|
||||||
|
i18n: LocalizerType;
|
||||||
|
|
||||||
|
value?: number;
|
||||||
|
onChange(value: number): void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DisappearingTimerSelect: React.FC<Props> = (props: Props) => {
|
||||||
|
const { i18n, value = 0, onChange } = props;
|
||||||
|
|
||||||
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
|
|
||||||
|
let expirationTimerOptions: ReadonlyArray<{
|
||||||
|
readonly value: number;
|
||||||
|
readonly text: string;
|
||||||
|
}> = expirationTimer.DEFAULT_DURATIONS_IN_SECONDS.map(seconds => {
|
||||||
|
const text = expirationTimer.format(i18n, seconds, {
|
||||||
|
capitalizeOff: true,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
value: seconds,
|
||||||
|
text,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const isCustomTimeSelected = !expirationTimer.DEFAULT_DURATIONS_SET.has(
|
||||||
|
value
|
||||||
|
);
|
||||||
|
|
||||||
|
const onSelectChange = (newValue: string) => {
|
||||||
|
const intValue = parseInt(newValue, 10);
|
||||||
|
if (intValue === -1) {
|
||||||
|
setIsModalOpen(true);
|
||||||
|
} else {
|
||||||
|
onChange(intValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Custom time...
|
||||||
|
expirationTimerOptions = [
|
||||||
|
...expirationTimerOptions,
|
||||||
|
{
|
||||||
|
value: -1,
|
||||||
|
text: i18n(
|
||||||
|
isCustomTimeSelected
|
||||||
|
? 'selectedCustomDisappearingTimeOption'
|
||||||
|
: 'customDisappearingTimeOption'
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let modalNode: ReactNode = null;
|
||||||
|
if (isModalOpen) {
|
||||||
|
modalNode = (
|
||||||
|
<DisappearingTimeDialog
|
||||||
|
i18n={i18n}
|
||||||
|
initialValue={value}
|
||||||
|
onSubmit={newValue => {
|
||||||
|
setIsModalOpen(false);
|
||||||
|
onChange(newValue);
|
||||||
|
}}
|
||||||
|
onClose={() => setIsModalOpen(false)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let info: ReactNode;
|
||||||
|
if (isCustomTimeSelected) {
|
||||||
|
info = (
|
||||||
|
<div className={`${CSS_MODULE}__info`}>
|
||||||
|
{expirationTimer.format(i18n, value)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={classNames(
|
||||||
|
CSS_MODULE,
|
||||||
|
isCustomTimeSelected ? `${CSS_MODULE}--custom-time` : false
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
onChange={onSelectChange}
|
||||||
|
value={isCustomTimeSelected ? -1 : value}
|
||||||
|
options={expirationTimerOptions}
|
||||||
|
/>
|
||||||
|
{info}
|
||||||
|
{modalNode}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -126,6 +126,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
|
||||||
setComposeSearchTerm: action('setComposeSearchTerm'),
|
setComposeSearchTerm: action('setComposeSearchTerm'),
|
||||||
setComposeGroupAvatar: action('setComposeGroupAvatar'),
|
setComposeGroupAvatar: action('setComposeGroupAvatar'),
|
||||||
setComposeGroupName: action('setComposeGroupName'),
|
setComposeGroupName: action('setComposeGroupName'),
|
||||||
|
setComposeGroupExpireTimer: action('setComposeGroupExpireTimer'),
|
||||||
showArchivedConversations: action('showArchivedConversations'),
|
showArchivedConversations: action('showArchivedConversations'),
|
||||||
showInbox: action('showInbox'),
|
showInbox: action('showInbox'),
|
||||||
startComposing: action('startComposing'),
|
startComposing: action('startComposing'),
|
||||||
|
@ -514,3 +515,53 @@ story.add('Captcha dialog: pending', () => (
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// Set group metadata
|
||||||
|
|
||||||
|
story.add('Group Metadata: No Timer', () => (
|
||||||
|
<LeftPane
|
||||||
|
{...createProps({
|
||||||
|
modeSpecificProps: {
|
||||||
|
mode: LeftPaneMode.SetGroupMetadata,
|
||||||
|
groupAvatar: undefined,
|
||||||
|
groupName: 'Group 1',
|
||||||
|
groupExpireTimer: 0,
|
||||||
|
hasError: false,
|
||||||
|
isCreating: false,
|
||||||
|
selectedContacts: defaultConversations,
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
story.add('Group Metadata: Regular Timer', () => (
|
||||||
|
<LeftPane
|
||||||
|
{...createProps({
|
||||||
|
modeSpecificProps: {
|
||||||
|
mode: LeftPaneMode.SetGroupMetadata,
|
||||||
|
groupAvatar: undefined,
|
||||||
|
groupName: 'Group 1',
|
||||||
|
groupExpireTimer: 24 * 3600,
|
||||||
|
hasError: false,
|
||||||
|
isCreating: false,
|
||||||
|
selectedContacts: defaultConversations,
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
story.add('Group Metadata: Custom Timer', () => (
|
||||||
|
<LeftPane
|
||||||
|
{...createProps({
|
||||||
|
modeSpecificProps: {
|
||||||
|
mode: LeftPaneMode.SetGroupMetadata,
|
||||||
|
groupAvatar: undefined,
|
||||||
|
groupName: 'Group 1',
|
||||||
|
groupExpireTimer: 7 * 3600,
|
||||||
|
hasError: false,
|
||||||
|
isCreating: false,
|
||||||
|
selectedContacts: defaultConversations,
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
|
@ -98,6 +98,7 @@ export type PropsType = {
|
||||||
setComposeSearchTerm: (composeSearchTerm: string) => void;
|
setComposeSearchTerm: (composeSearchTerm: string) => void;
|
||||||
setComposeGroupAvatar: (_: undefined | ArrayBuffer) => void;
|
setComposeGroupAvatar: (_: undefined | ArrayBuffer) => void;
|
||||||
setComposeGroupName: (_: string) => void;
|
setComposeGroupName: (_: string) => void;
|
||||||
|
setComposeGroupExpireTimer: (_: number) => void;
|
||||||
showArchivedConversations: () => void;
|
showArchivedConversations: () => void;
|
||||||
showInbox: () => void;
|
showInbox: () => void;
|
||||||
startComposing: () => void;
|
startComposing: () => void;
|
||||||
|
@ -139,6 +140,7 @@ export const LeftPane: React.FC<PropsType> = ({
|
||||||
setComposeSearchTerm,
|
setComposeSearchTerm,
|
||||||
setComposeGroupAvatar,
|
setComposeGroupAvatar,
|
||||||
setComposeGroupName,
|
setComposeGroupName,
|
||||||
|
setComposeGroupExpireTimer,
|
||||||
showArchivedConversations,
|
showArchivedConversations,
|
||||||
showInbox,
|
showInbox,
|
||||||
startComposing,
|
startComposing,
|
||||||
|
@ -342,6 +344,7 @@ export const LeftPane: React.FC<PropsType> = ({
|
||||||
i18n,
|
i18n,
|
||||||
setComposeGroupAvatar,
|
setComposeGroupAvatar,
|
||||||
setComposeGroupName,
|
setComposeGroupName,
|
||||||
|
setComposeGroupExpireTimer,
|
||||||
onChangeComposeSearchTerm: event => {
|
onChangeComposeSearchTerm: event => {
|
||||||
setComposeSearchTerm(event.target.value);
|
setComposeSearchTerm(event.target.value);
|
||||||
},
|
},
|
||||||
|
|
|
@ -13,7 +13,7 @@ import {
|
||||||
} from 'react-contextmenu';
|
} from 'react-contextmenu';
|
||||||
|
|
||||||
import { Emojify } from './Emojify';
|
import { Emojify } from './Emojify';
|
||||||
import { DisappearingTimeDialog } from './DisappearingTimeDialog';
|
import { DisappearingTimeDialog } from '../DisappearingTimeDialog';
|
||||||
import { Avatar, AvatarSize } from '../Avatar';
|
import { Avatar, AvatarSize } from '../Avatar';
|
||||||
import { InContactsIcon } from '../InContactsIcon';
|
import { InContactsIcon } from '../InContactsIcon';
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@ export type Props = {
|
||||||
expireTimer: number;
|
expireTimer: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CSS_MODULE = 'module-universal-timer-notification';
|
||||||
|
|
||||||
export const UniversalTimerNotification: React.FC<Props> = props => {
|
export const UniversalTimerNotification: React.FC<Props> = props => {
|
||||||
const { i18n, expireTimer } = props;
|
const { i18n, expireTimer } = props;
|
||||||
|
|
||||||
|
@ -18,11 +20,19 @@ export const UniversalTimerNotification: React.FC<Props> = props => {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const timeValue = expirationTimer.format(i18n, expireTimer);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="module-universal-timer-notification">
|
<div className={CSS_MODULE}>
|
||||||
{i18n('UniversalTimerNotification__text', {
|
<div className={`${CSS_MODULE}__icon-container`}>
|
||||||
timeValue: expirationTimer.format(i18n, expireTimer),
|
<div className={`${CSS_MODULE}__icon`} />
|
||||||
})}
|
<div className={`${CSS_MODULE}__icon-label`}>{timeValue}</div>
|
||||||
|
</div>
|
||||||
|
<div className={`${CSS_MODULE}__message`}>
|
||||||
|
{i18n('UniversalTimerNotification__text', {
|
||||||
|
timeValue,
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,15 +5,12 @@ import React, { useState, ReactNode } from 'react';
|
||||||
|
|
||||||
import { ConversationType } from '../../../state/ducks/conversations';
|
import { ConversationType } from '../../../state/ducks/conversations';
|
||||||
import { assert } from '../../../util/assert';
|
import { assert } from '../../../util/assert';
|
||||||
import * as expirationTimer from '../../../util/expirationTimer';
|
|
||||||
|
|
||||||
import { LocalizerType } from '../../../types/Util';
|
import { LocalizerType } from '../../../types/Util';
|
||||||
import { MediaItemType } from '../../LightboxGallery';
|
import { MediaItemType } from '../../LightboxGallery';
|
||||||
import { missingCaseError } from '../../../util/missingCaseError';
|
import { missingCaseError } from '../../../util/missingCaseError';
|
||||||
|
|
||||||
import { Select } from '../../Select';
|
import { DisappearingTimerSelect } from '../../DisappearingTimerSelect';
|
||||||
|
|
||||||
import { DisappearingTimeDialog } from '../DisappearingTimeDialog';
|
|
||||||
|
|
||||||
import { PanelRow } from './PanelRow';
|
import { PanelRow } from './PanelRow';
|
||||||
import { PanelSection } from './PanelSection';
|
import { PanelSection } from './PanelSection';
|
||||||
|
@ -39,7 +36,6 @@ enum ModalState {
|
||||||
EditingGroupDescription,
|
EditingGroupDescription,
|
||||||
EditingGroupTitle,
|
EditingGroupTitle,
|
||||||
AddingGroupMembers,
|
AddingGroupMembers,
|
||||||
CustomDisappearingTimeout,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type StateProps = {
|
export type StateProps = {
|
||||||
|
@ -114,15 +110,6 @@ export const ConversationDetails: React.ComponentType<Props> = ({
|
||||||
setAddGroupMembersRequestState,
|
setAddGroupMembersRequestState,
|
||||||
] = useState<RequestState>(RequestState.Inactive);
|
] = useState<RequestState>(RequestState.Inactive);
|
||||||
|
|
||||||
const updateExpireTimer = (value: string) => {
|
|
||||||
const intValue = parseInt(value, 10);
|
|
||||||
if (intValue === -1) {
|
|
||||||
setModalState(ModalState.CustomDisappearingTimeout);
|
|
||||||
} else {
|
|
||||||
setDisappearingMessages(intValue);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (conversation === undefined) {
|
if (conversation === undefined) {
|
||||||
throw new Error('ConversationDetails rendered without a conversation');
|
throw new Error('ConversationDetails rendered without a conversation');
|
||||||
}
|
}
|
||||||
|
@ -218,55 +205,10 @@ export const ConversationDetails: React.ComponentType<Props> = ({
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case ModalState.CustomDisappearingTimeout:
|
|
||||||
modalNode = (
|
|
||||||
<DisappearingTimeDialog
|
|
||||||
i18n={i18n}
|
|
||||||
initialValue={conversation.expireTimer}
|
|
||||||
onSubmit={value => {
|
|
||||||
setModalState(ModalState.NothingOpen);
|
|
||||||
setDisappearingMessages(value);
|
|
||||||
}}
|
|
||||||
onClose={() => setModalState(ModalState.NothingOpen)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
throw missingCaseError(modalState);
|
throw missingCaseError(modalState);
|
||||||
}
|
}
|
||||||
|
|
||||||
const expireTimer: number = conversation.expireTimer || 0;
|
|
||||||
|
|
||||||
let expirationTimerOptions: ReadonlyArray<{
|
|
||||||
readonly value: number;
|
|
||||||
readonly text: string;
|
|
||||||
}> = expirationTimer.DEFAULT_DURATIONS_IN_SECONDS.map(seconds => {
|
|
||||||
const text = expirationTimer.format(i18n, seconds, {
|
|
||||||
capitalizeOff: true,
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
value: seconds,
|
|
||||||
text,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const isCustomTimeSelected = !expirationTimer.DEFAULT_DURATIONS_SET.has(
|
|
||||||
expireTimer
|
|
||||||
);
|
|
||||||
|
|
||||||
// Custom time...
|
|
||||||
expirationTimerOptions = [
|
|
||||||
...expirationTimerOptions,
|
|
||||||
{
|
|
||||||
value: -1,
|
|
||||||
text: i18n(
|
|
||||||
isCustomTimeSelected
|
|
||||||
? 'selectedCustomDisappearingTimeOption'
|
|
||||||
: 'customDisappearingTimeOption'
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="conversation-details-panel">
|
<div className="conversation-details-panel">
|
||||||
<ConversationDetailsHeader
|
<ConversationDetailsHeader
|
||||||
|
@ -297,17 +239,12 @@ export const ConversationDetails: React.ComponentType<Props> = ({
|
||||||
info={i18n('ConversationDetails--disappearing-messages-info')}
|
info={i18n('ConversationDetails--disappearing-messages-info')}
|
||||||
label={i18n('ConversationDetails--disappearing-messages-label')}
|
label={i18n('ConversationDetails--disappearing-messages-label')}
|
||||||
right={
|
right={
|
||||||
<Select
|
<DisappearingTimerSelect
|
||||||
onChange={updateExpireTimer}
|
i18n={i18n}
|
||||||
value={isCustomTimeSelected ? -1 : expireTimer}
|
value={conversation.expireTimer || 0}
|
||||||
options={expirationTimerOptions}
|
onChange={setDisappearingMessages}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
rightInfo={
|
|
||||||
isCustomTimeSelected
|
|
||||||
? expirationTimer.format(i18n, expireTimer)
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<PanelRow
|
<PanelRow
|
||||||
|
|
|
@ -13,7 +13,6 @@ export type Props = {
|
||||||
label: string | React.ReactNode;
|
label: string | React.ReactNode;
|
||||||
info?: string;
|
info?: string;
|
||||||
right?: string | React.ReactNode;
|
right?: string | React.ReactNode;
|
||||||
rightInfo?: string;
|
|
||||||
actions?: React.ReactNode;
|
actions?: React.ReactNode;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
};
|
};
|
||||||
|
@ -28,7 +27,6 @@ export const PanelRow: React.ComponentType<Props> = ({
|
||||||
label,
|
label,
|
||||||
info,
|
info,
|
||||||
right,
|
right,
|
||||||
rightInfo,
|
|
||||||
actions,
|
actions,
|
||||||
onClick,
|
onClick,
|
||||||
}) => {
|
}) => {
|
||||||
|
@ -39,14 +37,7 @@ export const PanelRow: React.ComponentType<Props> = ({
|
||||||
<div>{label}</div>
|
<div>{label}</div>
|
||||||
{info !== undefined ? <div className={bem('info')}>{info}</div> : null}
|
{info !== undefined ? <div className={bem('info')}>{info}</div> : null}
|
||||||
</div>
|
</div>
|
||||||
{right !== undefined ? (
|
{right !== undefined ? <div className={bem('right')}>{right}</div> : null}
|
||||||
<div className={bem('right')}>
|
|
||||||
{right}
|
|
||||||
{rightInfo !== undefined ? (
|
|
||||||
<div className={bem('right-info')}>{rightInfo}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
{actions !== undefined ? (
|
{actions !== undefined ? (
|
||||||
<div className={alwaysShowActions ? '' : bem('actions')}>{actions}</div>
|
<div className={alwaysShowActions ? '' : bem('actions')}>{actions}</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
|
@ -50,6 +50,7 @@ export abstract class LeftPaneHelper<T> {
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
setComposeGroupAvatar: (_: undefined | ArrayBuffer) => unknown;
|
setComposeGroupAvatar: (_: undefined | ArrayBuffer) => unknown;
|
||||||
setComposeGroupName: (_: string) => unknown;
|
setComposeGroupName: (_: string) => unknown;
|
||||||
|
setComposeGroupExpireTimer: (_: number) => void;
|
||||||
onChangeComposeSearchTerm: (
|
onChangeComposeSearchTerm: (
|
||||||
event: ChangeEvent<HTMLInputElement>
|
event: ChangeEvent<HTMLInputElement>
|
||||||
) => unknown;
|
) => unknown;
|
||||||
|
|
|
@ -6,6 +6,7 @@ import React, { ReactChild } from 'react';
|
||||||
import { LeftPaneHelper } from './LeftPaneHelper';
|
import { LeftPaneHelper } from './LeftPaneHelper';
|
||||||
import { Row, RowType } from '../ConversationList';
|
import { Row, RowType } from '../ConversationList';
|
||||||
import { PropsDataType as ContactListItemPropsType } from '../conversationList/ContactListItem';
|
import { PropsDataType as ContactListItemPropsType } from '../conversationList/ContactListItem';
|
||||||
|
import { DisappearingTimerSelect } from '../DisappearingTimerSelect';
|
||||||
import { LocalizerType } from '../../types/Util';
|
import { LocalizerType } from '../../types/Util';
|
||||||
import { AvatarInput } from '../AvatarInput';
|
import { AvatarInput } from '../AvatarInput';
|
||||||
import { Alert } from '../Alert';
|
import { Alert } from '../Alert';
|
||||||
|
@ -16,6 +17,7 @@ import { GroupTitleInput } from '../GroupTitleInput';
|
||||||
export type LeftPaneSetGroupMetadataPropsType = {
|
export type LeftPaneSetGroupMetadataPropsType = {
|
||||||
groupAvatar: undefined | ArrayBuffer;
|
groupAvatar: undefined | ArrayBuffer;
|
||||||
groupName: string;
|
groupName: string;
|
||||||
|
groupExpireTimer: number;
|
||||||
hasError: boolean;
|
hasError: boolean;
|
||||||
isCreating: boolean;
|
isCreating: boolean;
|
||||||
selectedContacts: ReadonlyArray<ContactListItemPropsType>;
|
selectedContacts: ReadonlyArray<ContactListItemPropsType>;
|
||||||
|
@ -28,6 +30,8 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
|
||||||
|
|
||||||
private readonly groupName: string;
|
private readonly groupName: string;
|
||||||
|
|
||||||
|
private readonly groupExpireTimer: number;
|
||||||
|
|
||||||
private readonly hasError: boolean;
|
private readonly hasError: boolean;
|
||||||
|
|
||||||
private readonly isCreating: boolean;
|
private readonly isCreating: boolean;
|
||||||
|
@ -37,6 +41,7 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
|
||||||
constructor({
|
constructor({
|
||||||
groupAvatar,
|
groupAvatar,
|
||||||
groupName,
|
groupName,
|
||||||
|
groupExpireTimer,
|
||||||
isCreating,
|
isCreating,
|
||||||
hasError,
|
hasError,
|
||||||
selectedContacts,
|
selectedContacts,
|
||||||
|
@ -45,6 +50,7 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
|
||||||
|
|
||||||
this.groupAvatar = groupAvatar;
|
this.groupAvatar = groupAvatar;
|
||||||
this.groupName = groupName;
|
this.groupName = groupName;
|
||||||
|
this.groupExpireTimer = groupExpireTimer;
|
||||||
this.hasError = hasError;
|
this.hasError = hasError;
|
||||||
this.isCreating = isCreating;
|
this.isCreating = isCreating;
|
||||||
this.selectedContacts = selectedContacts;
|
this.selectedContacts = selectedContacts;
|
||||||
|
@ -89,12 +95,14 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
|
||||||
createGroup,
|
createGroup,
|
||||||
i18n,
|
i18n,
|
||||||
setComposeGroupAvatar,
|
setComposeGroupAvatar,
|
||||||
|
setComposeGroupExpireTimer,
|
||||||
setComposeGroupName,
|
setComposeGroupName,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
clearGroupCreationError: () => unknown;
|
clearGroupCreationError: () => unknown;
|
||||||
createGroup: () => unknown;
|
createGroup: () => unknown;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
setComposeGroupAvatar: (_: undefined | ArrayBuffer) => unknown;
|
setComposeGroupAvatar: (_: undefined | ArrayBuffer) => unknown;
|
||||||
|
setComposeGroupExpireTimer: (_: number) => void;
|
||||||
setComposeGroupName: (_: string) => unknown;
|
setComposeGroupName: (_: string) => unknown;
|
||||||
}>): ReactChild {
|
}>): ReactChild {
|
||||||
const disabled = this.isCreating;
|
const disabled = this.isCreating;
|
||||||
|
@ -128,6 +136,17 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper<LeftPaneSetGr
|
||||||
value={this.groupName}
|
value={this.groupName}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<section className="module-left-pane__header__form__expire-timer">
|
||||||
|
<div className="module-left-pane__header__form__expire-timer__label">
|
||||||
|
{i18n('disappearingMessages')}
|
||||||
|
</div>
|
||||||
|
<DisappearingTimerSelect
|
||||||
|
i18n={i18n}
|
||||||
|
value={this.groupExpireTimer}
|
||||||
|
onChange={setComposeGroupExpireTimer}
|
||||||
|
/>
|
||||||
|
</section>
|
||||||
|
|
||||||
{this.hasError && (
|
{this.hasError && (
|
||||||
<Alert
|
<Alert
|
||||||
body={i18n('setGroupMetadata__error-message')}
|
body={i18n('setGroupMetadata__error-message')}
|
||||||
|
|
|
@ -48,7 +48,6 @@ import {
|
||||||
getClientZkGroupCipher,
|
getClientZkGroupCipher,
|
||||||
getClientZkProfileOperations,
|
getClientZkProfileOperations,
|
||||||
} from './util/zkgroup';
|
} from './util/zkgroup';
|
||||||
import * as universalExpireTimer from './util/universalExpireTimer';
|
|
||||||
import {
|
import {
|
||||||
computeHash,
|
computeHash,
|
||||||
deriveMasterKeyFromGroupV1,
|
deriveMasterKeyFromGroupV1,
|
||||||
|
@ -1477,10 +1476,12 @@ export async function fetchMembershipProof({
|
||||||
export async function createGroupV2({
|
export async function createGroupV2({
|
||||||
name,
|
name,
|
||||||
avatar,
|
avatar,
|
||||||
|
expireTimer,
|
||||||
conversationIds,
|
conversationIds,
|
||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
name: string;
|
name: string;
|
||||||
avatar: undefined | ArrayBuffer;
|
avatar: undefined | ArrayBuffer;
|
||||||
|
expireTimer: undefined | number;
|
||||||
conversationIds: Array<string>;
|
conversationIds: Array<string>;
|
||||||
}>): Promise<ConversationModel> {
|
}>): Promise<ConversationModel> {
|
||||||
// Ensure we have the credentials we need before attempting GroupsV2 operations
|
// Ensure we have the credentials we need before attempting GroupsV2 operations
|
||||||
|
@ -1709,7 +1710,6 @@ export async function createGroupV2({
|
||||||
window.MessageController.register(model.id, model);
|
window.MessageController.register(model.id, model);
|
||||||
conversation.trigger('newmessage', model);
|
conversation.trigger('newmessage', model);
|
||||||
|
|
||||||
const expireTimer = universalExpireTimer.get();
|
|
||||||
if (expireTimer) {
|
if (expireTimer) {
|
||||||
await conversation.updateExpirationTimer(expireTimer);
|
await conversation.updateExpirationTimer(expireTimer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import * as groups from '../../groups';
|
||||||
import { calling } from '../../services/calling';
|
import { calling } from '../../services/calling';
|
||||||
import { getOwn } from '../../util/getOwn';
|
import { getOwn } from '../../util/getOwn';
|
||||||
import { assert } from '../../util/assert';
|
import { assert } from '../../util/assert';
|
||||||
|
import * as universalExpireTimer from '../../util/universalExpireTimer';
|
||||||
import { trigger } from '../../shims/events';
|
import { trigger } from '../../shims/events';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -208,9 +209,9 @@ export type PreJoinConversationType = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export enum ComposerStep {
|
export enum ComposerStep {
|
||||||
StartDirectConversation,
|
StartDirectConversation = 'StartDirectConversation',
|
||||||
ChooseGroupMembers,
|
ChooseGroupMembers = 'ChooseGroupMembers',
|
||||||
SetGroupMetadata,
|
SetGroupMetadata = 'SetGroupMetadata',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum OneTimeModalState {
|
export enum OneTimeModalState {
|
||||||
|
@ -222,6 +223,7 @@ export enum OneTimeModalState {
|
||||||
type ComposerGroupCreationState = {
|
type ComposerGroupCreationState = {
|
||||||
groupAvatar: undefined | ArrayBuffer;
|
groupAvatar: undefined | ArrayBuffer;
|
||||||
groupName: string;
|
groupName: string;
|
||||||
|
groupExpireTimer: number;
|
||||||
maximumGroupSizeModalState: OneTimeModalState;
|
maximumGroupSizeModalState: OneTimeModalState;
|
||||||
recommendedGroupSizeModalState: OneTimeModalState;
|
recommendedGroupSizeModalState: OneTimeModalState;
|
||||||
selectedConversationIds: Array<string>;
|
selectedConversationIds: Array<string>;
|
||||||
|
@ -557,6 +559,10 @@ type SetComposeGroupNameActionType = {
|
||||||
type: 'SET_COMPOSE_GROUP_NAME';
|
type: 'SET_COMPOSE_GROUP_NAME';
|
||||||
payload: { groupName: string };
|
payload: { groupName: string };
|
||||||
};
|
};
|
||||||
|
type SetComposeGroupExpireTimerActionType = {
|
||||||
|
type: 'SET_COMPOSE_GROUP_EXPIRE_TIMER';
|
||||||
|
payload: { groupExpireTimer: number };
|
||||||
|
};
|
||||||
type SetComposeSearchTermActionType = {
|
type SetComposeSearchTermActionType = {
|
||||||
type: 'SET_COMPOSE_SEARCH_TERM';
|
type: 'SET_COMPOSE_SEARCH_TERM';
|
||||||
payload: { searchTerm: string };
|
payload: { searchTerm: string };
|
||||||
|
@ -625,6 +631,7 @@ export type ConversationActionType =
|
||||||
| SelectedConversationChangedActionType
|
| SelectedConversationChangedActionType
|
||||||
| SetComposeGroupAvatarActionType
|
| SetComposeGroupAvatarActionType
|
||||||
| SetComposeGroupNameActionType
|
| SetComposeGroupNameActionType
|
||||||
|
| SetComposeGroupExpireTimerActionType
|
||||||
| SetComposeSearchTermActionType
|
| SetComposeSearchTermActionType
|
||||||
| SetConversationHeaderTitleActionType
|
| SetConversationHeaderTitleActionType
|
||||||
| SetIsNearBottomActionType
|
| SetIsNearBottomActionType
|
||||||
|
@ -679,6 +686,7 @@ export const actions = {
|
||||||
selectMessage,
|
selectMessage,
|
||||||
setComposeGroupAvatar,
|
setComposeGroupAvatar,
|
||||||
setComposeGroupName,
|
setComposeGroupName,
|
||||||
|
setComposeGroupExpireTimer,
|
||||||
setComposeSearchTerm,
|
setComposeSearchTerm,
|
||||||
setIsNearBottom,
|
setIsNearBottom,
|
||||||
setLoadCountdownStart,
|
setLoadCountdownStart,
|
||||||
|
@ -903,6 +911,7 @@ function createGroup(): ThunkAction<
|
||||||
const conversation = await groups.createGroupV2({
|
const conversation = await groups.createGroupV2({
|
||||||
name: composer.groupName.trim(),
|
name: composer.groupName.trim(),
|
||||||
avatar: composer.groupAvatar,
|
avatar: composer.groupAvatar,
|
||||||
|
expireTimer: composer.groupExpireTimer,
|
||||||
conversationIds: composer.selectedConversationIds,
|
conversationIds: composer.selectedConversationIds,
|
||||||
});
|
});
|
||||||
dispatch({
|
dispatch({
|
||||||
|
@ -1192,6 +1201,15 @@ function setComposeGroupName(groupName: string): SetComposeGroupNameActionType {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setComposeGroupExpireTimer(
|
||||||
|
groupExpireTimer: number
|
||||||
|
): SetComposeGroupExpireTimerActionType {
|
||||||
|
return {
|
||||||
|
type: 'SET_COMPOSE_GROUP_EXPIRE_TIMER',
|
||||||
|
payload: { groupExpireTimer },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function setComposeSearchTerm(
|
function setComposeSearchTerm(
|
||||||
searchTerm: string
|
searchTerm: string
|
||||||
): SetComposeSearchTermActionType {
|
): SetComposeSearchTermActionType {
|
||||||
|
@ -2346,6 +2364,7 @@ export function reducer(
|
||||||
let maximumGroupSizeModalState: OneTimeModalState;
|
let maximumGroupSizeModalState: OneTimeModalState;
|
||||||
let groupName: string;
|
let groupName: string;
|
||||||
let groupAvatar: undefined | ArrayBuffer;
|
let groupAvatar: undefined | ArrayBuffer;
|
||||||
|
let groupExpireTimer: number;
|
||||||
|
|
||||||
switch (state.composer?.step) {
|
switch (state.composer?.step) {
|
||||||
case ComposerStep.ChooseGroupMembers:
|
case ComposerStep.ChooseGroupMembers:
|
||||||
|
@ -2357,6 +2376,7 @@ export function reducer(
|
||||||
maximumGroupSizeModalState,
|
maximumGroupSizeModalState,
|
||||||
groupName,
|
groupName,
|
||||||
groupAvatar,
|
groupAvatar,
|
||||||
|
groupExpireTimer,
|
||||||
} = state.composer);
|
} = state.composer);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -2364,6 +2384,7 @@ export function reducer(
|
||||||
recommendedGroupSizeModalState = OneTimeModalState.NeverShown;
|
recommendedGroupSizeModalState = OneTimeModalState.NeverShown;
|
||||||
maximumGroupSizeModalState = OneTimeModalState.NeverShown;
|
maximumGroupSizeModalState = OneTimeModalState.NeverShown;
|
||||||
groupName = '';
|
groupName = '';
|
||||||
|
groupExpireTimer = universalExpireTimer.get();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2379,6 +2400,7 @@ export function reducer(
|
||||||
maximumGroupSizeModalState,
|
maximumGroupSizeModalState,
|
||||||
groupName,
|
groupName,
|
||||||
groupAvatar,
|
groupAvatar,
|
||||||
|
groupExpireTimer,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -2398,6 +2420,7 @@ export function reducer(
|
||||||
...pick(composer, [
|
...pick(composer, [
|
||||||
'groupAvatar',
|
'groupAvatar',
|
||||||
'groupName',
|
'groupName',
|
||||||
|
'groupExpireTimer',
|
||||||
'maximumGroupSizeModalState',
|
'maximumGroupSizeModalState',
|
||||||
'recommendedGroupSizeModalState',
|
'recommendedGroupSizeModalState',
|
||||||
'selectedConversationIds',
|
'selectedConversationIds',
|
||||||
|
@ -2453,6 +2476,25 @@ export function reducer(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action.type === 'SET_COMPOSE_GROUP_EXPIRE_TIMER') {
|
||||||
|
const { composer } = state;
|
||||||
|
|
||||||
|
switch (composer?.step) {
|
||||||
|
case ComposerStep.ChooseGroupMembers:
|
||||||
|
case ComposerStep.SetGroupMetadata:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
composer: {
|
||||||
|
...composer,
|
||||||
|
groupExpireTimer: action.payload.groupExpireTimer,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
assert(false, 'Setting compose group name at this step is a no-op');
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (action.type === 'SET_COMPOSE_SEARCH_TERM') {
|
if (action.type === 'SET_COMPOSE_SEARCH_TERM') {
|
||||||
const { composer } = state;
|
const { composer } = state;
|
||||||
if (!composer) {
|
if (!composer) {
|
||||||
|
|
|
@ -518,6 +518,7 @@ const getGroupCreationComposerState = createSelector(
|
||||||
): {
|
): {
|
||||||
groupName: string;
|
groupName: string;
|
||||||
groupAvatar: undefined | ArrayBuffer;
|
groupAvatar: undefined | ArrayBuffer;
|
||||||
|
groupExpireTimer: number;
|
||||||
selectedConversationIds: Array<string>;
|
selectedConversationIds: Array<string>;
|
||||||
} => {
|
} => {
|
||||||
switch (composerState?.step) {
|
switch (composerState?.step) {
|
||||||
|
@ -532,6 +533,7 @@ const getGroupCreationComposerState = createSelector(
|
||||||
return {
|
return {
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
selectedConversationIds: [],
|
selectedConversationIds: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -548,6 +550,11 @@ export const getComposeGroupName = createSelector(
|
||||||
(composerState): string => composerState.groupName
|
(composerState): string => composerState.groupName
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const getComposeGroupExpireTimer = createSelector(
|
||||||
|
getGroupCreationComposerState,
|
||||||
|
(composerState): number => composerState.groupExpireTimer
|
||||||
|
);
|
||||||
|
|
||||||
export const getComposeSelectedContacts = createSelector(
|
export const getComposeSelectedContacts = createSelector(
|
||||||
getConversationLookup,
|
getConversationLookup,
|
||||||
getGroupCreationComposerState,
|
getGroupCreationComposerState,
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
getFilteredComposeGroups,
|
getFilteredComposeGroups,
|
||||||
getComposeGroupAvatar,
|
getComposeGroupAvatar,
|
||||||
getComposeGroupName,
|
getComposeGroupName,
|
||||||
|
getComposeGroupExpireTimer,
|
||||||
getComposeSelectedContacts,
|
getComposeSelectedContacts,
|
||||||
getComposerConversationSearchTerm,
|
getComposerConversationSearchTerm,
|
||||||
getComposerStep,
|
getComposerStep,
|
||||||
|
@ -129,6 +130,7 @@ const getModeSpecificProps = (
|
||||||
mode: LeftPaneMode.SetGroupMetadata,
|
mode: LeftPaneMode.SetGroupMetadata,
|
||||||
groupAvatar: getComposeGroupAvatar(state),
|
groupAvatar: getComposeGroupAvatar(state),
|
||||||
groupName: getComposeGroupName(state),
|
groupName: getComposeGroupName(state),
|
||||||
|
groupExpireTimer: getComposeGroupExpireTimer(state),
|
||||||
hasError: hasGroupCreationError(state),
|
hasError: hasGroupCreationError(state),
|
||||||
isCreating: isCreatingGroup(state),
|
isCreating: isCreatingGroup(state),
|
||||||
selectedContacts: getComposeSelectedContacts(state),
|
selectedContacts: getComposeSelectedContacts(state),
|
||||||
|
|
|
@ -325,6 +325,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -346,6 +347,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
},
|
},
|
||||||
|
@ -388,6 +390,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false as const,
|
isCreating: false as const,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
},
|
},
|
||||||
|
@ -409,6 +412,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false as const,
|
isCreating: false as const,
|
||||||
hasError: true as const,
|
hasError: true as const,
|
||||||
},
|
},
|
||||||
|
@ -449,6 +453,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false as const,
|
isCreating: false as const,
|
||||||
hasError: true as const,
|
hasError: true as const,
|
||||||
},
|
},
|
||||||
|
@ -470,6 +475,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: true as const,
|
isCreating: true as const,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
},
|
},
|
||||||
|
@ -1080,6 +1086,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
|
@ -1135,6 +1142,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
cantAddContactIdForModal: undefined,
|
cantAddContactIdForModal: undefined,
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
|
@ -1159,6 +1167,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
cantAddContactIdForModal: 'abc123',
|
cantAddContactIdForModal: 'abc123',
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
|
@ -1596,6 +1605,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
cantAddContactIdForModal: undefined,
|
cantAddContactIdForModal: undefined,
|
||||||
searchTerm: 'to be cleared',
|
searchTerm: 'to be cleared',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
maximumGroupSizeModalState: OneTimeModalState.Showing,
|
maximumGroupSizeModalState: OneTimeModalState.Showing,
|
||||||
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
|
@ -1621,6 +1631,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
cantAddContactIdForModal: undefined,
|
cantAddContactIdForModal: undefined,
|
||||||
searchTerm: 'to be cleared',
|
searchTerm: 'to be cleared',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
recommendedGroupSizeModalState: OneTimeModalState.Showing,
|
recommendedGroupSizeModalState: OneTimeModalState.Showing,
|
||||||
|
@ -1650,6 +1661,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
},
|
},
|
||||||
|
@ -1671,6 +1683,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: new Uint8Array([1, 2, 3]).buffer,
|
groupAvatar: new Uint8Array([1, 2, 3]).buffer,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
},
|
},
|
||||||
|
@ -1697,6 +1710,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: 'foo bar',
|
groupName: 'foo bar',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
},
|
},
|
||||||
|
@ -1730,6 +1744,7 @@ describe('both/state/selectors/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: 'foo bar',
|
groupName: 'foo bar',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
},
|
},
|
||||||
|
|
|
@ -454,6 +454,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
cantAddContactIdForModal: undefined,
|
cantAddContactIdForModal: undefined,
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
|
@ -482,6 +483,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false as const,
|
isCreating: false as const,
|
||||||
hasError: true as const,
|
hasError: true as const,
|
||||||
},
|
},
|
||||||
|
@ -517,6 +519,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
cantAddContactIdForModal: 'abc123',
|
cantAddContactIdForModal: 'abc123',
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
|
@ -567,6 +570,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
cantAddContactIdForModal: 'abc123',
|
cantAddContactIdForModal: 'abc123',
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
maximumGroupSizeModalState: OneTimeModalState.Showing,
|
maximumGroupSizeModalState: OneTimeModalState.Showing,
|
||||||
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
|
@ -592,6 +596,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
cantAddContactIdForModal: 'abc123',
|
cantAddContactIdForModal: 'abc123',
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
|
@ -612,6 +617,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
cantAddContactIdForModal: 'abc123',
|
cantAddContactIdForModal: 'abc123',
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
maximumGroupSizeModalState: OneTimeModalState.Shown,
|
maximumGroupSizeModalState: OneTimeModalState.Shown,
|
||||||
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
|
@ -634,6 +640,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
cantAddContactIdForModal: 'abc123',
|
cantAddContactIdForModal: 'abc123',
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
recommendedGroupSizeModalState: OneTimeModalState.Showing,
|
recommendedGroupSizeModalState: OneTimeModalState.Showing,
|
||||||
|
@ -659,6 +666,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
cantAddContactIdForModal: 'abc123',
|
cantAddContactIdForModal: 'abc123',
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
|
@ -679,6 +687,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
cantAddContactIdForModal: 'abc123',
|
cantAddContactIdForModal: 'abc123',
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
recommendedGroupSizeModalState: OneTimeModalState.Shown,
|
recommendedGroupSizeModalState: OneTimeModalState.Shown,
|
||||||
|
@ -703,6 +712,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: 'Foo Bar Group',
|
groupName: 'Foo Bar Group',
|
||||||
groupAvatar: new Uint8Array([1, 2, 3]).buffer,
|
groupAvatar: new Uint8Array([1, 2, 3]).buffer,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false as const,
|
isCreating: false as const,
|
||||||
hasError: true as const,
|
hasError: true as const,
|
||||||
},
|
},
|
||||||
|
@ -748,6 +758,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
sinon.assert.calledWith(createGroupStub, {
|
sinon.assert.calledWith(createGroupStub, {
|
||||||
name: 'Foo Bar Group',
|
name: 'Foo Bar Group',
|
||||||
avatar: new Uint8Array([1, 2, 3]).buffer,
|
avatar: new Uint8Array([1, 2, 3]).buffer,
|
||||||
|
expireTimer: 0,
|
||||||
conversationIds: ['abc123'],
|
conversationIds: ['abc123'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1205,6 +1216,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: 'foo',
|
groupName: 'foo',
|
||||||
groupAvatar: new ArrayBuffer(2),
|
groupAvatar: new ArrayBuffer(2),
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false as const,
|
isCreating: false as const,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
},
|
},
|
||||||
|
@ -1230,6 +1242,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: 'foo',
|
groupName: 'foo',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false as const,
|
isCreating: false as const,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
},
|
},
|
||||||
|
@ -1255,6 +1268,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false as const,
|
isCreating: false as const,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
},
|
},
|
||||||
|
@ -1424,6 +1438,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
cantAddContactIdForModal: undefined,
|
cantAddContactIdForModal: undefined,
|
||||||
searchTerm: 'to be cleared',
|
searchTerm: 'to be cleared',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
recommendedGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
|
@ -1451,6 +1466,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
},
|
},
|
||||||
|
@ -1515,6 +1531,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1530,6 +1547,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const action = showChooseGroupMembers();
|
const action = showChooseGroupMembers();
|
||||||
|
@ -1549,6 +1567,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: 'Foo Bar Group',
|
groupName: 'Foo Bar Group',
|
||||||
groupAvatar: new Uint8Array([4, 2]).buffer,
|
groupAvatar: new Uint8Array([4, 2]).buffer,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
},
|
},
|
||||||
|
@ -1566,6 +1585,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: 'Foo Bar Group',
|
groupName: 'Foo Bar Group',
|
||||||
groupAvatar: new Uint8Array([4, 2]).buffer,
|
groupAvatar: new Uint8Array([4, 2]).buffer,
|
||||||
|
groupExpireTimer: 0,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1584,6 +1604,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1605,6 +1626,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1622,6 +1644,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const action = startSettingGroupMetadata();
|
const action = startSettingGroupMetadata();
|
||||||
|
@ -1634,6 +1657,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
hasError: false,
|
hasError: false,
|
||||||
});
|
});
|
||||||
|
@ -1651,6 +1675,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: 'Foo Bar Group',
|
groupName: 'Foo Bar Group',
|
||||||
groupAvatar: new Uint8Array([6, 9]).buffer,
|
groupAvatar: new Uint8Array([6, 9]).buffer,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const action = startSettingGroupMetadata();
|
const action = startSettingGroupMetadata();
|
||||||
|
@ -1663,6 +1688,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: 'Foo Bar Group',
|
groupName: 'Foo Bar Group',
|
||||||
groupAvatar: new Uint8Array([6, 9]).buffer,
|
groupAvatar: new Uint8Array([6, 9]).buffer,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
});
|
});
|
||||||
|
@ -1678,6 +1704,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: 'Foo Bar Group',
|
groupName: 'Foo Bar Group',
|
||||||
groupAvatar: new Uint8Array([4, 2]).buffer,
|
groupAvatar: new Uint8Array([4, 2]).buffer,
|
||||||
|
groupExpireTimer: 0,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
hasError: false as const,
|
hasError: false as const,
|
||||||
},
|
},
|
||||||
|
@ -1731,6 +1758,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const one = reducer(zero, getAction('abc', zero));
|
const one = reducer(zero, getAction('abc', zero));
|
||||||
|
@ -1745,6 +1773,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1760,6 +1789,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const action = getAction('abc', state);
|
const action = getAction('abc', state);
|
||||||
|
@ -1774,6 +1804,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1792,6 +1823,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const action = getAction(newUuid, state);
|
const action = getAction(newUuid, state);
|
||||||
|
@ -1806,6 +1838,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1824,6 +1857,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const action = getAction(newUuid, state);
|
const action = getAction(newUuid, state);
|
||||||
|
@ -1838,6 +1872,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1858,6 +1893,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const action = getAction(uuid(), state);
|
const action = getAction(uuid(), state);
|
||||||
|
@ -1881,6 +1917,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const action = getAction(newUuid, state);
|
const action = getAction(newUuid, state);
|
||||||
|
@ -1895,6 +1932,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.Showing,
|
maximumGroupSizeModalState: OneTimeModalState.Showing,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1913,6 +1951,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.Shown,
|
maximumGroupSizeModalState: OneTimeModalState.Shown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const action = getAction(newUuid, state);
|
const action = getAction(newUuid, state);
|
||||||
|
@ -1927,6 +1966,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.Shown,
|
maximumGroupSizeModalState: OneTimeModalState.Shown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1942,6 +1982,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const action = getAction(uuid(), state);
|
const action = getAction(uuid(), state);
|
||||||
|
@ -1969,6 +2010,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const action = getAction(uuid(), state);
|
const action = getAction(uuid(), state);
|
||||||
|
@ -1995,6 +2037,7 @@ describe('both/state/ducks/conversations', () => {
|
||||||
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
maximumGroupSizeModalState: OneTimeModalState.NeverShown,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const action = getAction(uuid(), state);
|
const action = getAction(uuid(), state);
|
||||||
|
|
|
@ -14,6 +14,7 @@ describe('LeftPaneSetGroupMetadataHelper', () => {
|
||||||
const showChooseGroupMembers = sinon.fake();
|
const showChooseGroupMembers = sinon.fake();
|
||||||
const helper = new LeftPaneSetGroupMetadataHelper({
|
const helper = new LeftPaneSetGroupMetadataHelper({
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
hasError: false,
|
hasError: false,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
|
@ -29,6 +30,7 @@ describe('LeftPaneSetGroupMetadataHelper', () => {
|
||||||
it("returns undefined (i.e., you can't go back) if a request is active", () => {
|
it("returns undefined (i.e., you can't go back) if a request is active", () => {
|
||||||
const helper = new LeftPaneSetGroupMetadataHelper({
|
const helper = new LeftPaneSetGroupMetadataHelper({
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: 'Foo Bar',
|
groupName: 'Foo Bar',
|
||||||
hasError: false,
|
hasError: false,
|
||||||
isCreating: true,
|
isCreating: true,
|
||||||
|
@ -46,6 +48,7 @@ describe('LeftPaneSetGroupMetadataHelper', () => {
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
new LeftPaneSetGroupMetadataHelper({
|
new LeftPaneSetGroupMetadataHelper({
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
hasError: false,
|
hasError: false,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
|
@ -59,6 +62,7 @@ describe('LeftPaneSetGroupMetadataHelper', () => {
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
new LeftPaneSetGroupMetadataHelper({
|
new LeftPaneSetGroupMetadataHelper({
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
hasError: false,
|
hasError: false,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
|
@ -77,6 +81,7 @@ describe('LeftPaneSetGroupMetadataHelper', () => {
|
||||||
assert.isUndefined(
|
assert.isUndefined(
|
||||||
new LeftPaneSetGroupMetadataHelper({
|
new LeftPaneSetGroupMetadataHelper({
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
hasError: false,
|
hasError: false,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
|
@ -92,6 +97,7 @@ describe('LeftPaneSetGroupMetadataHelper', () => {
|
||||||
];
|
];
|
||||||
const helper = new LeftPaneSetGroupMetadataHelper({
|
const helper = new LeftPaneSetGroupMetadataHelper({
|
||||||
groupAvatar: undefined,
|
groupAvatar: undefined,
|
||||||
|
groupExpireTimer: 0,
|
||||||
groupName: '',
|
groupName: '',
|
||||||
hasError: false,
|
hasError: false,
|
||||||
isCreating: false,
|
isCreating: false,
|
||||||
|
|
2
ts/window.d.ts
vendored
2
ts/window.d.ts
vendored
|
@ -107,7 +107,7 @@ import { MessageDetail } from './components/conversation/MessageDetail';
|
||||||
import { ProgressModal } from './components/ProgressModal';
|
import { ProgressModal } from './components/ProgressModal';
|
||||||
import { Quote } from './components/conversation/Quote';
|
import { Quote } from './components/conversation/Quote';
|
||||||
import { StagedLinkPreview } from './components/conversation/StagedLinkPreview';
|
import { StagedLinkPreview } from './components/conversation/StagedLinkPreview';
|
||||||
import { DisappearingTimeDialog } from './components/conversation/DisappearingTimeDialog';
|
import { DisappearingTimeDialog } from './components/DisappearingTimeDialog';
|
||||||
import { MIMEType } from './types/MIME';
|
import { MIMEType } from './types/MIME';
|
||||||
import { AttachmentType } from './types/Attachment';
|
import { AttachmentType } from './types/Attachment';
|
||||||
import { ElectronLocaleType } from './util/mapToSupportLocale';
|
import { ElectronLocaleType } from './util/mapToSupportLocale';
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue