Prefer type to interface and add an ESLint rule

This commit is contained in:
Evan Hahn 2021-01-14 12:07:05 -06:00 committed by Scott Nonnenberg
parent c85c073669
commit 8a72607fa7
106 changed files with 431 additions and 375 deletions

View file

@ -1,4 +1,4 @@
// Copyright 2018-2020 Signal Messenger, LLC
// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
@ -37,10 +37,10 @@ export type Props = {
i18n: LocalizerType;
} & Pick<React.HTMLProps<HTMLDivElement>, 'className'>;
interface State {
imageBroken: boolean;
lastAvatarPath?: string;
}
type State = {
readonly imageBroken: boolean;
readonly lastAvatarPath?: string;
};
export class Avatar extends React.Component<Props, State> {
public handleImageErrorBound: () => void;

View file

@ -39,11 +39,11 @@ import {
import { LocalizerType } from '../types/Util';
import { missingCaseError } from '../util/missingCaseError';
interface MeType extends ConversationType {
type MeType = ConversationType & {
uuid: string;
}
};
export interface PropsType {
export type PropsType = {
activeCall?: ActiveCallType;
availableCameras: Array<MediaDeviceInfo>;
cancelCall: (_: CancelCallType) => void;
@ -74,11 +74,11 @@ export interface PropsType {
togglePip: () => void;
toggleSettings: () => void;
toggleSpeakerView: () => void;
}
};
interface ActiveCallManagerPropsType extends PropsType {
type ActiveCallManagerPropsType = PropsType & {
activeCall: ActiveCallType;
}
};
const ActiveCallManager: React.FC<ActiveCallManagerPropsType> = ({
activeCall,

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useRef, useEffect } from 'react';
@ -8,7 +8,7 @@ import { Intl } from './Intl';
import { ContactName } from './conversation/ContactName';
import { ColorType } from '../types/Colors';
interface Props {
type Props = {
conversation: {
avatarPath?: string;
color?: ColorType;
@ -19,7 +19,7 @@ interface Props {
};
i18n: LocalizerType;
close: () => void;
}
};
const AUTO_CLOSE_MS = 10000;

View file

@ -41,24 +41,24 @@ const conversation = {
lastUpdated: Date.now(),
};
interface OverridePropsBase {
type OverridePropsBase = {
hasLocalAudio?: boolean;
hasLocalVideo?: boolean;
isInSpeakerView?: boolean;
}
};
interface DirectCallOverrideProps extends OverridePropsBase {
type DirectCallOverrideProps = OverridePropsBase & {
callMode: CallMode.Direct;
callState?: CallState;
hasRemoteVideo?: boolean;
}
};
interface GroupCallOverrideProps extends OverridePropsBase {
type GroupCallOverrideProps = OverridePropsBase & {
callMode: CallMode.Group;
connectionState?: GroupCallConnectionState;
peekedParticipants?: Array<ConversationType>;
remoteParticipants?: Array<GroupCallRemoteParticipantType>;
}
};
const createActiveDirectCallProp = (
overrideProps: DirectCallOverrideProps

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* eslint-disable react/no-array-index-key */
@ -12,10 +12,10 @@ import { LocalizerType } from '../types/Util';
import { sortByTitle } from '../util/sortByTitle';
import { ConversationType } from '../state/ducks/conversations';
interface ParticipantType extends ConversationType {
type ParticipantType = ConversationType & {
hasAudio?: boolean;
hasVideo?: boolean;
}
};
export type PropsType = {
readonly i18n: LocalizerType;

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
@ -42,14 +42,14 @@ type PositionState =
offsetX: number;
};
interface SnapCandidate {
type SnapCandidate = {
mode:
| PositionMode.SnapToBottom
| PositionMode.SnapToLeft
| PositionMode.SnapToRight
| PositionMode.SnapToTop;
distanceToEdge: number;
}
};
export type PropsType = {
activeCall: ActiveCallType;

View file

@ -61,13 +61,13 @@ const NoVideo = ({
);
};
export interface PropsType {
export type PropsType = {
activeCall: ActiveCallType;
getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource;
i18n: LocalizerType;
setGroupCallVideoRequest: (_: Array<GroupCallVideoRequest>) => void;
setRendererCanvas: (_: SetRendererCanvasType) => void;
}
};
export const CallingPipRemoteVideo = ({
activeCall,

View file

@ -1,4 +1,4 @@
// Copyright 2018-2020 Signal Messenger, LLC
// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
@ -8,18 +8,18 @@ import { AttachmentType } from '../types/Attachment';
import { LocalizerType } from '../types/Util';
export interface Props {
export type Props = {
attachment: AttachmentType;
i18n: LocalizerType;
url: string;
caption?: string;
onSave?: (caption: string) => void;
close?: () => void;
}
};
interface State {
type State = {
caption: string;
}
};
export class CaptionEditor extends React.Component<Props, State> {
private readonly handleKeyDownBound: (

View file

@ -1,4 +1,4 @@
// Copyright 2019-2020 Signal Messenger, LLC
// Copyright 2019-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from 'react';
@ -42,20 +42,20 @@ Quill.register('modules/emojiCompletion', EmojiCompletion);
Quill.register('modules/mentionCompletion', MentionCompletion);
Quill.register('modules/signalClipboard', SignalClipboard);
interface HistoryStatic {
type HistoryStatic = {
undo(): void;
clear(): void;
}
};
export interface InputApi {
export type InputApi = {
focus: () => void;
insertEmoji: (e: EmojiPickDataType) => void;
reset: () => void;
resetEmojiResults: () => void;
submit: () => void;
}
};
export interface Props {
export type Props = {
readonly i18n: LocalizerType;
readonly disabled?: boolean;
readonly large?: boolean;
@ -75,7 +75,7 @@ export interface Props {
onSubmit(message: string, mentions: Array<BodyRangeType>): unknown;
getQuotedMessage(): unknown;
clearQuotedMessage(): unknown;
}
};
const MAX_LENGTH = 64 * 1024;

View file

@ -1,4 +1,4 @@
// Copyright 2018-2020 Signal Messenger, LLC
// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
@ -11,7 +11,7 @@ import { InContactsIcon } from './InContactsIcon';
import { LocalizerType } from '../types/Util';
import { ColorType } from '../types/Colors';
interface Props {
type Props = {
avatarPath?: string;
color?: ColorType;
i18n: LocalizerType;
@ -23,7 +23,7 @@ interface Props {
phoneNumber?: string;
profileName?: string;
title: string;
}
};
export class ContactListItem extends React.Component<Props> {
public renderAvatar(): JSX.Element {

View file

@ -1,16 +1,16 @@
// Copyright 2019-2020 Signal Messenger, LLC
// Copyright 2019-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
export interface Props {
export type Props = {
duration: number;
expiresAt: number;
onComplete?: () => unknown;
}
interface State {
};
type State = {
ratio: number;
}
};
const CIRCUMFERENCE = 11.013 * 2 * Math.PI;

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useRef, useEffect } from 'react';
@ -8,12 +8,12 @@ import { ColorType } from '../types/Colors';
import { LocalizerType } from '../types/Util';
import { Avatar } from './Avatar';
interface PropsType {
type PropsType = {
conversation: ConversationType;
hasRemoteVideo: boolean;
i18n: LocalizerType;
setRendererCanvas: (_: SetRendererCanvasType) => void;
}
};
export const DirectCallRemoteParticipant: React.FC<PropsType> = ({
conversation,

View file

@ -1,14 +1,14 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import { LocalizerType } from '../types/Util';
interface PropsType {
type PropsType = {
hasExpired: boolean;
i18n: LocalizerType;
}
};
export const ExpiredBuildDialog = ({
hasExpired,

View file

@ -16,12 +16,12 @@ const OVERFLOW_SCROLL_BUTTON_RATIO = 0.75;
// This should be an integer, as sub-pixel widths can cause performance issues.
export const OVERFLOW_PARTICIPANT_WIDTH = 140;
interface PropsType {
type PropsType = {
getFrameBuffer: () => ArrayBuffer;
getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource;
i18n: LocalizerType;
overflowedParticipants: ReadonlyArray<GroupCallRemoteParticipantType>;
}
};
export const GroupCallOverflowArea: FC<PropsType> = ({
getFrameBuffer,

View file

@ -24,27 +24,27 @@ import { ContactName } from './conversation/ContactName';
import { useIntersectionObserver } from '../util/hooks';
import { MAX_FRAME_SIZE } from '../calling/constants';
interface BasePropsType {
type BasePropsType = {
getFrameBuffer: () => ArrayBuffer;
getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource;
i18n: LocalizerType;
remoteParticipant: GroupCallRemoteParticipantType;
}
};
interface InPipPropsType {
type InPipPropsType = {
isInPip: true;
}
};
interface InOverflowAreaPropsType {
type InOverflowAreaPropsType = {
height: number;
isInPip?: false;
width: number;
}
};
interface InGridPropsType extends InOverflowAreaPropsType {
type InGridPropsType = InOverflowAreaPropsType & {
left: number;
top: number;
}
};
export type PropsType = BasePropsType &
(InPipPropsType | InOverflowAreaPropsType | InGridPropsType);

View file

@ -25,23 +25,23 @@ const PARTICIPANT_MARGIN = 10;
// We scale our video requests down for performance. This number is somewhat arbitrary.
const VIDEO_REQUEST_SCALAR = 0.75;
interface Dimensions {
type Dimensions = {
width: number;
height: number;
}
};
interface GridArrangement {
type GridArrangement = {
rows: Array<Array<GroupCallRemoteParticipantType>>;
scalar: number;
}
};
interface PropsType {
type PropsType = {
getGroupCallVideoFrameSource: (demuxId: number) => VideoFrameSource;
i18n: LocalizerType;
isInSpeakerView: boolean;
remoteParticipants: ReadonlyArray<GroupCallRemoteParticipantType>;
setGroupCallVideoRequest: (_: Array<GroupCallVideoRequest>) => void;
}
};
// This component lays out group call remote participants. It uses a custom layout
// algorithm (in other words, nothing that the browser provides, like flexbox) in

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React, { useState, useEffect } from 'react';
@ -6,10 +6,10 @@ import classNames from 'classnames';
import { GroupCallConnectionState } from '../types/Calling';
import { LocalizerType } from '../types/Util';
interface PropsType {
type PropsType = {
connectionState: GroupCallConnectionState;
i18n: LocalizerType;
}
};
// In the future, this component should show toasts when users join or leave. See
// DESKTOP-902.

View file

@ -1,4 +1,4 @@
// Copyright 2018-2020 Signal Messenger, LLC
// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
@ -8,13 +8,13 @@ import { ReplacementValuesType } from '../types/I18N';
export type FullJSXType = Array<JSX.Element | string> | JSX.Element | string;
export interface Props {
export type Props = {
/** The translation string id */
id: string;
i18n: LocalizerType;
components?: Array<FullJSXType> | ReplacementValuesType<FullJSXType>;
renderText?: RenderTextCallbackType;
}
};
export class Intl extends React.Component<Props> {
public static defaultProps: Partial<Props> = {

View file

@ -17,7 +17,7 @@ import {
import { LocalizerType } from '../types/Util';
import { cleanId } from './_util';
export interface PropsType {
export type PropsType = {
conversations?: Array<ConversationListItemPropsType>;
archivedConversations?: Array<ConversationListItemPropsType>;
pinnedConversations?: Array<ConversationListItemPropsType>;
@ -43,7 +43,7 @@ export interface PropsType {
renderNetworkStatus: () => JSX.Element;
renderRelinkDialog: () => JSX.Element;
renderUpdateDialog: () => JSX.Element;
}
};
// from https://github.com/bvaughn/react-virtualized/blob/fb3484ed5dcc41bffae8eab029126c0fb8f7abc0/source/List/types.js#L5
type RowRendererParamsType = {
@ -69,26 +69,26 @@ export enum HeaderType {
Chats,
}
interface ArchiveButtonRow {
type ArchiveButtonRow = {
type: RowType.ArchiveButton;
}
};
interface ConversationRow {
type ConversationRow = {
index: number;
type:
| RowType.ArchivedConversation
| RowType.Conversation
| RowType.PinnedConversation;
}
};
interface HeaderRow {
type HeaderRow = {
headerType: HeaderType;
type: RowType.Header;
}
};
interface UndefinedRow {
type UndefinedRow = {
type: RowType.Undefined;
}
};
type Row = ArchiveButtonRow | ConversationRow | HeaderRow | UndefinedRow;

View file

@ -24,7 +24,7 @@ const colorSVG = (url: string, color: string) => {
};
};
export interface Props {
export type Props = {
close: () => void;
contentType: MIME.MIMEType | undefined;
i18n: LocalizerType;
@ -34,10 +34,10 @@ export interface Props {
onNext?: () => void;
onPrevious?: () => void;
onSave?: () => void;
}
interface State {
};
type State = {
videoTime?: number;
}
};
const CONTROLS_WIDTH = 50;
const CONTROLS_SPACING = 10;
@ -158,12 +158,12 @@ const styles = {
},
};
interface IconButtonProps {
type IconButtonProps = {
i18n: LocalizerType;
onClick?: () => void;
style?: React.CSSProperties;
type: 'save' | 'close' | 'previous' | 'next';
}
};
const IconButton = ({ i18n, onClick, style, type }: IconButtonProps) => {
const clickHandler = (event: React.MouseEvent<HTMLButtonElement>): void => {

View file

@ -10,16 +10,16 @@ import { Message } from './conversation/media-gallery/types/Message';
import { AttachmentType } from '../types/Attachment';
import { LocalizerType } from '../types/Util';
export interface MediaItemType {
export type MediaItemType = {
objectURL?: string;
thumbnailObjectUrl?: string;
contentType?: MIME.MIMEType;
index: number;
attachment: AttachmentType;
message: Message;
}
};
export interface Props {
export type Props = {
close: () => void;
i18n: LocalizerType;
media: Array<MediaItemType>;
@ -29,11 +29,11 @@ export interface Props {
index: number;
}) => void;
selectedIndex: number;
}
};
interface State {
type State = {
selectedIndex: number;
}
};
export class LightboxGallery extends React.Component<Props, State> {
public static defaultProps: Partial<Props> = {

View file

@ -1,4 +1,4 @@
// Copyright 2018-2020 Signal Messenger, LLC
// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
@ -13,7 +13,7 @@ import { AvatarPopup } from './AvatarPopup';
import { LocalizerType } from '../types/Util';
import { ColorType } from '../types/Colors';
export interface PropsType {
export type PropsType = {
searchTerm: string;
searchConversationName?: string;
searchConversationId?: string;
@ -58,12 +58,12 @@ export interface PropsType {
clearSearch: () => void;
showArchivedConversations: () => void;
}
};
interface StateType {
type StateType = {
showingAvatarPopup: boolean;
popperRoot: HTMLDivElement | null;
}
};
export class MainHeader extends React.Component<PropsType, StateType> {
private readonly inputRef: React.RefObject<HTMLInputElement>;

View file

@ -1,4 +1,4 @@
// Copyright 2019-2020 Signal Messenger, LLC
// Copyright 2019-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
@ -11,10 +11,10 @@ import { SizeClassType } from './emoji/lib';
import { LocalizerType, RenderTextCallbackType } from '../types/Util';
export interface Props {
export type Props = {
text: string;
i18n: LocalizerType;
}
};
const renderNewLines: RenderTextCallbackType = ({ text, key }) => (
<AddNewLines key={key} text={text} />

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
@ -8,11 +8,11 @@ import { NetworkStateType } from '../state/ducks/network';
const FIVE_SECONDS = 5 * 1000;
export interface PropsType extends NetworkStateType {
export type PropsType = NetworkStateType & {
hasNetworkDialog: boolean;
i18n: LocalizerType;
manualReconnect: () => void;
}
};
type RenderDialogTypes = {
title: string;

View file

@ -1,15 +1,15 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import { LocalizerType } from '../types/Util';
export interface PropsType {
export type PropsType = {
i18n: LocalizerType;
isRegistrationDone: boolean;
relinkDevice: () => void;
}
};
export const RelinkDialog = ({
i18n,

View file

@ -1,4 +1,4 @@
// Copyright 2019-2020 Signal Messenger, LLC
// Copyright 2019-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
@ -15,11 +15,11 @@ export const SpinnerDirections = [
] as const;
export type SpinnerDirection = typeof SpinnerDirections[number];
export interface Props {
export type Props = {
size?: string;
svgSize: SpinnerSvgSize;
direction?: SpinnerDirection;
}
};
export const Spinner = ({ size, svgSize, direction }: Props): JSX.Element => (
<div

View file

@ -7,11 +7,11 @@ import { Avatar } from './Avatar';
import { LocalizerType } from '../types/Util';
export interface Props {
export type Props = {
phoneNumber: string;
i18n: LocalizerType;
onClick: () => void;
}
};
export class StartNewConversation extends React.PureComponent<Props> {
public render(): JSX.Element {

View file

@ -7,10 +7,10 @@ import { noop } from 'lodash';
import { Manager, Reference, Popper } from 'react-popper';
import { Theme, themeClassName } from '../util/theme';
interface EventWrapperPropsType {
type EventWrapperPropsType = {
children: React.ReactNode;
onHoverChanged: (_: boolean) => void;
}
};
// React doesn't reliably fire `onMouseLeave` or `onMouseOut` events if wrapping a
// disabled button. This uses native browser events to avoid that.

View file

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
@ -7,7 +7,7 @@ import { Dialogs } from '../types/Dialogs';
import { Intl } from './Intl';
import { LocalizerType } from '../types/Util';
export interface PropsType {
export type PropsType = {
ackRender: () => void;
dialogType: Dialogs;
didSnooze: boolean;
@ -17,7 +17,7 @@ export interface PropsType {
showEventsCount: number;
snoozeUpdate: () => void;
startUpdate: () => void;
}
};
export const UpdateDialog = ({
ackRender,

View file

@ -5,11 +5,11 @@ import React from 'react';
import { RenderTextCallbackType } from '../../types/Util';
export interface Props {
export type Props = {
text: string;
/** Allows you to customize now non-newlines are rendered. Simplest is just a <span>. */
renderNonNewLine?: RenderTextCallbackType;
}
};
export class AddNewLines extends React.Component<Props> {
public static defaultProps: Partial<Props> = {

View file

@ -15,14 +15,14 @@ import {
isVideoAttachment,
} from '../../types/Attachment';
export interface Props {
export type Props = {
attachments: Array<AttachmentType>;
i18n: LocalizerType;
onClickAttachment: (attachment: AttachmentType) => void;
onCloseAttachment: (attachment: AttachmentType) => void;
onAddAttachment: () => void;
onClose: () => void;
}
};
const IMAGE_WIDTH = 120;
const IMAGE_HEIGHT = 120;

View file

@ -14,14 +14,14 @@ import {
import { missingCaseError } from '../../util/missingCaseError';
import { Tooltip, TooltipPlacement } from '../Tooltip';
export interface PropsActionsType {
export type PropsActionsType = {
messageSizeChanged: (messageId: string, conversationId: string) => void;
returnToActiveCall: () => void;
startCallingLobby: (_: {
conversationId: string;
isVideoCall: boolean;
}) => void;
}
};
type PropsHousekeeping = {
i18n: LocalizerType;

View file

@ -21,12 +21,12 @@ import {
import { LocalizerType } from '../../types/Util';
export interface Props {
export type Props = {
contact: ContactType;
hasSignalAccount: boolean;
i18n: LocalizerType;
onSendMessage: () => void;
}
};
function getLabelForEmail(method: Email, i18n: LocalizerType): string {
switch (method.type) {

View file

@ -1,4 +1,4 @@
// Copyright 2018-2020 Signal Messenger, LLC
// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
@ -6,14 +6,14 @@ import React from 'react';
import { LocalizerType } from '../../types/Util';
import { Emojify } from './Emojify';
export interface PropsType {
export type PropsType = {
i18n: LocalizerType;
title: string;
module?: string;
name?: string;
phoneNumber?: string;
profileName?: string;
}
};
export const ContactName = ({ module, title }: PropsType): JSX.Element => {
const prefix = module || 'module-contact-name';

View file

@ -32,7 +32,7 @@ export enum OutgoingCallButtonStyle {
Join,
}
export interface PropsDataType {
export type PropsDataType = {
id: string;
name?: string;
@ -58,9 +58,9 @@ export interface PropsDataType {
showBackButton?: boolean;
outgoingCallButtonStyle: OutgoingCallButtonStyle;
}
};
export interface PropsActionsType {
export type PropsActionsType = {
onSetMuteNotifications: (seconds: number) => void;
onSetDisappearingMessages: (seconds: number) => void;
onDeleteMessages: () => void;
@ -78,11 +78,11 @@ export interface PropsActionsType {
onArchive: () => void;
onMarkUnread: () => void;
onMoveToInbox: () => void;
}
};
export interface PropsHousekeepingType {
export type PropsHousekeepingType = {
i18n: LocalizerType;
}
};
export type PropsType = PropsDataType &
PropsActionsType &

View file

@ -13,7 +13,7 @@ import {
renderName,
} from './_contactUtil';
export interface Props {
export type Props = {
contact: ContactType;
i18n: LocalizerType;
isIncoming: boolean;
@ -21,7 +21,7 @@ export interface Props {
withContentBelow: boolean;
tabIndex: number;
onClick?: () => void;
}
};
export class EmbeddedContact extends React.Component<Props> {
public render(): JSX.Element {

View file

@ -40,13 +40,13 @@ function getImageTag({
);
}
export interface Props {
export type Props = {
text: string;
/** A class name to be added to the generated emoji images */
sizeClass?: SizeClassType;
/** Allows you to customize now non-newlines are rendered. Simplest is just a <span>. */
renderNonEmoji?: RenderTextCallbackType;
}
};
export class Emojify extends React.Component<Props> {
public static defaultProps: Partial<Props> = {

View file

@ -6,14 +6,14 @@ import classNames from 'classnames';
import { getIncrement, getTimerBucket } from '../../util/timer';
export interface Props {
export type Props = {
withImageNoCaption?: boolean;
withSticker?: boolean;
withTapToViewExpired?: boolean;
expirationLength: number;
expirationTimestamp: number;
direction?: 'incoming' | 'outgoing';
}
};
export class ExpireTimer extends React.Component<Props> {
private interval: NodeJS.Timeout | null;

View file

@ -10,21 +10,21 @@ import { LocalizerType } from '../../types/Util';
import { missingCaseError } from '../../util/missingCaseError';
interface Contact {
type Contact = {
phoneNumber?: string;
profileName?: string;
name?: string;
title: string;
isMe?: boolean;
}
};
export type ChangeType = 'add' | 'remove' | 'name' | 'avatar' | 'general';
interface Change {
type Change = {
type: ChangeType;
newName?: string;
contacts?: Array<Contact>;
}
};
export type PropsData = {
from: Contact;

View file

@ -9,7 +9,7 @@ import { Spinner } from '../Spinner';
import { LocalizerType } from '../../types/Util';
import { AttachmentType } from '../../types/Attachment';
export interface Props {
export type Props = {
alt: string;
attachment: AttachmentType;
url: string;
@ -40,7 +40,7 @@ export interface Props {
onClick?: (attachment: AttachmentType) => void;
onClickClose?: (attachment: AttachmentType) => void;
onError?: () => void;
}
};
export class Image extends React.Component<Props> {
private canClick() {

View file

@ -18,7 +18,7 @@ import { Image } from './Image';
import { LocalizerType } from '../../types/Util';
export interface Props {
export type Props = {
attachments: Array<AttachmentType>;
withContentAbove?: boolean;
withContentBelow?: boolean;
@ -31,7 +31,7 @@ export interface Props {
onError: () => void;
onClick?: (attachment: AttachmentType) => void;
}
};
export const ImageGrid = ({
attachments,

View file

@ -5,10 +5,10 @@ import * as React from 'react';
import moment, { Moment } from 'moment';
import { isLinkPreviewDateValid } from '../../linkPreviews/isLinkPreviewDateValid';
interface Props {
type Props = {
date: null | number;
className?: string;
}
};
export const LinkPreviewDate: React.FC<Props> = ({
date,

View file

@ -36,11 +36,11 @@ const linkify = LinkifyIt()
'travel',
]);
export interface Props {
export type Props = {
text: string;
/** Allows you to customize now non-links are rendered. Simplest is just a <span>. */
renderNonLink?: RenderTextCallbackType;
}
};
const SUPPORTED_PROTOCOLS = /^(http|https):/i;

View file

@ -52,9 +52,9 @@ import { createRefMerger } from '../_util';
import { emojiToData } from '../emoji/lib';
import { SmartReactionPicker } from '../../state/smart/ReactionPicker';
interface Trigger {
type Trigger = {
handleContextClick: (event: React.MouseEvent<HTMLDivElement>) => void;
}
};
const STICKER_SIZE = 200;
const SELECTED_TIMEOUT = 1000;
@ -190,7 +190,7 @@ export type Props = PropsData &
PropsActions &
Pick<ReactionPickerProps, 'renderEmojiPicker'>;
interface State {
type State = {
expiring: boolean;
expired: boolean;
imageBroken: boolean;
@ -205,7 +205,7 @@ interface State {
containerWidth: number;
canDeleteForEveryone: boolean;
}
};
const EXPIRATION_CHECK_MINIMUM = 2000;
const EXPIRED_DELAY = 600;

View file

@ -20,7 +20,7 @@ type OpenConversationActionType = (
messageId?: string
) => void;
export interface Props {
export type Props = {
direction?: 'incoming' | 'outgoing';
text: string;
textPending?: boolean;
@ -31,7 +31,7 @@ export interface Props {
i18n: LocalizerType;
bodyRanges?: BodyRangesType;
openConversation?: OpenConversationActionType;
}
};
const renderEmoji = ({
text,

View file

@ -11,7 +11,7 @@ import { Message, MessageStatusType, Props as MessageProps } from './Message';
import { LocalizerType } from '../../types/Util';
import { ColorType } from '../../types/Colors';
interface Contact {
type Contact = {
status: MessageStatusType;
title: string;
@ -27,9 +27,9 @@ interface Contact {
onSendAnyway: () => void;
onShowSafetyNumber: () => void;
}
};
export interface Props {
export type Props = {
sentAt: number;
receivedAt: number;
@ -38,7 +38,7 @@ export interface Props {
contacts: Array<Contact>;
i18n: LocalizerType;
}
};
const _keyForError = (error: Error): string => {
return `${error.name}-${error.message}`;

View file

@ -11,11 +11,11 @@ import {
ProfileNameChangeType,
} from '../../util/getStringForProfileChange';
export interface PropsType {
export type PropsType = {
change: ProfileNameChangeType;
changedContact: ConversationType;
i18n: LocalizerType;
}
};
export function ProfileChangeNotification(props: PropsType): JSX.Element {
const { change, changedContact, i18n } = props;

View file

@ -13,7 +13,7 @@ import { ColorType } from '../../types/Colors';
import { ContactName } from './ContactName';
import { getTextWithMentions } from '../../util/getTextWithMentions';
export interface Props {
export type Props = {
attachment?: QuotedAttachmentType;
authorTitle: string;
authorPhoneNumber?: string;
@ -29,25 +29,25 @@ export interface Props {
onClose?: () => void;
text: string;
referencedMessageNotFound: boolean;
}
};
interface State {
type State = {
imageBroken: boolean;
}
};
export interface QuotedAttachmentType {
export type QuotedAttachmentType = {
contentType: MIME.MIMEType;
fileName: string;
/** Not included in protobuf */
isVoiceMessage: boolean;
thumbnail?: Attachment;
}
};
interface Attachment {
type Attachment = {
contentType: MIME.MIMEType;
/** Not included in protobuf, and is loaded asynchronously */
objectUrl?: string;
}
};
function validateQuote(quote: Props): boolean {
if (quote.text) {

View file

@ -46,12 +46,12 @@ const DEFAULT_EMOJI_ORDER = [
'rage',
];
interface ReactionCategory {
type ReactionCategory = {
count: number;
emoji?: string;
id: string;
index: number;
}
};
type ReactionWithEmojiData = Reaction & EmojiData;

View file

@ -5,9 +5,9 @@ import React from 'react';
import { LocalizerType } from '../../types/Util';
export interface Props {
export type Props = {
i18n: LocalizerType;
}
};
export const ResetSessionNotification = ({ i18n }: Props): JSX.Element => (
<div className="module-reset-session-notification">

View file

@ -7,13 +7,13 @@ import { ContactName } from './ContactName';
import { Intl } from '../Intl';
import { LocalizerType } from '../../types/Util';
export interface ContactType {
export type ContactType = {
id: string;
phoneNumber?: string;
profileName?: string;
title: string;
name?: string;
}
};
export type PropsData = {
isGroup: boolean;

View file

@ -6,11 +6,11 @@ import React from 'react';
import { AttachmentType, getExtensionForDisplay } from '../../types/Attachment';
import { LocalizerType } from '../../types/Util';
export interface Props {
export type Props = {
attachment: AttachmentType;
onClose: (attachment: AttachmentType) => void;
i18n: LocalizerType;
}
};
export const StagedGenericAttachment = ({
attachment,

View file

@ -10,7 +10,7 @@ import { LinkPreviewDate } from './LinkPreviewDate';
import { AttachmentType, isImageAttachment } from '../../types/Attachment';
import { LocalizerType } from '../../types/Util';
export interface Props {
export type Props = {
isLoaded: boolean;
title: string;
description: null | string;
@ -20,7 +20,7 @@ export interface Props {
i18n: LocalizerType;
onClose?: () => void;
}
};
export const StagedLinkPreview: React.FC<Props> = ({
isLoaded,

View file

@ -1,13 +1,13 @@
// Copyright 2019-2020 Signal Messenger, LLC
// Copyright 2019-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React from 'react';
import { LocalizerType } from '../../types/Util';
interface Props {
type Props = {
onClick: () => void;
i18n: LocalizerType;
}
};
export const StagedPlaceholderAttachment = ({
i18n,

View file

@ -9,7 +9,7 @@ import { formatRelativeTime } from '../../util/formatRelativeTime';
import { LocalizerType } from '../../types/Util';
export interface Props {
export type Props = {
timestamp?: number;
extended?: boolean;
module?: string;
@ -19,7 +19,7 @@ export interface Props {
withUnread?: boolean;
direction?: 'incoming' | 'outgoing';
i18n: LocalizerType;
}
};
const UPDATE_FREQUENCY = 60 * 1000;

View file

@ -6,10 +6,10 @@ import classNames from 'classnames';
import { LocalizerType } from '../../types/Util';
export interface Props {
export type Props = {
i18n: LocalizerType;
color?: string;
}
};
export const TypingAnimation = ({ i18n, color }: Props): JSX.Element => (
<div className="module-typing-animation" title={i18n('typingAlt')}>

View file

@ -10,7 +10,7 @@ import { Avatar } from '../Avatar';
import { LocalizerType } from '../../types/Util';
import { ColorType } from '../../types/Colors';
export interface Props {
export type Props = {
avatarPath?: string;
color: ColorType;
name?: string;
@ -19,7 +19,7 @@ export interface Props {
title: string;
conversationType: 'group' | 'direct';
i18n: LocalizerType;
}
};
export class TypingBubble extends React.PureComponent<Props> {
public renderAvatar(): JSX.Element | null {

View file

@ -8,14 +8,14 @@ import { ContactName } from './ContactName';
import { Intl } from '../Intl';
import { LocalizerType } from '../../types/Util';
export interface ContactType {
export type ContactType = {
id: string;
phoneNumber?: string;
profileName?: string;
title: string;
name?: string;
isMe: boolean;
}
};
export type PropsData = {
canProcessNow: boolean;

View file

@ -10,12 +10,12 @@ import { LocalizerType } from '../../types/Util';
import { missingCaseError } from '../../util/missingCaseError';
interface Contact {
type Contact = {
phoneNumber?: string;
profileName?: string;
name?: string;
title: string;
}
};
export type PropsData = {
type: 'markVerified' | 'markNotVerified';

View file

@ -10,13 +10,13 @@ import { MediaItemType } from '../../LightboxGallery';
import { missingCaseError } from '../../../util/missingCaseError';
import { LocalizerType } from '../../../types/Util';
export interface Props {
export type Props = {
i18n: LocalizerType;
header?: string;
type: 'media' | 'documents';
mediaItems: Array<MediaItemType>;
onItemClick?: (event: ItemClickEvent) => void;
}
};
export class AttachmentSection extends React.Component<Props> {
public render(): JSX.Element {

View file

@ -7,7 +7,7 @@ import classNames from 'classnames';
import moment from 'moment';
import formatFileSize from 'filesize';
interface Props {
type Props = {
// Required
timestamp: number;
@ -16,7 +16,7 @@ interface Props {
fileSize?: number;
onClick?: () => void;
shouldShowSeparator?: boolean;
}
};
export class DocumentListItem extends React.Component<Props> {
public static defaultProps: Partial<Props> = {

View file

@ -3,9 +3,9 @@
import React from 'react';
interface Props {
type Props = {
label: string;
}
};
export const EmptyState = ({ label }: Props): JSX.Element => (
<div className="module-empty-state">{label}</div>

View file

@ -15,23 +15,23 @@ import { LocalizerType } from '../../../types/Util';
import { MediaItemType } from '../../LightboxGallery';
export interface Props {
export type Props = {
documents: Array<MediaItemType>;
i18n: LocalizerType;
media: Array<MediaItemType>;
onItemClick?: (event: ItemClickEvent) => void;
}
};
interface State {
type State = {
selectedTab: 'media' | 'documents';
}
};
const MONTH_FORMAT = 'MMMM YYYY';
interface TabSelectEvent {
type TabSelectEvent = {
type: 'media' | 'documents';
}
};
const Tab = ({
isSelected,

View file

@ -11,15 +11,15 @@ import {
import { LocalizerType } from '../../../types/Util';
import { MediaItemType } from '../../LightboxGallery';
export interface Props {
export type Props = {
mediaItem: MediaItemType;
onClick?: () => void;
i18n: LocalizerType;
}
};
interface State {
type State = {
imageBroken: boolean;
}
};
export class MediaGridItem extends React.Component<Props, State> {
private readonly onImageErrorBound: () => void;

View file

@ -11,10 +11,10 @@ import { MediaItemType } from '../../LightboxGallery';
type StaticSectionType = 'today' | 'yesterday' | 'thisWeek' | 'thisMonth';
type YearMonthSectionType = 'yearMonth';
interface GenericSection<T> {
type GenericSection<T> = {
type: T;
mediaItems: Array<MediaItemType>;
}
};
type StaticSection = GenericSection<StaticSectionType>;
type YearMonthSection = GenericSection<YearMonthSectionType> & {
year: number;
@ -93,11 +93,11 @@ const toSection = (
}
};
interface GenericMediaItemWithSection<T> {
type GenericMediaItemWithSection<T> = {
order: number;
type: T;
mediaItem: MediaItemType;
}
};
type MediaItemWithStaticSection = GenericMediaItemWithSection<
StaticSectionType
>;

View file

@ -1,11 +1,11 @@
// Copyright 2018-2020 Signal Messenger, LLC
// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { AttachmentType } from '../../../../types/Attachment';
import { Message } from './Message';
export interface ItemClickEvent {
export type ItemClickEvent = {
message: Message;
attachment: AttachmentType;
type: 'media' | 'documents';
}
};