diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 4212f5a63..cc084abd8 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1805,7 +1805,7 @@ }, "disappearingMessages": { "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": { "message": "Disappearing messages disabled", diff --git a/js/modules/signal.js b/js/modules/signal.js index e23ecdfd8..15753157a 100644 --- a/js/modules/signal.js +++ b/js/modules/signal.js @@ -56,7 +56,7 @@ const { } = require('../../ts/components/conversation/StagedLinkPreview'); const { DisappearingTimeDialog, -} = require('../../ts/components/conversation/DisappearingTimeDialog'); +} = require('../../ts/components/DisappearingTimeDialog'); // State const { createTimeline } = require('../../ts/state/roots/createTimeline'); diff --git a/stylesheets/_modules.scss b/stylesheets/_modules.scss index 1bb7ba113..a9d513fa9 100644 --- a/stylesheets/_modules.scss +++ b/stylesheets/_modules.scss @@ -2366,64 +2366,9 @@ $timer-icons: '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '05', } // 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-timer-notification, .module-universal-timer-notification { text-align: center; @@ -2433,6 +2378,53 @@ $timer-icons: '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '05', @include dark-theme { 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 { @@ -3070,8 +3062,7 @@ button.module-conversation-details__action-button { margin-right: 12px; } - &__info, - &__right-info { + &__info { @include font-body-2; margin-top: 4px; @@ -3090,14 +3081,6 @@ button.module-conversation-details__action-button { min-width: 143px; } - &__right-info { - position: absolute; - - @include font-subtitle; - - padding-left: 14px; - } - &__actions { margin-left: 12px; overflow: hidden; @@ -7005,6 +6988,21 @@ button.module-image__border-overlay:focus { &__form { display: flex; 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; + } + } } } diff --git a/stylesheets/components/DisappearingTimerSelect.scss b/stylesheets/components/DisappearingTimerSelect.scss new file mode 100644 index 000000000..df4c0c027 --- /dev/null +++ b/stylesheets/components/DisappearingTimerSelect.scss @@ -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; + } + } +} diff --git a/stylesheets/manifest.scss b/stylesheets/manifest.scss index dbce8e8ca..7a4d0758c 100644 --- a/stylesheets/manifest.scss +++ b/stylesheets/manifest.scss @@ -43,6 +43,7 @@ @import './components/ConversationHeader.scss'; @import './components/CustomColorEditor.scss'; @import './components/DisappearingTimeDialog.scss'; +@import './components/DisappearingTimerSelect.scss'; @import './components/EditConversationAttributesModal.scss'; @import './components/ForwardMessageModal.scss'; @import './components/GradientDial.scss'; diff --git a/ts/components/conversation/DisappearingTimeDialog.stories.tsx b/ts/components/DisappearingTimeDialog.stories.tsx similarity index 77% rename from ts/components/conversation/DisappearingTimeDialog.stories.tsx rename to ts/components/DisappearingTimeDialog.stories.tsx index fa8df0eef..48e2a537d 100644 --- a/ts/components/conversation/DisappearingTimeDialog.stories.tsx +++ b/ts/components/DisappearingTimeDialog.stories.tsx @@ -6,10 +6,10 @@ import { action } from '@storybook/addon-actions'; import { storiesOf } from '@storybook/react'; import { DisappearingTimeDialog } from './DisappearingTimeDialog'; -import { setup as setupI18n } from '../../../js/modules/i18n'; -import enMessages from '../../../_locales/en/messages.json'; +import { setup as setupI18n } from '../../js/modules/i18n'; +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); diff --git a/ts/components/conversation/DisappearingTimeDialog.tsx b/ts/components/DisappearingTimeDialog.tsx similarity index 94% rename from ts/components/conversation/DisappearingTimeDialog.tsx rename to ts/components/DisappearingTimeDialog.tsx index 6ebeb5134..d92e4fb19 100644 --- a/ts/components/conversation/DisappearingTimeDialog.tsx +++ b/ts/components/DisappearingTimeDialog.tsx @@ -4,10 +4,10 @@ import React, { useState } from 'react'; -import { ConfirmationDialog } from '../ConfirmationDialog'; -import { Select } from '../Select'; -import { LocalizerType } from '../../types/Util'; -import { Theme } from '../../util/theme'; +import { ConfirmationDialog } from './ConfirmationDialog'; +import { Select } from './Select'; +import { LocalizerType } from '../types/Util'; +import { Theme } from '../util/theme'; const CSS_MODULE = 'module-disappearing-time-dialog'; diff --git a/ts/components/DisappearingTimerSelect.stories.tsx b/ts/components/DisappearingTimerSelect.stories.tsx new file mode 100644 index 000000000..72a6e2673 --- /dev/null +++ b/ts/components/DisappearingTimerSelect.stories.tsx @@ -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 = ({ initialValue }) => { + const [value, setValue] = useState(initialValue); + + return ( + setValue(newValue)} + /> + ); +}; + +story.add('Initial value: 1 day', () => ( + +)); + +story.add('Initial value 3 days (Custom time)', () => ( + +)); diff --git a/ts/components/DisappearingTimerSelect.tsx b/ts/components/DisappearingTimerSelect.tsx new file mode 100644 index 000000000..a4d4cba7b --- /dev/null +++ b/ts/components/DisappearingTimerSelect.tsx @@ -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) => { + 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 = ( + { + setIsModalOpen(false); + onChange(newValue); + }} + onClose={() => setIsModalOpen(false)} + /> + ); + } + + let info: ReactNode; + if (isCustomTimeSelected) { + info = ( +
+ {expirationTimer.format(i18n, value)} +
+ ); + } + + return ( +
+ } - rightInfo={ - isCustomTimeSelected - ? expirationTimer.format(i18n, expireTimer) - : undefined - } /> ) : null} void; }; @@ -28,7 +27,6 @@ export const PanelRow: React.ComponentType = ({ label, info, right, - rightInfo, actions, onClick, }) => { @@ -39,14 +37,7 @@ export const PanelRow: React.ComponentType = ({
{label}
{info !== undefined ?
{info}
: null}
- {right !== undefined ? ( -
- {right} - {rightInfo !== undefined ? ( -
{rightInfo}
- ) : null} -
- ) : null} + {right !== undefined ?
{right}
: null} {actions !== undefined ? (
{actions}
) : null} diff --git a/ts/components/leftPane/LeftPaneHelper.tsx b/ts/components/leftPane/LeftPaneHelper.tsx index d4887e7f5..ae12e8599 100644 --- a/ts/components/leftPane/LeftPaneHelper.tsx +++ b/ts/components/leftPane/LeftPaneHelper.tsx @@ -50,6 +50,7 @@ export abstract class LeftPaneHelper { i18n: LocalizerType; setComposeGroupAvatar: (_: undefined | ArrayBuffer) => unknown; setComposeGroupName: (_: string) => unknown; + setComposeGroupExpireTimer: (_: number) => void; onChangeComposeSearchTerm: ( event: ChangeEvent ) => unknown; diff --git a/ts/components/leftPane/LeftPaneSetGroupMetadataHelper.tsx b/ts/components/leftPane/LeftPaneSetGroupMetadataHelper.tsx index 9d253f52b..5523ee2eb 100644 --- a/ts/components/leftPane/LeftPaneSetGroupMetadataHelper.tsx +++ b/ts/components/leftPane/LeftPaneSetGroupMetadataHelper.tsx @@ -6,6 +6,7 @@ import React, { ReactChild } from 'react'; import { LeftPaneHelper } from './LeftPaneHelper'; import { Row, RowType } from '../ConversationList'; import { PropsDataType as ContactListItemPropsType } from '../conversationList/ContactListItem'; +import { DisappearingTimerSelect } from '../DisappearingTimerSelect'; import { LocalizerType } from '../../types/Util'; import { AvatarInput } from '../AvatarInput'; import { Alert } from '../Alert'; @@ -16,6 +17,7 @@ import { GroupTitleInput } from '../GroupTitleInput'; export type LeftPaneSetGroupMetadataPropsType = { groupAvatar: undefined | ArrayBuffer; groupName: string; + groupExpireTimer: number; hasError: boolean; isCreating: boolean; selectedContacts: ReadonlyArray; @@ -28,6 +30,8 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper unknown; createGroup: () => unknown; i18n: LocalizerType; setComposeGroupAvatar: (_: undefined | ArrayBuffer) => unknown; + setComposeGroupExpireTimer: (_: number) => void; setComposeGroupName: (_: string) => unknown; }>): ReactChild { const disabled = this.isCreating; @@ -128,6 +136,17 @@ export class LeftPaneSetGroupMetadataHelper extends LeftPaneHelper +
+
+ {i18n('disappearingMessages')} +
+ +
+ {this.hasError && ( ; }>): Promise { // 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); conversation.trigger('newmessage', model); - const expireTimer = universalExpireTimer.get(); if (expireTimer) { await conversation.updateExpirationTimer(expireTimer); } diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index ede5595da..e24185119 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -20,6 +20,7 @@ import * as groups from '../../groups'; import { calling } from '../../services/calling'; import { getOwn } from '../../util/getOwn'; import { assert } from '../../util/assert'; +import * as universalExpireTimer from '../../util/universalExpireTimer'; import { trigger } from '../../shims/events'; import { @@ -208,9 +209,9 @@ export type PreJoinConversationType = { }; export enum ComposerStep { - StartDirectConversation, - ChooseGroupMembers, - SetGroupMetadata, + StartDirectConversation = 'StartDirectConversation', + ChooseGroupMembers = 'ChooseGroupMembers', + SetGroupMetadata = 'SetGroupMetadata', } export enum OneTimeModalState { @@ -222,6 +223,7 @@ export enum OneTimeModalState { type ComposerGroupCreationState = { groupAvatar: undefined | ArrayBuffer; groupName: string; + groupExpireTimer: number; maximumGroupSizeModalState: OneTimeModalState; recommendedGroupSizeModalState: OneTimeModalState; selectedConversationIds: Array; @@ -557,6 +559,10 @@ type SetComposeGroupNameActionType = { type: 'SET_COMPOSE_GROUP_NAME'; payload: { groupName: string }; }; +type SetComposeGroupExpireTimerActionType = { + type: 'SET_COMPOSE_GROUP_EXPIRE_TIMER'; + payload: { groupExpireTimer: number }; +}; type SetComposeSearchTermActionType = { type: 'SET_COMPOSE_SEARCH_TERM'; payload: { searchTerm: string }; @@ -625,6 +631,7 @@ export type ConversationActionType = | SelectedConversationChangedActionType | SetComposeGroupAvatarActionType | SetComposeGroupNameActionType + | SetComposeGroupExpireTimerActionType | SetComposeSearchTermActionType | SetConversationHeaderTitleActionType | SetIsNearBottomActionType @@ -679,6 +686,7 @@ export const actions = { selectMessage, setComposeGroupAvatar, setComposeGroupName, + setComposeGroupExpireTimer, setComposeSearchTerm, setIsNearBottom, setLoadCountdownStart, @@ -903,6 +911,7 @@ function createGroup(): ThunkAction< const conversation = await groups.createGroupV2({ name: composer.groupName.trim(), avatar: composer.groupAvatar, + expireTimer: composer.groupExpireTimer, conversationIds: composer.selectedConversationIds, }); 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( searchTerm: string ): SetComposeSearchTermActionType { @@ -2346,6 +2364,7 @@ export function reducer( let maximumGroupSizeModalState: OneTimeModalState; let groupName: string; let groupAvatar: undefined | ArrayBuffer; + let groupExpireTimer: number; switch (state.composer?.step) { case ComposerStep.ChooseGroupMembers: @@ -2357,6 +2376,7 @@ export function reducer( maximumGroupSizeModalState, groupName, groupAvatar, + groupExpireTimer, } = state.composer); break; default: @@ -2364,6 +2384,7 @@ export function reducer( recommendedGroupSizeModalState = OneTimeModalState.NeverShown; maximumGroupSizeModalState = OneTimeModalState.NeverShown; groupName = ''; + groupExpireTimer = universalExpireTimer.get(); break; } @@ -2379,6 +2400,7 @@ export function reducer( maximumGroupSizeModalState, groupName, groupAvatar, + groupExpireTimer, }, }; } @@ -2398,6 +2420,7 @@ export function reducer( ...pick(composer, [ 'groupAvatar', 'groupName', + 'groupExpireTimer', 'maximumGroupSizeModalState', 'recommendedGroupSizeModalState', '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') { const { composer } = state; if (!composer) { diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index cd390f550..16871388a 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -518,6 +518,7 @@ const getGroupCreationComposerState = createSelector( ): { groupName: string; groupAvatar: undefined | ArrayBuffer; + groupExpireTimer: number; selectedConversationIds: Array; } => { switch (composerState?.step) { @@ -532,6 +533,7 @@ const getGroupCreationComposerState = createSelector( return { groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, selectedConversationIds: [], }; } @@ -548,6 +550,11 @@ export const getComposeGroupName = createSelector( (composerState): string => composerState.groupName ); +export const getComposeGroupExpireTimer = createSelector( + getGroupCreationComposerState, + (composerState): number => composerState.groupExpireTimer +); + export const getComposeSelectedContacts = createSelector( getConversationLookup, getGroupCreationComposerState, diff --git a/ts/state/smart/LeftPane.tsx b/ts/state/smart/LeftPane.tsx index 2f7bac723..c3a75ead4 100644 --- a/ts/state/smart/LeftPane.tsx +++ b/ts/state/smart/LeftPane.tsx @@ -23,6 +23,7 @@ import { getFilteredComposeGroups, getComposeGroupAvatar, getComposeGroupName, + getComposeGroupExpireTimer, getComposeSelectedContacts, getComposerConversationSearchTerm, getComposerStep, @@ -129,6 +130,7 @@ const getModeSpecificProps = ( mode: LeftPaneMode.SetGroupMetadata, groupAvatar: getComposeGroupAvatar(state), groupName: getComposeGroupName(state), + groupExpireTimer: getComposeGroupExpireTimer(state), hasError: hasGroupCreationError(state), isCreating: isCreatingGroup(state), selectedContacts: getComposeSelectedContacts(state), diff --git a/ts/test-both/state/selectors/conversations_test.ts b/ts/test-both/state/selectors/conversations_test.ts index 548fc00f7..b5b8d1203 100644 --- a/ts/test-both/state/selectors/conversations_test.ts +++ b/ts/test-both/state/selectors/conversations_test.ts @@ -325,6 +325,7 @@ describe('both/state/selectors/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }, }; @@ -346,6 +347,7 @@ describe('both/state/selectors/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, isCreating: false, hasError: false as const, }, @@ -388,6 +390,7 @@ describe('both/state/selectors/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, isCreating: false as const, hasError: false as const, }, @@ -409,6 +412,7 @@ describe('both/state/selectors/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, isCreating: false as const, hasError: true as const, }, @@ -449,6 +453,7 @@ describe('both/state/selectors/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, isCreating: false as const, hasError: true as const, }, @@ -470,6 +475,7 @@ describe('both/state/selectors/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, isCreating: true as const, hasError: false as const, }, @@ -1080,6 +1086,7 @@ describe('both/state/selectors/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }, user: { @@ -1135,6 +1142,7 @@ describe('both/state/selectors/conversations', () => { cantAddContactIdForModal: undefined, searchTerm: '', groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', maximumGroupSizeModalState: OneTimeModalState.NeverShown, recommendedGroupSizeModalState: OneTimeModalState.NeverShown, @@ -1159,6 +1167,7 @@ describe('both/state/selectors/conversations', () => { cantAddContactIdForModal: 'abc123', searchTerm: '', groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', maximumGroupSizeModalState: OneTimeModalState.NeverShown, recommendedGroupSizeModalState: OneTimeModalState.NeverShown, @@ -1596,6 +1605,7 @@ describe('both/state/selectors/conversations', () => { cantAddContactIdForModal: undefined, searchTerm: 'to be cleared', groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', maximumGroupSizeModalState: OneTimeModalState.Showing, recommendedGroupSizeModalState: OneTimeModalState.NeverShown, @@ -1621,6 +1631,7 @@ describe('both/state/selectors/conversations', () => { cantAddContactIdForModal: undefined, searchTerm: 'to be cleared', groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', maximumGroupSizeModalState: OneTimeModalState.NeverShown, recommendedGroupSizeModalState: OneTimeModalState.Showing, @@ -1650,6 +1661,7 @@ describe('both/state/selectors/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, isCreating: false, hasError: false as const, }, @@ -1671,6 +1683,7 @@ describe('both/state/selectors/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: new Uint8Array([1, 2, 3]).buffer, + groupExpireTimer: 0, isCreating: false, hasError: false as const, }, @@ -1697,6 +1710,7 @@ describe('both/state/selectors/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: 'foo bar', groupAvatar: undefined, + groupExpireTimer: 0, isCreating: false, hasError: false as const, }, @@ -1730,6 +1744,7 @@ describe('both/state/selectors/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: 'foo bar', groupAvatar: undefined, + groupExpireTimer: 0, isCreating: false, hasError: false as const, }, diff --git a/ts/test-electron/state/ducks/conversations_test.ts b/ts/test-electron/state/ducks/conversations_test.ts index dc13b03ae..370e2980c 100644 --- a/ts/test-electron/state/ducks/conversations_test.ts +++ b/ts/test-electron/state/ducks/conversations_test.ts @@ -454,6 +454,7 @@ describe('both/state/ducks/conversations', () => { cantAddContactIdForModal: undefined, searchTerm: '', groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', maximumGroupSizeModalState: OneTimeModalState.NeverShown, recommendedGroupSizeModalState: OneTimeModalState.NeverShown, @@ -482,6 +483,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, isCreating: false as const, hasError: true as const, }, @@ -517,6 +519,7 @@ describe('both/state/ducks/conversations', () => { cantAddContactIdForModal: 'abc123', searchTerm: '', groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', maximumGroupSizeModalState: OneTimeModalState.NeverShown, recommendedGroupSizeModalState: OneTimeModalState.NeverShown, @@ -567,6 +570,7 @@ describe('both/state/ducks/conversations', () => { cantAddContactIdForModal: 'abc123', searchTerm: '', groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', maximumGroupSizeModalState: OneTimeModalState.Showing, recommendedGroupSizeModalState: OneTimeModalState.NeverShown, @@ -592,6 +596,7 @@ describe('both/state/ducks/conversations', () => { cantAddContactIdForModal: 'abc123', searchTerm: '', groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', maximumGroupSizeModalState: OneTimeModalState.NeverShown, recommendedGroupSizeModalState: OneTimeModalState.NeverShown, @@ -612,6 +617,7 @@ describe('both/state/ducks/conversations', () => { cantAddContactIdForModal: 'abc123', searchTerm: '', groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', maximumGroupSizeModalState: OneTimeModalState.Shown, recommendedGroupSizeModalState: OneTimeModalState.NeverShown, @@ -634,6 +640,7 @@ describe('both/state/ducks/conversations', () => { cantAddContactIdForModal: 'abc123', searchTerm: '', groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', maximumGroupSizeModalState: OneTimeModalState.NeverShown, recommendedGroupSizeModalState: OneTimeModalState.Showing, @@ -659,6 +666,7 @@ describe('both/state/ducks/conversations', () => { cantAddContactIdForModal: 'abc123', searchTerm: '', groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', maximumGroupSizeModalState: OneTimeModalState.NeverShown, recommendedGroupSizeModalState: OneTimeModalState.NeverShown, @@ -679,6 +687,7 @@ describe('both/state/ducks/conversations', () => { cantAddContactIdForModal: 'abc123', searchTerm: '', groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', maximumGroupSizeModalState: OneTimeModalState.NeverShown, recommendedGroupSizeModalState: OneTimeModalState.Shown, @@ -703,6 +712,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: 'Foo Bar Group', groupAvatar: new Uint8Array([1, 2, 3]).buffer, + groupExpireTimer: 0, isCreating: false as const, hasError: true as const, }, @@ -748,6 +758,7 @@ describe('both/state/ducks/conversations', () => { sinon.assert.calledWith(createGroupStub, { name: 'Foo Bar Group', avatar: new Uint8Array([1, 2, 3]).buffer, + expireTimer: 0, conversationIds: ['abc123'], }); }); @@ -1205,6 +1216,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: 'foo', groupAvatar: new ArrayBuffer(2), + groupExpireTimer: 0, isCreating: false as const, hasError: false as const, }, @@ -1230,6 +1242,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: 'foo', groupAvatar: undefined, + groupExpireTimer: 0, isCreating: false as const, hasError: false as const, }, @@ -1255,6 +1268,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, isCreating: false as const, hasError: false as const, }, @@ -1424,6 +1438,7 @@ describe('both/state/ducks/conversations', () => { cantAddContactIdForModal: undefined, searchTerm: 'to be cleared', groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', maximumGroupSizeModalState: OneTimeModalState.NeverShown, recommendedGroupSizeModalState: OneTimeModalState.NeverShown, @@ -1451,6 +1466,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, isCreating: false, hasError: false as const, }, @@ -1515,6 +1531,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }); }); @@ -1530,6 +1547,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }; const action = showChooseGroupMembers(); @@ -1549,6 +1567,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: 'Foo Bar Group', groupAvatar: new Uint8Array([4, 2]).buffer, + groupExpireTimer: 0, isCreating: false, hasError: false as const, }, @@ -1566,6 +1585,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: 'Foo Bar Group', groupAvatar: new Uint8Array([4, 2]).buffer, + groupExpireTimer: 0, }); }); @@ -1584,6 +1604,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }); }); @@ -1605,6 +1626,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }); }); }); @@ -1622,6 +1644,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }; const action = startSettingGroupMetadata(); @@ -1634,6 +1657,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, isCreating: false, hasError: false, }); @@ -1651,6 +1675,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: 'Foo Bar Group', groupAvatar: new Uint8Array([6, 9]).buffer, + groupExpireTimer: 0, }, }; const action = startSettingGroupMetadata(); @@ -1663,6 +1688,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: 'Foo Bar Group', groupAvatar: new Uint8Array([6, 9]).buffer, + groupExpireTimer: 0, isCreating: false, hasError: false as const, }); @@ -1678,6 +1704,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: 'Foo Bar Group', groupAvatar: new Uint8Array([4, 2]).buffer, + groupExpireTimer: 0, isCreating: false, hasError: false as const, }, @@ -1731,6 +1758,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }; const one = reducer(zero, getAction('abc', zero)); @@ -1745,6 +1773,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }); }); @@ -1760,6 +1789,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }; const action = getAction('abc', state); @@ -1774,6 +1804,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }); }); @@ -1792,6 +1823,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }; const action = getAction(newUuid, state); @@ -1806,6 +1838,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }); }); @@ -1824,6 +1857,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }; const action = getAction(newUuid, state); @@ -1838,6 +1872,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }); }); @@ -1858,6 +1893,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }; const action = getAction(uuid(), state); @@ -1881,6 +1917,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }; const action = getAction(newUuid, state); @@ -1895,6 +1932,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.Showing, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }); }); @@ -1913,6 +1951,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.Shown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }; const action = getAction(newUuid, state); @@ -1927,6 +1966,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.Shown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }); }); @@ -1942,6 +1982,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }; const action = getAction(uuid(), state); @@ -1969,6 +2010,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }; const action = getAction(uuid(), state); @@ -1995,6 +2037,7 @@ describe('both/state/ducks/conversations', () => { maximumGroupSizeModalState: OneTimeModalState.NeverShown, groupName: '', groupAvatar: undefined, + groupExpireTimer: 0, }, }; const action = getAction(uuid(), state); diff --git a/ts/test-node/components/leftPane/LeftPaneSetGroupMetadataHelper_test.ts b/ts/test-node/components/leftPane/LeftPaneSetGroupMetadataHelper_test.ts index d22e4d6e0..4fbff0263 100644 --- a/ts/test-node/components/leftPane/LeftPaneSetGroupMetadataHelper_test.ts +++ b/ts/test-node/components/leftPane/LeftPaneSetGroupMetadataHelper_test.ts @@ -14,6 +14,7 @@ describe('LeftPaneSetGroupMetadataHelper', () => { const showChooseGroupMembers = sinon.fake(); const helper = new LeftPaneSetGroupMetadataHelper({ groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', hasError: false, isCreating: false, @@ -29,6 +30,7 @@ describe('LeftPaneSetGroupMetadataHelper', () => { it("returns undefined (i.e., you can't go back) if a request is active", () => { const helper = new LeftPaneSetGroupMetadataHelper({ groupAvatar: undefined, + groupExpireTimer: 0, groupName: 'Foo Bar', hasError: false, isCreating: true, @@ -46,6 +48,7 @@ describe('LeftPaneSetGroupMetadataHelper', () => { assert.strictEqual( new LeftPaneSetGroupMetadataHelper({ groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', hasError: false, isCreating: false, @@ -59,6 +62,7 @@ describe('LeftPaneSetGroupMetadataHelper', () => { assert.strictEqual( new LeftPaneSetGroupMetadataHelper({ groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', hasError: false, isCreating: false, @@ -77,6 +81,7 @@ describe('LeftPaneSetGroupMetadataHelper', () => { assert.isUndefined( new LeftPaneSetGroupMetadataHelper({ groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', hasError: false, isCreating: false, @@ -92,6 +97,7 @@ describe('LeftPaneSetGroupMetadataHelper', () => { ]; const helper = new LeftPaneSetGroupMetadataHelper({ groupAvatar: undefined, + groupExpireTimer: 0, groupName: '', hasError: false, isCreating: false, diff --git a/ts/window.d.ts b/ts/window.d.ts index 23cff3456..2961daf6c 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -107,7 +107,7 @@ import { MessageDetail } from './components/conversation/MessageDetail'; import { ProgressModal } from './components/ProgressModal'; import { Quote } from './components/conversation/Quote'; import { StagedLinkPreview } from './components/conversation/StagedLinkPreview'; -import { DisappearingTimeDialog } from './components/conversation/DisappearingTimeDialog'; +import { DisappearingTimeDialog } from './components/DisappearingTimeDialog'; import { MIMEType } from './types/MIME'; import { AttachmentType } from './types/Attachment'; import { ElectronLocaleType } from './util/mapToSupportLocale';