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

@ -95,6 +95,36 @@ const rules = {
// Upgrade from a warning
'@typescript-eslint/explicit-module-boundary-types': 'error',
'no-restricted-syntax': [
'error',
{
selector: 'TSInterfaceDeclaration',
message:
'Prefer `type`. Interfaces are mutable and less powerful, so we prefer `type` for simplicity.',
},
// Defaults
{
selector: 'ForInStatement',
message:
'for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.',
},
{
selector: 'ForOfStatement',
message:
'iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations.',
},
{
selector: 'LabeledStatement',
message:
'Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand.',
},
{
selector: 'WithStatement',
message:
'`with` is disallowed in strict mode because it makes code impossible to predict and optimize.',
},
],
};
module.exports = {

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 { hot } from 'react-hot-loader/root';
@ -11,6 +11,8 @@ import { store } from './store';
import { I18n } from './util/i18n';
declare global {
// We want to extend `window` here.
// eslint-disable-next-line no-restricted-syntax
interface Window {
localeMessages: { [key: string]: { message: string } };
}

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
/* eslint-disable no-param-reassign */
@ -56,15 +56,15 @@ export const minStickers = 1;
export const maxStickers = 200;
export const maxByteSize = 300 * 1024;
interface StateStickerData {
type StateStickerData = {
readonly imageData?: StickerImageData;
readonly emoji?: EmojiPickDataType;
}
};
interface StateToastData {
type StateToastData = {
key: string;
subs?: Array<number | string>;
}
};
export type State = {
readonly order: Array<string>;

View File

@ -1,9 +1,11 @@
// Copyright 2019-2020 Signal Messenger, LLC
// Copyright 2019-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { Metadata } from 'sharp';
declare global {
// We want to extend `window`'s properties, so we need an interface.
// eslint-disable-next-line no-restricted-syntax
interface Window {
processStickerImage: ProcessStickerImageFn;
encryptAndUpload: EncryptAndUploadFn;

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';
}
};

View File

@ -54,17 +54,17 @@ const emptyContentType = { type: null, charset: null };
type FetchFn = (href: string, init: RequestInit) => Promise<Response>;
export interface LinkPreviewMetadata {
export type LinkPreviewMetadata = {
title: string;
description: null | string;
date: null | number;
imageHref: null | string;
}
};
export interface LinkPreviewImage {
export type LinkPreviewImage = {
data: ArrayBuffer;
contentType: MIMEType;
}
};
type ParsedContentType =
| { type: null; charset: null }

4
ts/model-types.d.ts vendored
View File

@ -41,10 +41,10 @@ export declare class DeletesModelType extends Backbone.Model<
type TaskResultType = any;
export interface CustomError extends Error {
export type CustomError = Error & {
identifier?: string;
number?: string;
}
};
export type GroupMigrationType = {
areWeInvited: boolean;

View File

@ -76,10 +76,10 @@ const COLORS = [
const THREE_HOURS = 3 * 60 * 60 * 1000;
interface CustomError extends Error {
type CustomError = Error & {
identifier?: string;
number?: string;
}
};
export class ConversationModel extends window.Backbone.Model<
ConversationAttributesType
@ -4556,9 +4556,9 @@ window.Whisper.GroupMemberConversation = window.Backbone.Model.extend({
},
});
interface SortableByTitle {
type SortableByTitle = {
getTitle: () => string;
}
};
const sortConversationTitles = (
left: SortableByTitle,

View File

@ -1,20 +1,20 @@
// Copyright 2018-2020 Signal Messenger, LLC
// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
interface Environment {
type Environment = {
isAppFocused: boolean;
isAudioNotificationEnabled: boolean;
isEnabled: boolean;
hasNotifications: boolean;
userSetting: UserSetting;
}
};
interface Status {
type Status = {
shouldClearNotifications: boolean;
shouldPlayNotificationSound: boolean;
shouldShowNotifications: boolean;
type: Type;
}
};
type UserSetting = 'off' | 'count' | 'name' | 'message';

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 Quill from 'quill';
@ -22,11 +22,11 @@ import { getBlotTextPartitions, matchBlotTextPartitions } from '../util';
const Keyboard = Quill.import('modules/keyboard');
interface EmojiPickerOptions {
type EmojiPickerOptions = {
onPickEmoji: (emoji: EmojiPickDataType) => void;
setEmojiPickerElement: (element: JSX.Element | null) => void;
skinTone: number;
}
};
export class EmojiCompletion {
results: Array<EmojiData>;

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 _ from 'lodash';
@ -15,14 +15,16 @@ import { LocalizerType } from '../../types/Util';
import { MemberRepository } from '../memberRepository';
import { matchBlotTextPartitions } from '../util';
export interface MentionCompletionOptions {
export type MentionCompletionOptions = {
i18n: LocalizerType;
memberRepositoryRef: RefObject<MemberRepository>;
setMentionPickerElement: (element: JSX.Element | null) => void;
me?: ConversationType;
}
};
declare global {
// We want to extend `HTMLElement`'s properties, so we need an interface.
// eslint-disable-next-line no-restricted-syntax
interface HTMLElement {
// Webkit-specific
scrollIntoViewIfNeeded: (bringToCenter: boolean) => void;

5
ts/quill/types.d.ts vendored
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 UpdatedDelta from 'quill-delta';
@ -11,6 +11,8 @@ declare module 'react-quill' {
type DeltaStatic = UpdatedDelta;
}
// We want to extend some existing interfaces.
/* eslint-disable no-restricted-syntax */
declare module 'quill' {
// this type is fixed in @types/quill, but our version of react-quill cannot
// use the version of quill that has this fix in its typings
@ -76,3 +78,4 @@ declare module 'quill' {
bindings: Record<string | number, Array<unknown>>;
}
}
/* eslint-enable no-restricted-syntax */

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 emojiRegex from 'emoji-regex';
@ -9,10 +9,10 @@ import Op from 'quill-delta/dist/Op';
import { BodyRangeType } from '../types/Util';
import { MentionBlot } from './mentions/blot';
export interface MentionBlotValue {
export type MentionBlotValue = {
uuid: string;
title: string;
}
};
export const isMentionBlot = (blot: LeafBlot): blot is MentionBlot =>
blot.value() && blot.value().mention;

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 @typescript-eslint/ban-types */
@ -30,7 +30,7 @@ export type StickerPackType = any;
export type StickerType = any;
export type UnprocessedType = any;
export interface DataInterface {
export type DataInterface = {
close: () => Promise<void>;
removeDB: () => Promise<void>;
removeIndexedDBFiles: () => Promise<void>;
@ -188,7 +188,7 @@ export interface DataInterface {
conversationId: string,
options: { limit: number }
) => Promise<Array<MessageType>>;
}
};
// The reason for client/server divergence is the need to inject Backbone models and
// collections into data calls so those are the objects returned. This was necessary 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
/* eslint-disable no-nested-ternary */
@ -56,6 +56,8 @@ import {
} from './Interface';
declare global {
// We want to extend `Function`'s properties, so we need to use an interface.
// eslint-disable-next-line no-restricted-syntax
interface Function {
needsSerial?: boolean;
}

6
ts/sqlcipher.d.ts vendored
View File

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
// Taken from:
@ -35,10 +35,10 @@ declare module '@journeyapps/sqlcipher' {
): Database;
};
export interface RunResult extends Statement {
export type RunResult = Statement & {
lastID: number;
changes: number;
}
};
export class Statement {
bind(callback?: (err: Error | null) => void): this;

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
/* eslint-disable no-console */
@ -17,7 +17,8 @@ import { createLogger } from 'redux-logger';
import { reducer, StateType } from './reducer';
declare global {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
// We want to extend `window`'s properties, so we need an interface.
// eslint-disable-next-line no-restricted-syntax, @typescript-eslint/no-unused-vars
interface Console {
_log: Console['log'];
}

View File

@ -30,24 +30,24 @@ import { LatestQueue } from '../../util/LatestQueue';
// State
export interface GroupCallPeekInfoType {
export type GroupCallPeekInfoType = {
uuids: Array<string>;
creatorUuid?: string;
eraId?: string;
maxDevices: number;
deviceCount: number;
}
};
export interface GroupCallParticipantInfoType {
export type GroupCallParticipantInfoType = {
uuid: string;
demuxId: number;
hasRemoteAudio: boolean;
hasRemoteVideo: boolean;
speakerTime?: number;
videoAspectRatio: number;
}
};
export interface DirectCallStateType {
export type DirectCallStateType = {
callMode: CallMode.Direct;
conversationId: string;
callState?: CallState;
@ -55,18 +55,18 @@ export interface DirectCallStateType {
isIncoming: boolean;
isVideoCall: boolean;
hasRemoteVideo?: boolean;
}
};
export interface GroupCallStateType {
export type GroupCallStateType = {
callMode: CallMode.Group;
conversationId: string;
connectionState: GroupCallConnectionState;
joinState: GroupCallJoinState;
peekInfo: GroupCallPeekInfoType;
remoteParticipants: Array<GroupCallParticipantInfoType>;
}
};
export interface ActiveCallStateType {
export type ActiveCallStateType = {
conversationId: string;
hasLocalAudio: boolean;
hasLocalVideo: boolean;
@ -76,11 +76,11 @@ export interface ActiveCallStateType {
safetyNumberChangedUuids: Array<string>;
settingsDialogOpen: boolean;
showParticipantsList: boolean;
}
};
export interface CallsByConversationType {
export type CallsByConversationType = {
[conversationId: string]: DirectCallStateType | GroupCallStateType;
}
};
export type CallingStateType = MediaDeviceSettings & {
callsByConversation: CallsByConversationType;
@ -145,15 +145,15 @@ type PeekNotConnectedGroupCallType = {
conversationId: string;
};
interface StartDirectCallType {
type StartDirectCallType = {
conversationId: string;
hasLocalAudio: boolean;
hasLocalVideo: boolean;
}
};
export interface StartCallType extends StartDirectCallType {
export type StartCallType = StartDirectCallType & {
callMode: CallMode.Direct | CallMode.Group;
}
};
export type RemoteVideoChangeType = {
conversationId: string;

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 { connect } from 'react-redux';
@ -20,7 +20,7 @@ import { getOwn } from '../../util/getOwn';
import { missingCaseError } from '../../util/missingCaseError';
import { isGroupCallingEnabled } from '../../util/isGroupCallingEnabled';
export interface OwnProps {
export type OwnProps = {
id: string;
onDeleteMessages: () => void;
@ -39,7 +39,7 @@ export interface OwnProps {
onMarkUnread: () => void;
onMoveToInbox: () => void;
onShowSafetyNumber: () => void;
}
};
const getOutgoingCallButtonStyle = (
conversation: ConversationType,

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 { assert } from 'chai';
@ -6,10 +6,10 @@ import { assert } from 'chai';
import { assignWithNoUnnecessaryAllocation } from '../../util/assignWithNoUnnecessaryAllocation';
describe('assignWithNoUnnecessaryAllocation', () => {
interface Person {
type Person = {
name?: string;
age?: number;
}
};
it('returns the same object if there are no modifications', () => {
const empty = {};

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 { assert } from 'chai';
@ -69,14 +69,14 @@ const memberRepositoryRef: RefObject<MemberRepository> = {
const matcher = matchMention(memberRepositoryRef);
interface Mention {
type Mention = {
uuid: string;
title: string;
}
};
interface MentionInsert {
type MentionInsert = {
mention: Mention;
}
};
const isMention = (insert?: unknown): insert is MentionInsert => {
if (insert) {

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 @typescript-eslint/no-explicit-any */
@ -9,6 +9,8 @@ import { ByteBufferClass } from '../window.d';
declare global {
// this is fixed in already, and won't be necessary when the new definitions
// files are used: https://github.com/microsoft/TSJS-lib-generator/pull/843
// We want to extend `SubtleCrypto`, so we need an interface.
// eslint-disable-next-line no-restricted-syntax
export interface SubtleCrypto {
decrypt(
algorithm:
@ -108,10 +110,10 @@ const PROFILE_KEY_LENGTH = 32; // bytes
const PROFILE_TAG_LENGTH = 128; // bits
const PROFILE_NAME_PADDED_LENGTH = 53; // bytes
interface EncryptedAttachment {
type EncryptedAttachment = {
ciphertext: ArrayBuffer;
digest: ArrayBuffer;
}
};
async function verifyDigest(
data: ArrayBuffer,

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 @typescript-eslint/ban-types */
@ -49,6 +49,8 @@ const GROUPV2_ID_LENGTH = 32;
const RETRY_TIMEOUT = 2 * 60 * 1000;
declare global {
// We want to extend `Event`, so we need an interface.
// eslint-disable-next-line no-restricted-syntax
interface Event {
code?: string | number;
configuration?: any;
@ -79,6 +81,8 @@ declare global {
typing?: any;
verified?: any;
}
// We want to extend `Error`, so we need an interface.
// eslint-disable-next-line no-restricted-syntax
interface Error {
reason?: any;
stackForLog?: string;

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 no-nested-ternary */
@ -70,10 +70,10 @@ export type SendOptionsType = {
online?: boolean;
};
export interface CustomError extends Error {
export type CustomError = Error & {
identifier?: string;
number?: string;
}
};
export type CallbackResultType = {
successfulIdentifiers?: Array<any>;
@ -105,9 +105,9 @@ type GroupV1InfoType = {
members: Array<string>;
};
interface GroupCallUpdateType {
type GroupCallUpdateType = {
eraId: string;
}
};
type MessageOptionsType = {
attachments?: Array<AttachmentType> | null;

View File

@ -1,11 +1,11 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* eslint-disable @typescript-eslint/no-explicit-any */
import utils from './Helpers';
// Default implmentation working with localStorage
const localStorageImpl = {
const localStorageImpl: StorageInterface = {
put(key: string, value: any) {
if (value === undefined) {
throw new Error('Tried to store undefined');
@ -26,14 +26,14 @@ const localStorageImpl = {
},
};
export interface StorageInterface {
export type StorageInterface = {
put(key: string, value: any): void | Promise<void>;
get(key: string, defaultValue: any): any;
remove(key: string): void | Promise<void>;
}
};
const Storage = {
impl: localStorageImpl as StorageInterface,
impl: localStorageImpl,
put(key: string, value: unknown): Promise<void> | void {
return Storage.impl.put(key, value);

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 no-param-reassign */
@ -586,6 +586,8 @@ async function _outerAjax(url: string | null, options: PromiseAjaxOptionsType) {
}
declare global {
// We want to extend `Error`, so we need an interface.
// eslint-disable-next-line no-restricted-syntax
interface Error {
code?: number | string;
response?: any;

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 is from '@sindresorhus/is';
@ -20,7 +20,7 @@ const MIN_HEIGHT = 50;
// Used for display
export interface AttachmentType {
export type AttachmentType = {
blurHash?: string;
caption?: string;
contentType: MIME.MIMEType;
@ -47,7 +47,7 @@ export interface AttachmentType {
url: string;
contentType: MIME.MIMEType;
};
}
};
// UI-focused functions
@ -288,9 +288,9 @@ export type Attachment = {
// digest?: ArrayBuffer;
} & Partial<AttachmentSchemaVersion3>;
interface AttachmentSchemaVersion3 {
type AttachmentSchemaVersion3 = {
path: string;
}
};
export const isVisualMedia = (attachment: Attachment): boolean => {
const { contentType } = attachment;

View File

@ -10,7 +10,7 @@ export enum CallMode {
Group = 'Group',
}
interface ActiveCallBaseType {
type ActiveCallBaseType = {
conversation: ConversationType;
hasLocalAudio: boolean;
hasLocalVideo: boolean;
@ -20,9 +20,9 @@ interface ActiveCallBaseType {
settingsDialogOpen: boolean;
showParticipantsList: boolean;
showSafetyNumberDialog?: boolean;
}
};
interface ActiveDirectCallType extends ActiveCallBaseType {
type ActiveDirectCallType = ActiveCallBaseType & {
callMode: CallMode.Direct;
callState?: CallState;
callEndedReason?: CallEndedReason;
@ -32,9 +32,9 @@ interface ActiveDirectCallType extends ActiveCallBaseType {
hasRemoteVideo: boolean;
}
];
}
};
interface ActiveGroupCallType extends ActiveCallBaseType {
type ActiveGroupCallType = ActiveCallBaseType & {
callMode: CallMode.Group;
connectionState: GroupCallConnectionState;
conversationsWithSafetyNumberChanges: Array<ConversationType>;
@ -43,7 +43,7 @@ interface ActiveGroupCallType extends ActiveCallBaseType {
deviceCount: number;
peekedParticipants: Array<ConversationType>;
remoteParticipants: Array<GroupCallRemoteParticipantType>;
}
};
export type ActiveCallType = ActiveDirectCallType | ActiveGroupCallType;
@ -96,28 +96,28 @@ export enum GroupCallJoinState {
Joined = 2,
}
export interface GroupCallRemoteParticipantType extends ConversationType {
export type GroupCallRemoteParticipantType = ConversationType & {
demuxId: number;
hasRemoteAudio: boolean;
hasRemoteVideo: boolean;
speakerTime?: number;
videoAspectRatio: number;
}
};
// Similar to RingRTC's `VideoRequest` but without the `framerate` property.
export interface GroupCallVideoRequest {
export type GroupCallVideoRequest = {
demuxId: number;
width: number;
height: number;
}
};
// Should match RingRTC's VideoFrameSource
export interface VideoFrameSource {
export type VideoFrameSource = {
receiveVideoFrame(buffer: ArrayBuffer): [number, number] | undefined;
}
};
// Must be kept in sync with RingRTC.AudioDevice
export interface AudioDevice {
export type AudioDevice = {
// Device name.
name: string;
// Index of this device, starting from 0.
@ -126,7 +126,7 @@ export interface AudioDevice {
uniqueId: string;
// If present, the identifier of a localized string to substitute for the device name.
i18nKey?: string;
}
};
export enum CallingDeviceType {
CAMERA,
@ -143,21 +143,21 @@ export type MediaDeviceSettings = {
selectedCamera: string | undefined;
};
interface DirectCallHistoryDetailsType {
type DirectCallHistoryDetailsType = {
callMode: CallMode.Direct;
wasIncoming: boolean;
wasVideoCall: boolean;
wasDeclined: boolean;
acceptedTime?: number;
endedTime: number;
}
};
interface GroupCallHistoryDetailsType {
type GroupCallHistoryDetailsType = {
callMode: CallMode.Group;
creatorUuid: string;
eraId: string;
startedTime: number;
}
};
export type CallHistoryDetailsType =
| DirectCallHistoryDetailsType

View File

@ -1,9 +1,9 @@
// Copyright 2019-2020 Signal Messenger, LLC
// Copyright 2019-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { format as formatPhoneNumber } from './PhoneNumber';
export interface ContactType {
export type ContactType = {
name?: Name;
number?: Array<Phone>;
email?: Array<Email>;
@ -11,16 +11,16 @@ export interface ContactType {
avatar?: Avatar;
organization?: string;
signalAccount?: string;
}
};
interface Name {
type Name = {
givenName?: string;
familyName?: string;
prefix?: string;
suffix?: string;
middleName?: string;
displayName?: string;
}
};
export enum ContactFormType {
HOME = 1,
@ -35,19 +35,19 @@ export enum AddressType {
CUSTOM = 3,
}
export interface Phone {
export type Phone = {
value: string;
type: ContactFormType;
label?: string;
}
};
export interface Email {
export type Email = {
value: string;
type: ContactFormType;
label?: string;
}
};
export interface PostalAddress {
export type PostalAddress = {
type: AddressType;
label?: string;
street?: string;
@ -57,18 +57,18 @@ export interface PostalAddress {
region?: string;
postcode?: string;
country?: string;
}
};
interface Avatar {
type Avatar = {
avatar: Attachment;
isProfile: boolean;
}
};
interface Attachment {
type Attachment = {
path?: string;
error?: boolean;
pending?: boolean;
}
};
export function contactSelector(
contact: ContactType,

View File

@ -1,13 +1,13 @@
// Copyright 2018-2020 Signal Messenger, LLC
// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
export interface BodyRangeType {
export type BodyRangeType = {
start: number;
length: number;
mentionUuid: string;
replacementText: string;
conversationID?: string;
}
};
export type BodyRangesType = Array<BodyRangeType>;

View File

@ -3,7 +3,7 @@
import { AttachmentType } from '../Attachment';
export interface LinkPreviewType {
export type LinkPreviewType = {
title: string;
description?: string;
domain: string;
@ -11,4 +11,4 @@ export interface LinkPreviewType {
isStickerPack: boolean;
image?: AttachmentType;
date?: number;
}
};

View File

@ -1,11 +1,9 @@
// Copyright 2018-2020 Signal Messenger, LLC
// Copyright 2018-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import * as MIME from '../types/MIME';
interface MIMETypeSupportMap {
[key: string]: boolean;
}
type MIMETypeSupportMap = Record<string, boolean>;
// See: https://en.wikipedia.org/wiki/Comparison_of_web_browsers#Image_format_support
const SUPPORTED_IMAGE_MIME_TYPES: MIMETypeSupportMap = {

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 PQueue from 'p-queue';
@ -6,6 +6,8 @@ import PQueue from 'p-queue';
import { sleep } from './sleep';
declare global {
// We want to extend `window`'s properties, so we need an interface.
// eslint-disable-next-line no-restricted-syntax
interface Window {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
batchers: Array<BatcherType<any>>;

View File

@ -1,20 +1,20 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { LocalizerType } from '../types/Util';
import { CallMode } from '../types/Calling';
import { missingCaseError } from './missingCaseError';
interface DirectCallNotificationType {
type DirectCallNotificationType = {
callMode: CallMode.Direct;
wasIncoming: boolean;
wasVideoCall: boolean;
wasDeclined: boolean;
acceptedTime?: number;
endedTime: number;
}
};
interface GroupCallNotificationType {
type GroupCallNotificationType = {
activeCallConversationId?: string;
callMode: CallMode.Group;
conversationId: string;
@ -27,7 +27,7 @@ interface GroupCallNotificationType {
deviceCount: number;
maxDevices: number;
startedTime: number;
}
};
export type CallingNotificationType =
| DirectCallNotificationType

View File

@ -1,4 +1,4 @@
// Copyright 2020 Signal Messenger, LLC
// Copyright 2020-2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
const PNG_SIGNATURE = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]);
@ -6,9 +6,9 @@ const ACTL_CHUNK_BYTES = new TextEncoder().encode('acTL');
const IDAT_CHUNK_BYTES = new TextEncoder().encode('IDAT');
const MAX_BYTES_TO_READ = 1024 * 1024;
interface AnimatedPngData {
type AnimatedPngData = {
numPlays: number;
}
};
/**
* This is a naïve implementation. It only performs two checks:

Some files were not shown because too many files have changed in this diff Show More