diff --git a/js/expiring_messages.js b/js/expiring_messages.js index 4c490921d207..86e6588c235e 100644 --- a/js/expiring_messages.js +++ b/js/expiring_messages.js @@ -1,9 +1,6 @@ /* global _, - Backbone, - i18n, MessageController, - moment, Whisper */ @@ -98,59 +95,4 @@ }, update: debouncedCheckExpiringMessages, }; - - const TimerOption = Backbone.Model.extend({ - getName() { - return ( - i18n(['timerOption', this.get('time'), this.get('unit')].join('_')) || - moment.duration(this.get('time'), this.get('unit')).humanize() - ); - }, - getAbbreviated() { - return i18n( - ['timerOption', this.get('time'), this.get('unit'), 'abbreviated'].join( - '_' - ) - ); - }, - }); - Whisper.ExpirationTimerOptions = new (Backbone.Collection.extend({ - model: TimerOption, - getName(seconds = 0) { - const o = this.findWhere({ seconds }); - if (o) { - return o.getName(); - } - return [seconds, 'seconds'].join(' '); - }, - getAbbreviated(seconds = 0) { - const o = this.findWhere({ seconds }); - if (o) { - return o.getAbbreviated(); - } - return [seconds, 's'].join(''); - }, - }))( - [ - [0, 'seconds'], - [5, 'seconds'], - [10, 'seconds'], - [30, 'seconds'], - [1, 'minute'], - [5, 'minutes'], - [30, 'minutes'], - [1, 'hour'], - [6, 'hours'], - [12, 'hours'], - [1, 'day'], - [1, 'week'], - ].map(o => { - const duration = moment.duration(o[0], o[1]); // 5, 'seconds' - return { - time: o[0], - unit: o[1], - seconds: duration.asSeconds(), - }; - }) - ); })(); diff --git a/js/modules/signal.js b/js/modules/signal.js index 578e50c80d23..e0bdf962dc7b 100644 --- a/js/modules/signal.js +++ b/js/modules/signal.js @@ -33,9 +33,6 @@ const { ContactDetail, } = require('../../ts/components/conversation/ContactDetail'); const { ContactListItem } = require('../../ts/components/ContactListItem'); -const { - ConversationHeader, -} = require('../../ts/components/conversation/ConversationHeader'); const { Emojify } = require('../../ts/components/conversation/Emojify'); const { ErrorModal } = require('../../ts/components/ErrorModal'); const { Lightbox } = require('../../ts/components/Lightbox'); @@ -63,6 +60,9 @@ const { createTimeline } = require('../../ts/state/roots/createTimeline'); const { createCompositionArea, } = require('../../ts/state/roots/createCompositionArea'); +const { + createConversationHeader, +} = require('../../ts/state/roots/createConversationHeader'); const { createCallManager } = require('../../ts/state/roots/createCallManager'); const { createLeftPane } = require('../../ts/state/roots/createLeftPane'); const { @@ -295,7 +295,6 @@ exports.setup = (options = {}) => { ConfirmationModal, ContactDetail, ContactListItem, - ConversationHeader, Emojify, ErrorModal, getCallingNotificationText, @@ -315,6 +314,7 @@ exports.setup = (options = {}) => { const Roots = { createCallManager, createCompositionArea, + createConversationHeader, createLeftPane, createSafetyNumberViewer, createShortcutGuideModal, diff --git a/ts/background.ts b/ts/background.ts index 31d11d7dcea1..e3b7b05567ab 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -124,7 +124,7 @@ type WhatIsThis = typeof window.WhatIsThis; }; // Keyboard/mouse mode - let interactionMode = 'mouse'; + let interactionMode: 'mouse' | 'keyboard' = 'mouse'; $(document.body).addClass('mouse-mode'); window.enterKeyboardMode = () => { @@ -664,8 +664,8 @@ type WhatIsThis = typeof window.WhatIsThis; conversationLookup: window.Signal.Util.makeLookup(conversations, 'id'), messagesByConversation: {}, messagesLookup: {}, - selectedConversation: null, - selectedMessage: null, + selectedConversation: undefined, + selectedMessage: undefined, selectedMessageCounter: 0, showArchived: false, }, @@ -822,7 +822,7 @@ type WhatIsThis = typeof window.WhatIsThis; const conversationsToSearch = getConversationsToSearch(); const increment = direction === 'up' ? -1 : 1; - let startIndex; + let startIndex: WhatIsThis; if (conversationId) { const index = conversationsToSearch.findIndex( @@ -844,7 +844,7 @@ type WhatIsThis = typeof window.WhatIsThis; if (!unreadOnly) { return target.id; } - if (target.unreadCount > 0) { + if ((target.unreadCount || 0) > 0) { return target.id; } } diff --git a/ts/components/conversation/ConversationHeader.stories.tsx b/ts/components/conversation/ConversationHeader.stories.tsx index 1ba1c0cb7734..c0db8d88cb74 100644 --- a/ts/components/conversation/ConversationHeader.stories.tsx +++ b/ts/components/conversation/ConversationHeader.stories.tsx @@ -1,16 +1,11 @@ -import * as React from 'react'; +import React, { ComponentProps } from 'react'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import { setup as setupI18n } from '../../../js/modules/i18n'; import enMessages from '../../../_locales/en/messages.json'; -import { - ConversationHeader, - PropsActionsType, - PropsHousekeepingType, - PropsType, -} from './ConversationHeader'; +import { ConversationHeader } from './ConversationHeader'; import { gifUrl } from '../../storybook/Fixtures'; const book = storiesOf('Components/Conversation/ConversationHeader', module); @@ -21,11 +16,17 @@ type ConversationHeaderStory = { description: string; items: Array<{ title: string; - props: PropsType; + props: ComponentProps; }>; }; -const actionProps: PropsActionsType = { +const commonProps = { + showBackButton: false, + showCallButtons: true, + markedUnread: false, + + i18n, + onSetDisappearingMessages: action('onSetDisappearingMessages'), onDeleteMessages: action('onDeleteMessages'), onResetSession: action('onResetSession'), @@ -49,10 +50,6 @@ const actionProps: PropsActionsType = { onSetPin: action('onSetPin'), }; -const housekeepingProps: PropsHousekeepingType = { - i18n, -}; - const stories: Array = [ { title: '1:1 conversation', @@ -62,6 +59,7 @@ const stories: Array = [ { title: 'With name and profile, verified', props: { + ...commonProps, color: 'red', isVerified: true, avatarPath: gifUrl, @@ -72,13 +70,12 @@ const stories: Array = [ id: '1', profileName: '🔥Flames🔥', acceptedMessageRequest: true, - ...actionProps, - ...housekeepingProps, }, }, { title: 'With name, not verified, no avatar', props: { + ...commonProps, color: 'blue', isVerified: false, title: 'Someone 🔥 Somewhere', @@ -87,13 +84,12 @@ const stories: Array = [ type: 'direct', id: '2', acceptedMessageRequest: true, - ...actionProps, - ...housekeepingProps, }, }, { title: 'With name, not verified, descenders', props: { + ...commonProps, color: 'blue', isVerified: false, title: 'Joyrey 🔥 Leppey', @@ -102,13 +98,12 @@ const stories: Array = [ type: 'direct', id: '2', acceptedMessageRequest: true, - ...actionProps, - ...housekeepingProps, }, }, { title: 'Profile, no name', props: { + ...commonProps, color: 'teal', isVerified: false, phoneNumber: '(202) 555-0003', @@ -117,25 +112,23 @@ const stories: Array = [ title: '🔥Flames🔥', profileName: '🔥Flames🔥', acceptedMessageRequest: true, - ...actionProps, - ...housekeepingProps, }, }, { title: 'No name, no profile, no color', props: { + ...commonProps, title: '(202) 555-0011', phoneNumber: '(202) 555-0011', type: 'direct', id: '11', acceptedMessageRequest: true, - ...actionProps, - ...housekeepingProps, }, }, { title: 'With back button', props: { + ...commonProps, showBackButton: true, color: 'deep_orange', phoneNumber: '(202) 555-0004', @@ -143,46 +136,32 @@ const stories: Array = [ type: 'direct', id: '4', acceptedMessageRequest: true, - ...actionProps, - ...housekeepingProps, }, }, { title: 'Disappearing messages set', props: { + ...commonProps, color: 'indigo', title: '(202) 555-0005', phoneNumber: '(202) 555-0005', type: 'direct', id: '5', - expirationSettingName: '10 seconds', - timerOptions: [ - { - name: 'off', - value: 0, - }, - { - name: '10 seconds', - value: 10, - }, - ], + expireTimer: 10, acceptedMessageRequest: true, - ...actionProps, - ...housekeepingProps, }, }, { title: 'Muting Conversation', props: { + ...commonProps, color: 'ultramarine', title: '(202) 555-0006', phoneNumber: '(202) 555-0006', type: 'direct', id: '6', - muteExpirationLabel: '10/18/3000, 11:11 AM', acceptedMessageRequest: true, - ...actionProps, - ...housekeepingProps, + muteExpiresAt: new Date('3000-10-18T11:11:11Z').valueOf(), }, }, ], @@ -195,52 +174,30 @@ const stories: Array = [ { title: 'Basic', props: { + ...commonProps, color: 'signal-blue', title: 'Typescript support group', name: 'Typescript support group', phoneNumber: '', id: '1', type: 'group', - expirationSettingName: '10 seconds', - timerOptions: [ - { - name: 'off', - value: 0, - }, - { - name: '10 seconds', - value: 10, - }, - ], + expireTimer: 10, acceptedMessageRequest: true, - ...actionProps, - ...housekeepingProps, }, }, { title: 'In a group you left - no disappearing messages', props: { + ...commonProps, color: 'signal-blue', title: 'Typescript support group', name: 'Typescript support group', phoneNumber: '', id: '2', type: 'group', - disableTimerChanges: true, - expirationSettingName: '10 seconds', - timerOptions: [ - { - name: 'off', - value: 0, - }, - { - name: '10 seconds', - value: 10, - }, - ], + left: true, + expireTimer: 10, acceptedMessageRequest: true, - ...actionProps, - ...housekeepingProps, }, }, ], @@ -252,6 +209,7 @@ const stories: Array = [ { title: 'In chat with yourself', props: { + ...commonProps, color: 'blue', title: '(202) 555-0007', phoneNumber: '(202) 555-0007', @@ -259,8 +217,6 @@ const stories: Array = [ type: 'direct', isMe: true, acceptedMessageRequest: true, - ...actionProps, - ...housekeepingProps, }, }, ], @@ -272,6 +228,7 @@ const stories: Array = [ { title: '1:1 conversation', props: { + ...commonProps, color: 'blue', title: '(202) 555-0007', phoneNumber: '(202) 555-0007', @@ -279,8 +236,6 @@ const stories: Array = [ type: 'direct', isMe: false, acceptedMessageRequest: false, - ...actionProps, - ...housekeepingProps, }, }, ], diff --git a/ts/components/conversation/ConversationHeader.tsx b/ts/components/conversation/ConversationHeader.tsx index a81d21e541e6..523a98fa3e98 100644 --- a/ts/components/conversation/ConversationHeader.tsx +++ b/ts/components/conversation/ConversationHeader.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import moment from 'moment'; import classNames from 'classnames'; import { ContextMenu, @@ -14,11 +15,11 @@ import { InContactsIcon } from '../InContactsIcon'; import { LocalizerType } from '../../types/Util'; import { ColorType } from '../../types/Colors'; import { getMuteOptions } from '../../util/getMuteOptions'; - -interface TimerOption { - name: string; - value: number; -} +import { + ExpirationTimerOptions, + TimerOption, +} from '../../util/ExpirationTimerOptions'; +import { isMuted } from '../../util/isMuted'; export interface PropsDataType { id: string; @@ -36,13 +37,16 @@ export interface PropsDataType { isMe?: boolean; isArchived?: boolean; isPinned?: boolean; + isMissingMandatoryProfileSharing?: boolean; + left?: boolean; markedUnread?: boolean; - disableTimerChanges?: boolean; - expirationSettingName?: string; - muteExpirationLabel?: string; + canChangeTimer?: boolean; + expireTimer?: number; + muteExpiresAt?: number; + showBackButton?: boolean; - timerOptions?: Array; + showCallButtons?: boolean; } export interface PropsActionsType { @@ -186,8 +190,11 @@ export class ConversationHeader extends React.Component { } public renderExpirationLength(): JSX.Element | null { - const { expirationSettingName, showBackButton } = this.props; + const { i18n, expireTimer, showBackButton } = this.props; + const expirationSettingName = expireTimer + ? ExpirationTimerOptions.getName(i18n, expireTimer) + : undefined; if (!expirationSettingName) { return null; } @@ -249,71 +256,62 @@ export class ConversationHeader extends React.Component { ); } - public renderOutgoingAudioCallButton(): JSX.Element | null { + private renderOutgoingCallButtons(): JSX.Element | null { const { i18n, - isMe, onOutgoingAudioCallInConversation, + onOutgoingVideoCallInConversation, + showCallButtons, showBackButton, - type, } = this.props; - if (type === 'group' || isMe) { + if (!showCallButtons) { return null; } return ( -