diff --git a/.eslintignore b/.eslintignore index 117780711..87ca3b3c1 100644 --- a/.eslintignore +++ b/.eslintignore @@ -15,6 +15,7 @@ libtextsecure/components.js libtextsecure/test/test.js test/test.js sticker-creator/dist/** +ts/protobuf/compiled.d.ts # Third-party files js/Mp3LameEncoder.min.js @@ -25,7 +26,6 @@ app/**/*.js ts/**/*.js sticker-creator/**/*.js -**/*.d.ts .eslintrc.js webpack.config.ts preload.bundle.* diff --git a/ts/model-types.d.ts b/ts/model-types.d.ts index ad3ed4df9..82fb73933 100644 --- a/ts/model-types.d.ts +++ b/ts/model-types.d.ts @@ -1,42 +1,39 @@ // Copyright 2020-2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only +/* eslint-disable max-classes-per-file */ + import * as Backbone from 'backbone'; -import { GroupV2ChangeType } from './groups'; -import { BodyRangeType, BodyRangesType } from './types/Util'; -import { CallHistoryDetailsFromDiskType } from './types/Calling'; -import { CustomColorType } from './types/Colors'; -import { DeviceType } from './textsecure/Types'; -import { SendMessageChallengeData } from './textsecure/Errors'; -import { MessageModel } from './models/messages'; -import { ConversationModel } from './models/conversations'; -import { ProfileNameChangeType } from './util/getStringForProfileChange'; -import { CapabilitiesType } from './textsecure/WebAPI'; -import { ReadStatus } from './messages/MessageReadStatus'; -import { SendStateByConversationId } from './messages/MessageSendState'; -import { GroupNameCollisionsWithIdsByTitle } from './util/groupMemberNameCollisions'; -import { ConversationColorType } from './types/Colors'; -import { - AttachmentDraftType, - AttachmentType, - ThumbnailType, -} from './types/Attachment'; -import { EmbeddedContactType } from './types/EmbeddedContact'; +import type { GroupV2ChangeType } from './groups'; +import type { BodyRangeType, BodyRangesType } from './types/Util'; +import type { CallHistoryDetailsFromDiskType } from './types/Calling'; +import type { CustomColorType, ConversationColorType } from './types/Colors'; +import type { DeviceType } from './textsecure/Types.d'; +import type { SendMessageChallengeData } from './textsecure/Errors'; +import type { MessageModel } from './models/messages'; +import type { ConversationModel } from './models/conversations'; +import type { ProfileNameChangeType } from './util/getStringForProfileChange'; +import type { CapabilitiesType } from './textsecure/WebAPI'; +import type { ReadStatus } from './messages/MessageReadStatus'; +import type { SendStateByConversationId } from './messages/MessageSendState'; +import type { GroupNameCollisionsWithIdsByTitle } from './util/groupMemberNameCollisions'; + +import type { AttachmentDraftType, AttachmentType } from './types/Attachment'; +import type { EmbeddedContactType } from './types/EmbeddedContact'; import { SignalService as Proto } from './protobuf'; -import { AvatarDataType } from './types/Avatar'; -import { UUIDStringType, UUIDKind } from './types/UUID'; -import { ReactionSource } from './reactions/ReactionSource'; +import type { AvatarDataType } from './types/Avatar'; +import type { UUIDStringType } from './types/UUID'; +import type { ReactionSource } from './reactions/ReactionSource'; +import type { SeenStatus } from './MessageSeenStatus'; +import type { GiftBadgeStates } from './components/conversation/Message'; +import type { LinkPreviewType } from './types/message/LinkPreviews'; + +import type { StickerType } from './types/Stickers'; +import type { MIMEType } from './types/MIME'; import AccessRequiredEnum = Proto.AccessControl.AccessRequired; import MemberRoleEnum = Proto.Member.Role; -import { SeenStatus } from './MessageSeenStatus'; -import { GiftBadgeStates } from './components/conversation/Message'; -import { LinkPreviewType } from './types/message/LinkPreviews'; - -import type { ProcessedQuoteAttachment } from './textsecure/Types.d'; -import type { StickerType } from './types/Stickers'; -import { MIMEType } from './types/MIME'; export type LastMessageStatus = | 'paused' @@ -48,8 +45,6 @@ export type LastMessageStatus = | 'read' | 'viewed'; -type TaskResultType = any; - export type SenderKeyInfoType = { createdAtDate: number; distributionId: string; @@ -77,7 +72,7 @@ export type QuotedAttachment = { export type QuotedMessageType = { // TODO DESKTOP-3826 - // eslint-disable-next-line no-explicit-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any attachments: Array; // `author` is an old attribute that holds the author's E164. We shouldn't use it for // new messages, but old messages might have this attribute. @@ -121,6 +116,7 @@ export type MessageReactionType = { isSentByConversationId?: Record; }; +/* eslint-disable camelcase */ export type MessageAttributesType = { bodyAttachment?: AttachmentType; bodyRanges?: BodyRangesType; @@ -242,6 +238,7 @@ export type MessageAttributesType = { deletedForEveryoneSendStatus?: Record; deletedForEveryoneFailed?: boolean; }; +/* eslint-enable camelcase */ export type ConversationAttributesTypeType = 'private' | 'group'; @@ -255,6 +252,7 @@ export type ValidateConversationType = Pick< 'e164' | 'uuid' | 'type' | 'groupId' >; +/* eslint-disable camelcase */ export type ConversationAttributesType = { accessKey?: string | null; addedBy?: string; @@ -395,6 +393,7 @@ export type ConversationAttributesType = { // up in that case). unblurredAvatarPath?: string; }; +/* eslint-enable camelcase */ export type GroupV2MemberType = { uuid: UUIDStringType; diff --git a/ts/mp4box.d.ts b/ts/mp4box.d.ts index a55da60c0..3fa633aad 100644 --- a/ts/mp4box.d.ts +++ b/ts/mp4box.d.ts @@ -1,6 +1,8 @@ // Copyright 2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only +/* eslint-disable camelcase */ + declare module 'mp4box' { type MP4MediaTrack = { alternate_group: number; diff --git a/ts/quill/types.d.ts b/ts/quill/types.d.ts index 4ce6c33f7..35767afa2 100644 --- a/ts/quill/types.d.ts +++ b/ts/quill/types.d.ts @@ -1,9 +1,9 @@ -// Copyright 2019-2021 Signal Messenger, LLC +// Copyright 2019-2022 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import UpdatedDelta from 'quill-delta'; -import { MentionCompletion } from './mentions/completion'; -import { EmojiCompletion } from './emoji/completion'; +import type UpdatedDelta from 'quill-delta'; +import type { MentionCompletion } from './mentions/completion'; +import type { EmojiCompletion } from './emoji/completion'; declare module 'react-quill' { // `react-quill` uses a different but compatible version of Delta @@ -31,6 +31,9 @@ declare module 'quill' { interface LeafBlot { text?: string; + // Quill doesn't make it easy to type this result. + // (It's probably doable, but not worth our time.) + // eslint-disable-next-line @typescript-eslint/no-explicit-any value(): any; } diff --git a/ts/textsecure/Types.d.ts b/ts/textsecure/Types.d.ts index e11b80e0e..066edb1e6 100644 --- a/ts/textsecure/Types.d.ts +++ b/ts/textsecure/Types.d.ts @@ -5,8 +5,8 @@ import type { SignalService as Proto } from '../protobuf'; import type { IncomingWebSocketRequest } from './WebsocketResources'; import type { UUID, UUIDStringType } from '../types/UUID'; import type { TextAttachmentType } from '../types/Attachment'; -import { GiftBadgeStates } from '../components/conversation/Message'; -import { MIMEType } from '../types/MIME'; +import type { GiftBadgeStates } from '../components/conversation/Message'; +import type { MIMEType } from '../types/MIME'; export { IdentityKeyType, diff --git a/ts/types/Storage.d.ts b/ts/types/Storage.d.ts index 80251bf81..3ee848671 100644 --- a/ts/types/Storage.d.ts +++ b/ts/types/Storage.d.ts @@ -12,7 +12,7 @@ import type { PhoneNumberSharingMode } from '../util/phoneNumberSharingMode'; import type { RetryItemType } from '../util/retryPlaceholders'; import type { ConfigMapType as RemoteConfigType } from '../RemoteConfig'; import type { SystemTraySetting } from './SystemTraySetting'; -import type { ExtendedStorageID, UnknownRecord } from './StorageService'; +import type { ExtendedStorageID, UnknownRecord } from './StorageService.d'; import type { GroupCredentialType } from '../textsecure/WebAPI'; import type { @@ -21,7 +21,7 @@ import type { } from '../textsecure/Types.d'; import type { ThemeSettingType } from './StorageUIKeys'; -import { RegisteredChallengeType } from '../challenge'; +import type { RegisteredChallengeType } from '../challenge'; export type SerializedCertificateType = { expires: number; @@ -41,6 +41,7 @@ export type IdentityKeyMap = Record< >; // This should be in sync with `STORAGE_UI_KEYS` in `ts/types/StorageUIKeys.ts`. +/* eslint-disable camelcase */ export type StorageAccessType = { 'always-relay-calls': boolean; 'audio-notification': boolean; @@ -144,6 +145,7 @@ export type StorageAccessType = { signaling_key: never; 'challenge:retry-message-ids': never; }; +/* eslint-enable camelcase */ export type StorageInterface = { onready(callback: () => void): void; diff --git a/ts/window.d.ts b/ts/window.d.ts index b5992ebf5..09d57afa0 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -3,98 +3,100 @@ // Captures the globals put in place by preload.js, background.js and others -import type { Cancelable } from 'lodash'; -import { Store } from 'redux'; -import * as Backbone from 'backbone'; -import * as Underscore from 'underscore'; -import PQueue from 'p-queue/dist'; -import { Ref } from 'react'; -import { assert } from 'chai'; +/* eslint-disable max-classes-per-file */ -import { imageToBlurHash } from './util/imageToBlurHash'; -import * as Util from './util'; -import { +import type { Cancelable } from 'lodash'; +import type { Store } from 'redux'; +import type * as Backbone from 'backbone'; +import type * as Underscore from 'underscore'; +import type PQueue from 'p-queue/dist'; +import type { Ref } from 'react'; +import type { assert } from 'chai'; +import type * as Mustache from 'mustache'; + +import type { PhoneNumber, PhoneNumberFormat } from 'google-libphonenumber'; +import type { imageToBlurHash } from './util/imageToBlurHash'; +import type * as Util from './util'; +import type { ConversationModelCollectionType, MessageModelCollectionType, } from './model-types.d'; -import { textsecure } from './textsecure'; -import { Storage } from './textsecure/Storage'; -import { +import type { textsecure } from './textsecure'; +import type { Storage } from './textsecure/Storage'; +import type { ChallengeHandler, IPCRequest as IPCChallengeRequest, } from './challenge'; -import { WebAPIConnectType } from './textsecure/WebAPI'; -import { CallingClass } from './services/calling'; -import * as Groups from './groups'; -import * as Crypto from './Crypto'; -import * as Curve from './Curve'; -import * as RemoteConfig from './RemoteConfig'; -import * as OS from './OS'; -import { Environment, getEnvironment } from './environment'; -import { LocalizerType, ThemeType } from './types/Util'; +import type { WebAPIConnectType } from './textsecure/WebAPI'; +import type { CallingClass } from './services/calling'; +import type * as Groups from './groups'; +import type * as Crypto from './Crypto'; +import type * as Curve from './Curve'; +import type * as RemoteConfig from './RemoteConfig'; +import type * as OS from './OS'; +import type { getEnvironment } from './environment'; +import type { LocalizerType, ThemeType } from './types/Util'; import type { Receipt } from './types/Receipt'; -import { ConversationController } from './ConversationController'; -import { ReduxActions } from './state/types'; -import { createStore } from './state/createStore'; -import { createApp } from './state/roots/createApp'; -import { createChatColorPicker } from './state/roots/createChatColorPicker'; -import { createConversationDetails } from './state/roots/createConversationDetails'; -import { createGroupLinkManagement } from './state/roots/createGroupLinkManagement'; -import { createGroupV1MigrationModal } from './state/roots/createGroupV1MigrationModal'; -import { createGroupV2JoinModal } from './state/roots/createGroupV2JoinModal'; -import { createGroupV2Permissions } from './state/roots/createGroupV2Permissions'; -import { createMessageDetail } from './state/roots/createMessageDetail'; -import { createConversationNotificationsSettings } from './state/roots/createConversationNotificationsSettings'; -import { createPendingInvites } from './state/roots/createPendingInvites'; -import { createSafetyNumberViewer } from './state/roots/createSafetyNumberViewer'; -import { createShortcutGuideModal } from './state/roots/createShortcutGuideModal'; -import { createStickerManager } from './state/roots/createStickerManager'; -import { createStickerPreviewModal } from './state/roots/createStickerPreviewModal'; -import * as appDuck from './state/ducks/app'; -import * as callingDuck from './state/ducks/calling'; -import * as conversationsDuck from './state/ducks/conversations'; -import * as emojisDuck from './state/ducks/emojis'; -import * as expirationDuck from './state/ducks/expiration'; -import * as itemsDuck from './state/ducks/items'; -import * as linkPreviewsDuck from './state/ducks/linkPreviews'; -import * as networkDuck from './state/ducks/network'; -import * as updatesDuck from './state/ducks/updates'; -import * as userDuck from './state/ducks/user'; -import * as searchDuck from './state/ducks/search'; -import * as stickersDuck from './state/ducks/stickers'; -import * as conversationsSelectors from './state/selectors/conversations'; -import * as searchSelectors from './state/selectors/search'; -import AccountManager from './textsecure/AccountManager'; -import Data from './sql/Client'; -import { PhoneNumber, PhoneNumberFormat } from 'google-libphonenumber'; -import { MessageModel } from './models/messages'; -import { ConversationModel } from './models/conversations'; -import { BatcherType } from './util/batcher'; -import { AttachmentList } from './components/conversation/AttachmentList'; -import { ChatColorPicker } from './components/ChatColorPicker'; -import { ConfirmationDialog } from './components/ConfirmationDialog'; -import { ContactModal } from './components/conversation/ContactModal'; -import { MessageDetail } from './components/conversation/MessageDetail'; -import { Quote } from './components/conversation/Quote'; -import { StagedLinkPreview } from './components/conversation/StagedLinkPreview'; -import { DisappearingTimeDialog } from './components/DisappearingTimeDialog'; -import { SignalProtocolStore } from './SignalProtocolStore'; -import { StartupQueue } from './util/StartupQueue'; -import { SocketStatus } from './types/SocketStatus'; -import SyncRequest from './textsecure/SyncRequest'; -import { MessageController } from './util/MessageController'; -import { StateType } from './state/reducer'; -import { SystemTraySetting } from './types/SystemTraySetting'; -import { UUID } from './types/UUID'; -import { Address } from './types/Address'; -import { QualifiedAddress } from './types/QualifiedAddress'; -import { CI } from './CI'; -import { IPCEventsType } from './util/createIPCEvents'; -import { ConversationView } from './views/conversation_view'; +import type { ConversationController } from './ConversationController'; +import type { ReduxActions } from './state/types'; +import type { createStore } from './state/createStore'; +import type { createApp } from './state/roots/createApp'; +import type { createChatColorPicker } from './state/roots/createChatColorPicker'; +import type { createConversationDetails } from './state/roots/createConversationDetails'; +import type { createGroupLinkManagement } from './state/roots/createGroupLinkManagement'; +import type { createGroupV1MigrationModal } from './state/roots/createGroupV1MigrationModal'; +import type { createGroupV2JoinModal } from './state/roots/createGroupV2JoinModal'; +import type { createGroupV2Permissions } from './state/roots/createGroupV2Permissions'; +import type { createMessageDetail } from './state/roots/createMessageDetail'; +import type { createConversationNotificationsSettings } from './state/roots/createConversationNotificationsSettings'; +import type { createPendingInvites } from './state/roots/createPendingInvites'; +import type { createSafetyNumberViewer } from './state/roots/createSafetyNumberViewer'; +import type { createShortcutGuideModal } from './state/roots/createShortcutGuideModal'; +import type { createStickerManager } from './state/roots/createStickerManager'; +import type { createStickerPreviewModal } from './state/roots/createStickerPreviewModal'; +import type * as appDuck from './state/ducks/app'; +import type * as callingDuck from './state/ducks/calling'; +import type * as conversationsDuck from './state/ducks/conversations'; +import type * as emojisDuck from './state/ducks/emojis'; +import type * as expirationDuck from './state/ducks/expiration'; +import type * as itemsDuck from './state/ducks/items'; +import type * as linkPreviewsDuck from './state/ducks/linkPreviews'; +import type * as networkDuck from './state/ducks/network'; +import type * as updatesDuck from './state/ducks/updates'; +import type * as userDuck from './state/ducks/user'; +import type * as searchDuck from './state/ducks/search'; +import type * as stickersDuck from './state/ducks/stickers'; +import type * as conversationsSelectors from './state/selectors/conversations'; +import type * as searchSelectors from './state/selectors/search'; +import type AccountManager from './textsecure/AccountManager'; +import type Data from './sql/Client'; +import type { MessageModel } from './models/messages'; +import type { ConversationModel } from './models/conversations'; +import type { BatcherType } from './util/batcher'; +import type { AttachmentList } from './components/conversation/AttachmentList'; +import type { ChatColorPicker } from './components/ChatColorPicker'; +import type { ConfirmationDialog } from './components/ConfirmationDialog'; +import type { ContactModal } from './components/conversation/ContactModal'; +import type { MessageDetail } from './components/conversation/MessageDetail'; +import type { Quote } from './components/conversation/Quote'; +import type { StagedLinkPreview } from './components/conversation/StagedLinkPreview'; +import type { DisappearingTimeDialog } from './components/DisappearingTimeDialog'; +import type { SignalProtocolStore } from './SignalProtocolStore'; +import type { StartupQueue } from './util/StartupQueue'; +import type { SocketStatus } from './types/SocketStatus'; +import type SyncRequest from './textsecure/SyncRequest'; +import type { MessageController } from './util/MessageController'; +import type { StateType } from './state/reducer'; +import type { SystemTraySetting } from './types/SystemTraySetting'; +import type { UUID } from './types/UUID'; +import type { Address } from './types/Address'; +import type { QualifiedAddress } from './types/QualifiedAddress'; +import type { CI } from './CI'; +import type { IPCEventsType } from './util/createIPCEvents'; +import type { ConversationView } from './views/conversation_view'; import type { SignalContextType } from './windows/context'; import type * as Message2 from './types/Message2'; import type { initializeMigrations } from './signal'; -import { RendererConfigType } from './types/RendererConfig'; export { Long } from 'long'; @@ -213,8 +215,8 @@ export type SignalCoreType = { }; declare global { - // We want to extend `window`'s properties, so we need an interface. - // eslint-disable-next-line no-restricted-syntax + // We want to extend various globals, so we need to use interfaces. + /* eslint-disable no-restricted-syntax */ interface Window { // Used in Sticker Creator to create proper paths to emoji images ROOT_PATH?: string; @@ -238,15 +240,11 @@ declare global { $: typeof jQuery; imageToBlurHash: typeof imageToBlurHash; - loadImage: any; isBehindProxy: () => boolean; getAutoLaunch: () => Promise; setAutoLaunch: (value: boolean) => Promise; - Mustache: { - render: (template: string, data: any, partials?: any) => string; - parse: (template: string) => void; - }; + Mustache: typeof Mustache; WebAudioRecorder: typeof WebAudioRecorderClass; addSetupMenuItems: () => void; @@ -358,26 +356,21 @@ declare global { // Test only assert: typeof assert; - // Used in test/index.html, and therefore not type-checked! testUtilities: { - onComplete: (data: any) => void; + onComplete: (info: unknown) => void; prepareTests: () => void; }; } - // We want to extend `Error`, so we need an interface. - // eslint-disable-next-line no-restricted-syntax interface Error { originalError?: Event; - reason?: any; + reason?: unknown; stackForLog?: string; // Used in sticker creator to attach messages to errors errorMessageI18nKey?: string; } - // We want to extend `Element`'s properties, so we need an interface. - // eslint-disable-next-line no-restricted-syntax interface Element { // WebKit-specific scrollIntoViewIfNeeded: (bringToCenter?: boolean) => void; @@ -390,18 +383,14 @@ declare global { } interface ArrayBuffer { - __array_buffer: never; + __arrayBuffer: never; } interface SharedArrayBuffer { - __array_buffer: never; + __arrayBuffer: never; } } -export class CertificateValidatorType { - validate: (cerficate: any, certificateTime: number) => Promise; -} - export class GumVideoCapturer { constructor( maxWidth: number,