Add type-alias-readonlydeep rule and make ducks mostly immutable
This commit is contained in:
parent
11ce3c3d59
commit
c58a723f45
58
.eslint/rules/type-alias-readonlydeep.js
Normal file
58
.eslint/rules/type-alias-readonlydeep.js
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright 2023 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
function isReadOnlyDeep(node, scope) {
|
||||||
|
if (node.type !== 'TSTypeReference') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let reference = scope.references.find(reference => {
|
||||||
|
return reference.identifier === node.typeName;
|
||||||
|
});
|
||||||
|
|
||||||
|
let variable = reference.resolved;
|
||||||
|
if (variable == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let defs = variable.defs;
|
||||||
|
if (defs.length !== 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let [def] = defs;
|
||||||
|
|
||||||
|
return (
|
||||||
|
def.type === 'ImportBinding' &&
|
||||||
|
def.parent.type === 'ImportDeclaration' &&
|
||||||
|
def.parent.source.type === 'Literal' &&
|
||||||
|
def.parent.source.value === 'type-fest'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {import("eslint").Rule.RuleModule} */
|
||||||
|
module.exports = {
|
||||||
|
meta: {
|
||||||
|
type: 'problem',
|
||||||
|
hasSuggestions: false,
|
||||||
|
fixable: false,
|
||||||
|
schema: [],
|
||||||
|
},
|
||||||
|
create(context) {
|
||||||
|
return {
|
||||||
|
TSTypeAliasDeclaration(node) {
|
||||||
|
let scope = context.getScope(node);
|
||||||
|
|
||||||
|
if (isReadOnlyDeep(node.typeAnnotation, scope)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
context.report({
|
||||||
|
node: node.id,
|
||||||
|
message:
|
||||||
|
'Type aliases must be wrapped with ReadonlyDeep from type-fest',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
79
.eslint/rules/type-alias-readonlydeep.test.js
Normal file
79
.eslint/rules/type-alias-readonlydeep.test.js
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// Copyright 2023 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
const rule = require('./type-alias-readonlydeep');
|
||||||
|
const RuleTester = require('eslint').RuleTester;
|
||||||
|
|
||||||
|
// avoid triggering mocha's global leak detection
|
||||||
|
require('@typescript-eslint/parser');
|
||||||
|
|
||||||
|
const ruleTester = new RuleTester({
|
||||||
|
parser: require.resolve('@typescript-eslint/parser'),
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 2018,
|
||||||
|
sourceType: 'module',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
ruleTester.run('type-alias-readonlydeep', rule, {
|
||||||
|
valid: [
|
||||||
|
{
|
||||||
|
code: `import type { ReadonlyDeep } from "type-fest"; type Foo = ReadonlyDeep<{}>`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `import { ReadonlyDeep } from "type-fest"; type Foo = ReadonlyDeep<{}>`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
invalid: [
|
||||||
|
{
|
||||||
|
code: `type Foo = {}`,
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message:
|
||||||
|
'Type aliases must be wrapped with ReadonlyDeep from type-fest',
|
||||||
|
type: 'Identifier',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `type Foo = Bar<{}>`,
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message:
|
||||||
|
'Type aliases must be wrapped with ReadonlyDeep from type-fest',
|
||||||
|
type: 'Identifier',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `type Foo = ReadonlyDeep<{}>`,
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message:
|
||||||
|
'Type aliases must be wrapped with ReadonlyDeep from type-fest',
|
||||||
|
type: 'Identifier',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `interface ReadonlyDeep<T> {}; type Foo = ReadonlyDeep<{}>`,
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message:
|
||||||
|
'Type aliases must be wrapped with ReadonlyDeep from type-fest',
|
||||||
|
type: 'Identifier',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
code: `import type { ReadonlyDeep } from "foo"; type Foo = ReadonlyDeep<{}>`,
|
||||||
|
errors: [
|
||||||
|
{
|
||||||
|
message:
|
||||||
|
'Type aliases must be wrapped with ReadonlyDeep from type-fest',
|
||||||
|
type: 'Identifier',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
|
@ -274,6 +274,12 @@ module.exports = {
|
||||||
'react/no-array-index-key': 'off',
|
'react/no-array-index-key': 'off',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
files: ['ts/state/ducks/**/*.ts'],
|
||||||
|
rules: {
|
||||||
|
'local-rules/type-alias-readonlydeep': 'error',
|
||||||
|
},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
rules: {
|
rules: {
|
||||||
|
|
|
@ -2480,6 +2480,10 @@ Signal Desktop makes use of the following open source projects.
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
## type-fest
|
||||||
|
|
||||||
|
License: (MIT OR CC0-1.0)
|
||||||
|
|
||||||
## typeface-inter
|
## typeface-inter
|
||||||
|
|
||||||
Copyright (c) 2016-2020 The Inter Project Authors.
|
Copyright (c) 2016-2020 The Inter Project Authors.
|
||||||
|
|
|
@ -4,4 +4,5 @@
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
'valid-i18n-keys': require('./.eslint/rules/valid-i18n-keys'),
|
'valid-i18n-keys': require('./.eslint/rules/valid-i18n-keys'),
|
||||||
|
'type-alias-readonlydeep': require('./.eslint/rules/type-alias-readonlydeep'),
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
"test-release": "node ts/scripts/test-release.js",
|
"test-release": "node ts/scripts/test-release.js",
|
||||||
"test-node": "electron-mocha --timeout 10000 --file test/setup-test-node.js --recursive test/modules ts/test-node ts/test-both",
|
"test-node": "electron-mocha --timeout 10000 --file test/setup-test-node.js --recursive test/modules ts/test-node ts/test-both",
|
||||||
"test-mock": "mocha ts/test-mock/**/*_test.js",
|
"test-mock": "mocha ts/test-mock/**/*_test.js",
|
||||||
"test-eslint": "mocha .eslint/rules/**/*.test.js",
|
"test-eslint": "mocha .eslint/rules/**/*.test.js --ignore-leaks",
|
||||||
"test-node-coverage": "nyc --reporter=lcov --reporter=text mocha --recursive test/modules ts/test-node ts/test-both",
|
"test-node-coverage": "nyc --reporter=lcov --reporter=text mocha --recursive test/modules ts/test-node ts/test-both",
|
||||||
"test-lint-intl": "ts-node ./build/intl-linter/linter.ts --test",
|
"test-lint-intl": "ts-node ./build/intl-linter/linter.ts --test",
|
||||||
"eslint": "eslint --cache . --max-warnings 0",
|
"eslint": "eslint --cache . --max-warnings 0",
|
||||||
|
@ -174,6 +174,7 @@
|
||||||
"semver": "5.4.1",
|
"semver": "5.4.1",
|
||||||
"split2": "4.0.0",
|
"split2": "4.0.0",
|
||||||
"testcheck": "1.0.0-rc.2",
|
"testcheck": "1.0.0-rc.2",
|
||||||
|
"type-fest": "3.5.0",
|
||||||
"typeface-inter": "3.18.1",
|
"typeface-inter": "3.18.1",
|
||||||
"uuid": "3.3.2",
|
"uuid": "3.3.2",
|
||||||
"websocket": "1.0.34",
|
"websocket": "1.0.34",
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { createPortal } from 'react-dom';
|
||||||
import { noop } from 'lodash';
|
import { noop } from 'lodash';
|
||||||
import { useSpring, animated, to } from '@react-spring/web';
|
import { useSpring, animated, to } from '@react-spring/web';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type {
|
import type {
|
||||||
ConversationType,
|
ConversationType,
|
||||||
SaveAttachmentActionCreatorType,
|
SaveAttachmentActionCreatorType,
|
||||||
|
@ -29,7 +30,7 @@ export type PropsType = {
|
||||||
getConversation?: (id: string) => ConversationType;
|
getConversation?: (id: string) => ConversationType;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
isViewOnce?: boolean;
|
isViewOnce?: boolean;
|
||||||
media: ReadonlyArray<MediaItemType>;
|
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>;
|
||||||
saveAttachment: SaveAttachmentActionCreatorType;
|
saveAttachment: SaveAttachmentActionCreatorType;
|
||||||
selectedIndex?: number;
|
selectedIndex?: number;
|
||||||
toggleForwardMessageModal: (messageId: string) => unknown;
|
toggleForwardMessageModal: (messageId: string) => unknown;
|
||||||
|
@ -682,7 +683,7 @@ function LightboxHeader({
|
||||||
}: {
|
}: {
|
||||||
getConversation: (id: string) => ConversationType;
|
getConversation: (id: string) => ConversationType;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
message: MediaItemMessageType;
|
message: ReadonlyDeep<MediaItemMessageType>;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const conversation = getConversation(message.conversationId);
|
const conversation = getConversation(message.conversationId);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import type { ReactChild, ReactNode, RefObject } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Measure from 'react-measure';
|
import Measure from 'react-measure';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import { ScrollDownButton } from './ScrollDownButton';
|
import { ScrollDownButton } from './ScrollDownButton';
|
||||||
|
|
||||||
import type { LocalizerType, ThemeType } from '../../types/Util';
|
import type { LocalizerType, ThemeType } from '../../types/Util';
|
||||||
|
@ -49,7 +50,7 @@ const MIN_ROW_HEIGHT = 18;
|
||||||
const SCROLL_DOWN_BUTTON_THRESHOLD = 8;
|
const SCROLL_DOWN_BUTTON_THRESHOLD = 8;
|
||||||
const LOAD_NEWER_THRESHOLD = 5;
|
const LOAD_NEWER_THRESHOLD = 5;
|
||||||
|
|
||||||
export type WarningType =
|
export type WarningType = ReadonlyDeep<
|
||||||
| {
|
| {
|
||||||
type: ContactSpoofingType.DirectConversationWithSameTitle;
|
type: ContactSpoofingType.DirectConversationWithSameTitle;
|
||||||
safeConversation: ConversationType;
|
safeConversation: ConversationType;
|
||||||
|
@ -58,7 +59,8 @@ export type WarningType =
|
||||||
type: ContactSpoofingType.MultipleGroupMembersWithSameTitle;
|
type: ContactSpoofingType.MultipleGroupMembersWithSameTitle;
|
||||||
acknowledgedGroupNameCollisions: GroupNameCollisionsWithIdsByTitle;
|
acknowledgedGroupNameCollisions: GroupNameCollisionsWithIdsByTitle;
|
||||||
groupNameCollisions: GroupNameCollisionsWithIdsByTitle;
|
groupNameCollisions: GroupNameCollisionsWithIdsByTitle;
|
||||||
};
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
export type ContactSpoofingReviewPropType =
|
export type ContactSpoofingReviewPropType =
|
||||||
| {
|
| {
|
||||||
|
@ -139,7 +141,7 @@ export type PropsActionsType = {
|
||||||
// From Backbone
|
// From Backbone
|
||||||
acknowledgeGroupMemberNameCollisions: (
|
acknowledgeGroupMemberNameCollisions: (
|
||||||
conversationId: string,
|
conversationId: string,
|
||||||
groupNameCollisions: Readonly<GroupNameCollisionsWithIdsByTitle>
|
groupNameCollisions: ReadonlyDeep<GroupNameCollisionsWithIdsByTitle>
|
||||||
) => void;
|
) => void;
|
||||||
clearInvitedUuidsForNewlyCreatedGroup: () => void;
|
clearInvitedUuidsForNewlyCreatedGroup: () => void;
|
||||||
clearSelectedMessage: () => unknown;
|
clearSelectedMessage: () => unknown;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { LocalizerType } from '../../../types/Util';
|
import type { LocalizerType } from '../../../types/Util';
|
||||||
|
|
||||||
import type { MediaItemType } from '../../../types/MediaItem';
|
import type { MediaItemType } from '../../../types/MediaItem';
|
||||||
|
@ -19,7 +20,7 @@ export type Props = {
|
||||||
showAllMedia: () => void;
|
showAllMedia: () => void;
|
||||||
showLightboxWithMedia: (
|
showLightboxWithMedia: (
|
||||||
selectedAttachmentPath: string | undefined,
|
selectedAttachmentPath: string | undefined,
|
||||||
media: ReadonlyArray<MediaItemType>
|
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>
|
||||||
) => void;
|
) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import {
|
import {
|
||||||
isImageTypeSupported,
|
isImageTypeSupported,
|
||||||
isVideoTypeSupported,
|
isVideoTypeSupported,
|
||||||
|
@ -13,7 +14,7 @@ import type { MediaItemType } from '../../../types/MediaItem';
|
||||||
import * as log from '../../../logging/log';
|
import * as log from '../../../logging/log';
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
mediaItem: MediaItemType;
|
mediaItem: ReadonlyDeep<MediaItemType>;
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { batch as batchDispatch } from 'react-redux';
|
||||||
import { v4 as generateGuid } from 'uuid';
|
import { v4 as generateGuid } from 'uuid';
|
||||||
import PQueue from 'p-queue';
|
import PQueue from 'p-queue';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type {
|
import type {
|
||||||
ConversationAttributesType,
|
ConversationAttributesType,
|
||||||
ConversationLastProfileType,
|
ConversationLastProfileType,
|
||||||
|
@ -5512,7 +5513,7 @@ export class ConversationModel extends window.Backbone
|
||||||
}
|
}
|
||||||
|
|
||||||
acknowledgeGroupMemberNameCollisions(
|
acknowledgeGroupMemberNameCollisions(
|
||||||
groupNameCollisions: Readonly<GroupNameCollisionsWithIdsByTitle>
|
groupNameCollisions: ReadonlyDeep<GroupNameCollisionsWithIdsByTitle>
|
||||||
): void {
|
): void {
|
||||||
this.set('acknowledgedGroupNameCollisions', groupNameCollisions);
|
this.set('acknowledgedGroupNameCollisions', groupNameCollisions);
|
||||||
window.Signal.Data.updateConversation(this.attributes);
|
window.Signal.Data.updateConversation(this.attributes);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import * as Errors from '../../types/errors';
|
import * as Errors from '../../types/errors';
|
||||||
import * as log from '../../logging/log';
|
import * as log from '../../logging/log';
|
||||||
|
|
||||||
|
@ -16,21 +17,21 @@ import type { NoopActionType } from './noop';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type AccountsStateType = {
|
export type AccountsStateType = ReadonlyDeep<{
|
||||||
accounts: Record<string, UUIDStringType | undefined>;
|
accounts: Record<string, UUIDStringType | undefined>;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
type AccountUpdateActionType = {
|
type AccountUpdateActionType = ReadonlyDeep<{
|
||||||
type: 'accounts/UPDATE';
|
type: 'accounts/UPDATE';
|
||||||
payload: {
|
payload: {
|
||||||
phoneNumber: string;
|
phoneNumber: string;
|
||||||
uuid?: UUIDStringType;
|
uuid?: UUIDStringType;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type AccountsActionType = AccountUpdateActionType;
|
export type AccountsActionType = ReadonlyDeep<AccountUpdateActionType>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { StateType as RootStateType } from '../reducer';
|
import type { StateType as RootStateType } from '../reducer';
|
||||||
import * as log from '../../logging/log';
|
import * as log from '../../logging/log';
|
||||||
|
|
||||||
|
@ -14,10 +15,10 @@ export enum AppViewType {
|
||||||
Standalone = 'Standalone',
|
Standalone = 'Standalone',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AppStateType = {
|
export type AppStateType = ReadonlyDeep<{
|
||||||
appView: AppViewType;
|
appView: AppViewType;
|
||||||
hasInitialLoadCompleted: boolean;
|
hasInitialLoadCompleted: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
|
@ -26,27 +27,28 @@ const OPEN_INBOX = 'app/OPEN_INBOX';
|
||||||
const OPEN_INSTALLER = 'app/OPEN_INSTALLER';
|
const OPEN_INSTALLER = 'app/OPEN_INSTALLER';
|
||||||
const OPEN_STANDALONE = 'app/OPEN_STANDALONE';
|
const OPEN_STANDALONE = 'app/OPEN_STANDALONE';
|
||||||
|
|
||||||
type InitialLoadCompleteActionType = {
|
type InitialLoadCompleteActionType = ReadonlyDeep<{
|
||||||
type: typeof INITIAL_LOAD_COMPLETE;
|
type: typeof INITIAL_LOAD_COMPLETE;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type OpenInboxActionType = {
|
type OpenInboxActionType = ReadonlyDeep<{
|
||||||
type: typeof OPEN_INBOX;
|
type: typeof OPEN_INBOX;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type OpenInstallerActionType = {
|
type OpenInstallerActionType = ReadonlyDeep<{
|
||||||
type: typeof OPEN_INSTALLER;
|
type: typeof OPEN_INSTALLER;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type OpenStandaloneActionType = {
|
type OpenStandaloneActionType = ReadonlyDeep<{
|
||||||
type: typeof OPEN_STANDALONE;
|
type: typeof OPEN_STANDALONE;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type AppActionType =
|
export type AppActionType = ReadonlyDeep<
|
||||||
| InitialLoadCompleteActionType
|
| InitialLoadCompleteActionType
|
||||||
| OpenInboxActionType
|
| OpenInboxActionType
|
||||||
| OpenInstallerActionType
|
| OpenInstallerActionType
|
||||||
| OpenStandaloneActionType;
|
| OpenStandaloneActionType
|
||||||
|
>;
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
initialLoadComplete,
|
initialLoadComplete,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
||||||
import { useBoundActions } from '../../hooks/useBoundActions';
|
import { useBoundActions } from '../../hooks/useBoundActions';
|
||||||
import { Sound } from '../../util/Sound';
|
import { Sound } from '../../util/Sound';
|
||||||
|
@ -35,25 +36,25 @@ import { getMessagePropStatus } from '../selectors/message';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type ActiveAudioPlayerStateType = {
|
export type ActiveAudioPlayerStateType = ReadonlyDeep<{
|
||||||
readonly playing: boolean;
|
playing: boolean;
|
||||||
readonly currentTime: number;
|
currentTime: number;
|
||||||
readonly playbackRate: number;
|
playbackRate: number;
|
||||||
readonly duration: number;
|
duration: number;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type AudioPlayerStateType = {
|
export type AudioPlayerStateType = ReadonlyDeep<{
|
||||||
readonly active:
|
active:
|
||||||
| (ActiveAudioPlayerStateType & { id: string; context: string })
|
| (ActiveAudioPlayerStateType & { id: string; context: string })
|
||||||
| undefined;
|
| undefined;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current "active" message audio for a particular rendering "context"
|
* Sets the current "active" message audio for a particular rendering "context"
|
||||||
*/
|
*/
|
||||||
export type SetMessageAudioAction = {
|
export type SetMessageAudioAction = ReadonlyDeep<{
|
||||||
type: 'audioPlayer/SET_MESSAGE_AUDIO';
|
type: 'audioPlayer/SET_MESSAGE_AUDIO';
|
||||||
payload:
|
payload:
|
||||||
| {
|
| {
|
||||||
|
@ -63,39 +64,40 @@ export type SetMessageAudioAction = {
|
||||||
duration: number;
|
duration: number;
|
||||||
}
|
}
|
||||||
| undefined;
|
| undefined;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SetPlaybackRate = {
|
type SetPlaybackRate = ReadonlyDeep<{
|
||||||
type: 'audioPlayer/SET_PLAYBACK_RATE';
|
type: 'audioPlayer/SET_PLAYBACK_RATE';
|
||||||
payload: number;
|
payload: number;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SetIsPlayingAction = {
|
type SetIsPlayingAction = ReadonlyDeep<{
|
||||||
type: 'audioPlayer/SET_IS_PLAYING';
|
type: 'audioPlayer/SET_IS_PLAYING';
|
||||||
payload: boolean;
|
payload: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CurrentTimeUpdated = {
|
type CurrentTimeUpdated = ReadonlyDeep<{
|
||||||
type: 'audioPlayer/CURRENT_TIME_UPDATED';
|
type: 'audioPlayer/CURRENT_TIME_UPDATED';
|
||||||
payload: number;
|
payload: number;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type MessageAudioEnded = {
|
type MessageAudioEnded = ReadonlyDeep<{
|
||||||
type: 'audioPlayer/MESSAGE_AUDIO_ENDED';
|
type: 'audioPlayer/MESSAGE_AUDIO_ENDED';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type DurationChanged = {
|
type DurationChanged = ReadonlyDeep<{
|
||||||
type: 'audioPlayer/DURATION_CHANGED';
|
type: 'audioPlayer/DURATION_CHANGED';
|
||||||
payload: number;
|
payload: number;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type AudioPlayerActionType =
|
type AudioPlayerActionType = ReadonlyDeep<
|
||||||
| SetMessageAudioAction
|
| SetMessageAudioAction
|
||||||
| SetIsPlayingAction
|
| SetIsPlayingAction
|
||||||
| SetPlaybackRate
|
| SetPlaybackRate
|
||||||
| MessageAudioEnded
|
| MessageAudioEnded
|
||||||
| CurrentTimeUpdated
|
| CurrentTimeUpdated
|
||||||
| DurationChanged;
|
| DurationChanged
|
||||||
|
>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import * as log from '../../logging/log';
|
import * as log from '../../logging/log';
|
||||||
import type { InMemoryAttachmentDraftType } from '../../types/Attachment';
|
import type { InMemoryAttachmentDraftType } from '../../types/Attachment';
|
||||||
import { SignalService as Proto } from '../../protobuf';
|
import { SignalService as Proto } from '../../protobuf';
|
||||||
|
@ -28,10 +29,10 @@ export enum RecordingState {
|
||||||
Idle = 'idle',
|
Idle = 'idle',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AudioPlayerStateType = {
|
export type AudioPlayerStateType = ReadonlyDeep<{
|
||||||
readonly recordingState: RecordingState;
|
recordingState: RecordingState;
|
||||||
readonly errorDialogAudioRecorderType?: ErrorDialogAudioRecorderType;
|
errorDialogAudioRecorderType?: ErrorDialogAudioRecorderType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
|
@ -41,33 +42,34 @@ const ERROR_RECORDING = 'audioRecorder/ERROR_RECORDING';
|
||||||
const NOW_RECORDING = 'audioRecorder/NOW_RECORDING';
|
const NOW_RECORDING = 'audioRecorder/NOW_RECORDING';
|
||||||
const START_RECORDING = 'audioRecorder/START_RECORDING';
|
const START_RECORDING = 'audioRecorder/START_RECORDING';
|
||||||
|
|
||||||
type CancelRecordingAction = {
|
type CancelRecordingAction = ReadonlyDeep<{
|
||||||
type: typeof CANCEL_RECORDING;
|
type: typeof CANCEL_RECORDING;
|
||||||
payload: undefined;
|
payload: undefined;
|
||||||
};
|
}>;
|
||||||
type CompleteRecordingAction = {
|
type CompleteRecordingAction = ReadonlyDeep<{
|
||||||
type: typeof COMPLETE_RECORDING;
|
type: typeof COMPLETE_RECORDING;
|
||||||
payload: undefined;
|
payload: undefined;
|
||||||
};
|
}>;
|
||||||
type ErrorRecordingAction = {
|
type ErrorRecordingAction = ReadonlyDeep<{
|
||||||
type: typeof ERROR_RECORDING;
|
type: typeof ERROR_RECORDING;
|
||||||
payload: ErrorDialogAudioRecorderType;
|
payload: ErrorDialogAudioRecorderType;
|
||||||
};
|
}>;
|
||||||
type StartRecordingAction = {
|
type StartRecordingAction = ReadonlyDeep<{
|
||||||
type: typeof START_RECORDING;
|
type: typeof START_RECORDING;
|
||||||
payload: undefined;
|
payload: undefined;
|
||||||
};
|
}>;
|
||||||
type NowRecordingAction = {
|
type NowRecordingAction = ReadonlyDeep<{
|
||||||
type: typeof NOW_RECORDING;
|
type: typeof NOW_RECORDING;
|
||||||
payload: undefined;
|
payload: undefined;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type AudioPlayerActionType =
|
type AudioPlayerActionType = ReadonlyDeep<
|
||||||
| CancelRecordingAction
|
| CancelRecordingAction
|
||||||
| CompleteRecordingAction
|
| CompleteRecordingAction
|
||||||
| ErrorRecordingAction
|
| ErrorRecordingAction
|
||||||
| NowRecordingAction
|
| NowRecordingAction
|
||||||
| StartRecordingAction;
|
| StartRecordingAction
|
||||||
|
>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
import { mapValues } from 'lodash';
|
import { mapValues } from 'lodash';
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { StateType as RootStateType } from '../reducer';
|
import type { StateType as RootStateType } from '../reducer';
|
||||||
import type { BadgeType, BadgeImageType } from '../../badges/types';
|
import type { BadgeType, BadgeImageType } from '../../badges/types';
|
||||||
import { getOwn } from '../../util/getOwn';
|
import { getOwn } from '../../util/getOwn';
|
||||||
|
@ -22,27 +23,27 @@ import { badgeImageFileDownloader } from '../../badges/badgeImageFileDownloader'
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type BadgesStateType = {
|
export type BadgesStateType = ReadonlyDeep<{
|
||||||
byId: Record<string, BadgeType>;
|
byId: Record<string, BadgeType>;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
const IMAGE_FILE_DOWNLOADED = 'badges/IMAGE_FILE_DOWNLOADED';
|
const IMAGE_FILE_DOWNLOADED = 'badges/IMAGE_FILE_DOWNLOADED';
|
||||||
const UPDATE_OR_CREATE = 'badges/UPDATE_OR_CREATE';
|
const UPDATE_OR_CREATE = 'badges/UPDATE_OR_CREATE';
|
||||||
|
|
||||||
type ImageFileDownloadedActionType = {
|
type ImageFileDownloadedActionType = ReadonlyDeep<{
|
||||||
type: typeof IMAGE_FILE_DOWNLOADED;
|
type: typeof IMAGE_FILE_DOWNLOADED;
|
||||||
payload: {
|
payload: {
|
||||||
url: string;
|
url: string;
|
||||||
localPath: string;
|
localPath: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type UpdateOrCreateActionType = {
|
type UpdateOrCreateActionType = ReadonlyDeep<{
|
||||||
type: typeof UPDATE_OR_CREATE;
|
type: typeof UPDATE_OR_CREATE;
|
||||||
payload: ReadonlyArray<BadgeType>;
|
payload: Array<BadgeType>;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Action creators
|
// Action creators
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
openSystemPreferences,
|
openSystemPreferences,
|
||||||
} from 'mac-screen-capture-permissions';
|
} from 'mac-screen-capture-permissions';
|
||||||
import { has, omit } from 'lodash';
|
import { has, omit } from 'lodash';
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import { getOwn } from '../../util/getOwn';
|
import { getOwn } from '../../util/getOwn';
|
||||||
import * as Errors from '../../types/errors';
|
import * as Errors from '../../types/errors';
|
||||||
import { getPlatform } from '../selectors/user';
|
import { getPlatform } from '../selectors/user';
|
||||||
|
@ -57,14 +58,15 @@ import MessageSender from '../../textsecure/SendMessage';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type GroupCallPeekInfoType = {
|
export type GroupCallPeekInfoType = ReadonlyDeep<{
|
||||||
uuids: Array<UUIDStringType>;
|
uuids: Array<UUIDStringType>;
|
||||||
creatorUuid?: UUIDStringType;
|
creatorUuid?: UUIDStringType;
|
||||||
eraId?: string;
|
eraId?: string;
|
||||||
maxDevices: number;
|
maxDevices: number;
|
||||||
deviceCount: number;
|
deviceCount: number;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type GroupCallParticipantInfoType = {
|
export type GroupCallParticipantInfoType = {
|
||||||
uuid: UUIDStringType;
|
uuid: UUIDStringType;
|
||||||
demuxId: number;
|
demuxId: number;
|
||||||
|
@ -76,6 +78,7 @@ export type GroupCallParticipantInfoType = {
|
||||||
videoAspectRatio: number;
|
videoAspectRatio: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type DirectCallStateType = {
|
export type DirectCallStateType = {
|
||||||
callMode: CallMode.Direct;
|
callMode: CallMode.Direct;
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
|
@ -87,7 +90,7 @@ export type DirectCallStateType = {
|
||||||
hasRemoteVideo?: boolean;
|
hasRemoteVideo?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type GroupCallRingStateType =
|
type GroupCallRingStateType = ReadonlyDeep<
|
||||||
| {
|
| {
|
||||||
ringId?: undefined;
|
ringId?: undefined;
|
||||||
ringerUuid?: undefined;
|
ringerUuid?: undefined;
|
||||||
|
@ -95,8 +98,10 @@ type GroupCallRingStateType =
|
||||||
| {
|
| {
|
||||||
ringId: bigint;
|
ringId: bigint;
|
||||||
ringerUuid: UUIDStringType;
|
ringerUuid: UUIDStringType;
|
||||||
};
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type GroupCallStateType = {
|
export type GroupCallStateType = {
|
||||||
callMode: CallMode.Group;
|
callMode: CallMode.Group;
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
|
@ -107,6 +112,7 @@ export type GroupCallStateType = {
|
||||||
remoteAudioLevels?: Map<number, number>;
|
remoteAudioLevels?: Map<number, number>;
|
||||||
} & GroupCallRingStateType;
|
} & GroupCallRingStateType;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type ActiveCallStateType = {
|
export type ActiveCallStateType = {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
hasLocalAudio: boolean;
|
hasLocalAudio: boolean;
|
||||||
|
@ -124,21 +130,23 @@ export type ActiveCallStateType = {
|
||||||
showParticipantsList: boolean;
|
showParticipantsList: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type CallsByConversationType = {
|
export type CallsByConversationType = {
|
||||||
[conversationId: string]: DirectCallStateType | GroupCallStateType;
|
[conversationId: string]: DirectCallStateType | GroupCallStateType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type CallingStateType = MediaDeviceSettings & {
|
export type CallingStateType = MediaDeviceSettings & {
|
||||||
callsByConversation: CallsByConversationType;
|
callsByConversation: CallsByConversationType;
|
||||||
activeCallState?: ActiveCallStateType;
|
activeCallState?: ActiveCallStateType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type AcceptCallType = {
|
export type AcceptCallType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
asVideoCall: boolean;
|
asVideoCall: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type CallStateChangeType = {
|
export type CallStateChangeType = ReadonlyDeep<{
|
||||||
remoteUserId: string; // TODO: Remove
|
remoteUserId: string; // TODO: Remove
|
||||||
callId: string; // TODO: Remove
|
callId: string; // TODO: Remove
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
|
@ -148,21 +156,22 @@ export type CallStateChangeType = {
|
||||||
isIncoming: boolean;
|
isIncoming: boolean;
|
||||||
isVideoCall: boolean;
|
isVideoCall: boolean;
|
||||||
title: string;
|
title: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type CancelCallType = {
|
export type CancelCallType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CancelIncomingGroupCallRingType = {
|
type CancelIncomingGroupCallRingType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
ringId: bigint;
|
ringId: bigint;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type DeclineCallType = {
|
export type DeclineCallType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type GroupCallStateChangeArgumentType = {
|
type GroupCallStateChangeArgumentType = {
|
||||||
connectionState: GroupCallConnectionState;
|
connectionState: GroupCallConnectionState;
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
|
@ -173,77 +182,81 @@ type GroupCallStateChangeArgumentType = {
|
||||||
remoteParticipants: Array<GroupCallParticipantInfoType>;
|
remoteParticipants: Array<GroupCallParticipantInfoType>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type GroupCallStateChangeActionPayloadType =
|
type GroupCallStateChangeActionPayloadType =
|
||||||
GroupCallStateChangeArgumentType & {
|
GroupCallStateChangeArgumentType & {
|
||||||
ourUuid: UUIDStringType;
|
ourUuid: UUIDStringType;
|
||||||
};
|
};
|
||||||
|
|
||||||
type HangUpActionPayloadType = {
|
type HangUpActionPayloadType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type KeyChangedType = {
|
type KeyChangedType = ReadonlyDeep<{
|
||||||
uuid: UUIDStringType;
|
uuid: UUIDStringType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type KeyChangeOkType = {
|
export type KeyChangeOkType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type IncomingDirectCallType = {
|
export type IncomingDirectCallType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
isVideoCall: boolean;
|
isVideoCall: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type IncomingGroupCallType = {
|
type IncomingGroupCallType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
ringId: bigint;
|
ringId: bigint;
|
||||||
ringerUuid: UUIDStringType;
|
ringerUuid: UUIDStringType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type PeekNotConnectedGroupCallType = {
|
type PeekNotConnectedGroupCallType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type StartDirectCallType = {
|
type StartDirectCallType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
hasLocalAudio: boolean;
|
hasLocalAudio: boolean;
|
||||||
hasLocalVideo: boolean;
|
hasLocalVideo: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type StartCallType = StartDirectCallType & {
|
export type StartCallType = ReadonlyDeep<
|
||||||
callMode: CallMode.Direct | CallMode.Group;
|
StartDirectCallType & {
|
||||||
};
|
callMode: CallMode.Direct | CallMode.Group;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
export type RemoteVideoChangeType = {
|
export type RemoteVideoChangeType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
hasVideo: boolean;
|
hasVideo: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type RemoteSharingScreenChangeType = {
|
type RemoteSharingScreenChangeType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
isSharingScreen: boolean;
|
isSharingScreen: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type SetLocalAudioType = {
|
export type SetLocalAudioType = ReadonlyDeep<{
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type SetLocalVideoType = {
|
export type SetLocalVideoType = ReadonlyDeep<{
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type SetGroupCallVideoRequestType = {
|
export type SetGroupCallVideoRequestType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
resolutions: Array<GroupCallVideoRequest>;
|
resolutions: Array<GroupCallVideoRequest>;
|
||||||
speakerHeight: number;
|
speakerHeight: number;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type StartCallingLobbyType = {
|
export type StartCallingLobbyType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
isVideoCall: boolean;
|
isVideoCall: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type StartCallingLobbyPayloadType =
|
type StartCallingLobbyPayloadType =
|
||||||
| {
|
| {
|
||||||
callMode: CallMode.Direct;
|
callMode: CallMode.Direct;
|
||||||
|
@ -263,10 +276,12 @@ type StartCallingLobbyPayloadType =
|
||||||
remoteParticipants: Array<GroupCallParticipantInfoType>;
|
remoteParticipants: Array<GroupCallParticipantInfoType>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type SetLocalPreviewType = {
|
export type SetLocalPreviewType = {
|
||||||
element: React.RefObject<HTMLVideoElement> | undefined;
|
element: React.RefObject<HTMLVideoElement> | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type SetRendererCanvasType = {
|
export type SetRendererCanvasType = {
|
||||||
element: React.RefObject<HTMLCanvasElement> | undefined;
|
element: React.RefObject<HTMLCanvasElement> | undefined;
|
||||||
};
|
};
|
||||||
|
@ -441,76 +456,79 @@ const TOGGLE_SPEAKER_VIEW = 'calling/TOGGLE_SPEAKER_VIEW';
|
||||||
const SWITCH_TO_PRESENTATION_VIEW = 'calling/SWITCH_TO_PRESENTATION_VIEW';
|
const SWITCH_TO_PRESENTATION_VIEW = 'calling/SWITCH_TO_PRESENTATION_VIEW';
|
||||||
const SWITCH_FROM_PRESENTATION_VIEW = 'calling/SWITCH_FROM_PRESENTATION_VIEW';
|
const SWITCH_FROM_PRESENTATION_VIEW = 'calling/SWITCH_FROM_PRESENTATION_VIEW';
|
||||||
|
|
||||||
type AcceptCallPendingActionType = {
|
type AcceptCallPendingActionType = ReadonlyDeep<{
|
||||||
type: 'calling/ACCEPT_CALL_PENDING';
|
type: 'calling/ACCEPT_CALL_PENDING';
|
||||||
payload: AcceptCallType;
|
payload: AcceptCallType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CancelCallActionType = {
|
type CancelCallActionType = ReadonlyDeep<{
|
||||||
type: 'calling/CANCEL_CALL';
|
type: 'calling/CANCEL_CALL';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CancelIncomingGroupCallRingActionType = {
|
type CancelIncomingGroupCallRingActionType = ReadonlyDeep<{
|
||||||
type: 'calling/CANCEL_INCOMING_GROUP_CALL_RING';
|
type: 'calling/CANCEL_INCOMING_GROUP_CALL_RING';
|
||||||
payload: CancelIncomingGroupCallRingType;
|
payload: CancelIncomingGroupCallRingType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type StartCallingLobbyActionType = {
|
type StartCallingLobbyActionType = {
|
||||||
type: 'calling/START_CALLING_LOBBY';
|
type: 'calling/START_CALLING_LOBBY';
|
||||||
payload: StartCallingLobbyPayloadType;
|
payload: StartCallingLobbyPayloadType;
|
||||||
};
|
};
|
||||||
|
|
||||||
type CallStateChangeFulfilledActionType = {
|
type CallStateChangeFulfilledActionType = ReadonlyDeep<{
|
||||||
type: 'calling/CALL_STATE_CHANGE_FULFILLED';
|
type: 'calling/CALL_STATE_CHANGE_FULFILLED';
|
||||||
payload: CallStateChangeType;
|
payload: CallStateChangeType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ChangeIODeviceFulfilledActionType = {
|
type ChangeIODeviceFulfilledActionType = ReadonlyDeep<{
|
||||||
type: 'calling/CHANGE_IO_DEVICE_FULFILLED';
|
type: 'calling/CHANGE_IO_DEVICE_FULFILLED';
|
||||||
payload: ChangeIODevicePayloadType;
|
payload: ChangeIODevicePayloadType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CloseNeedPermissionScreenActionType = {
|
type CloseNeedPermissionScreenActionType = ReadonlyDeep<{
|
||||||
type: 'calling/CLOSE_NEED_PERMISSION_SCREEN';
|
type: 'calling/CLOSE_NEED_PERMISSION_SCREEN';
|
||||||
payload: null;
|
payload: null;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type DeclineCallActionType = {
|
type DeclineCallActionType = ReadonlyDeep<{
|
||||||
type: 'calling/DECLINE_DIRECT_CALL';
|
type: 'calling/DECLINE_DIRECT_CALL';
|
||||||
payload: DeclineCallType;
|
payload: DeclineCallType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type GroupCallAudioLevelsChangeActionPayloadType = Readonly<{
|
type GroupCallAudioLevelsChangeActionPayloadType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
localAudioLevel: number;
|
localAudioLevel: number;
|
||||||
remoteDeviceStates: ReadonlyArray<{ audioLevel: number; demuxId: number }>;
|
remoteDeviceStates: ReadonlyArray<{ audioLevel: number; demuxId: number }>;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
type GroupCallAudioLevelsChangeActionType = {
|
type GroupCallAudioLevelsChangeActionType = ReadonlyDeep<{
|
||||||
type: 'calling/GROUP_CALL_AUDIO_LEVELS_CHANGE';
|
type: 'calling/GROUP_CALL_AUDIO_LEVELS_CHANGE';
|
||||||
payload: GroupCallAudioLevelsChangeActionPayloadType;
|
payload: GroupCallAudioLevelsChangeActionPayloadType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type GroupCallStateChangeActionType = {
|
export type GroupCallStateChangeActionType = {
|
||||||
type: 'calling/GROUP_CALL_STATE_CHANGE';
|
type: 'calling/GROUP_CALL_STATE_CHANGE';
|
||||||
payload: GroupCallStateChangeActionPayloadType;
|
payload: GroupCallStateChangeActionPayloadType;
|
||||||
};
|
};
|
||||||
|
|
||||||
type HangUpActionType = {
|
type HangUpActionType = ReadonlyDeep<{
|
||||||
type: 'calling/HANG_UP';
|
type: 'calling/HANG_UP';
|
||||||
payload: HangUpActionPayloadType;
|
payload: HangUpActionPayloadType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type IncomingDirectCallActionType = {
|
type IncomingDirectCallActionType = ReadonlyDeep<{
|
||||||
type: 'calling/INCOMING_DIRECT_CALL';
|
type: 'calling/INCOMING_DIRECT_CALL';
|
||||||
payload: IncomingDirectCallType;
|
payload: IncomingDirectCallType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type IncomingGroupCallActionType = {
|
type IncomingGroupCallActionType = ReadonlyDeep<{
|
||||||
type: 'calling/INCOMING_GROUP_CALL';
|
type: 'calling/INCOMING_GROUP_CALL';
|
||||||
payload: IncomingGroupCallType;
|
payload: IncomingGroupCallType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type KeyChangedActionType = {
|
type KeyChangedActionType = {
|
||||||
type: 'calling/MARK_CALL_UNTRUSTED';
|
type: 'calling/MARK_CALL_UNTRUSTED';
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -518,101 +536,104 @@ type KeyChangedActionType = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type KeyChangeOkActionType = {
|
type KeyChangeOkActionType = ReadonlyDeep<{
|
||||||
type: 'calling/MARK_CALL_TRUSTED';
|
type: 'calling/MARK_CALL_TRUSTED';
|
||||||
payload: null;
|
payload: null;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type OutgoingCallActionType = {
|
type OutgoingCallActionType = ReadonlyDeep<{
|
||||||
type: 'calling/OUTGOING_CALL';
|
type: 'calling/OUTGOING_CALL';
|
||||||
payload: StartDirectCallType;
|
payload: StartDirectCallType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type PeekGroupCallFulfilledActionType = {
|
export type PeekGroupCallFulfilledActionType = ReadonlyDeep<{
|
||||||
type: 'calling/PEEK_GROUP_CALL_FULFILLED';
|
type: 'calling/PEEK_GROUP_CALL_FULFILLED';
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
peekInfo: GroupCallPeekInfoType;
|
peekInfo: GroupCallPeekInfoType;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type RefreshIODevicesActionType = {
|
type RefreshIODevicesActionType = {
|
||||||
type: 'calling/REFRESH_IO_DEVICES';
|
type: 'calling/REFRESH_IO_DEVICES';
|
||||||
payload: MediaDeviceSettings;
|
payload: MediaDeviceSettings;
|
||||||
};
|
};
|
||||||
|
|
||||||
type RemoteSharingScreenChangeActionType = {
|
type RemoteSharingScreenChangeActionType = ReadonlyDeep<{
|
||||||
type: 'calling/REMOTE_SHARING_SCREEN_CHANGE';
|
type: 'calling/REMOTE_SHARING_SCREEN_CHANGE';
|
||||||
payload: RemoteSharingScreenChangeType;
|
payload: RemoteSharingScreenChangeType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type RemoteVideoChangeActionType = {
|
type RemoteVideoChangeActionType = ReadonlyDeep<{
|
||||||
type: 'calling/REMOTE_VIDEO_CHANGE';
|
type: 'calling/REMOTE_VIDEO_CHANGE';
|
||||||
payload: RemoteVideoChangeType;
|
payload: RemoteVideoChangeType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ReturnToActiveCallActionType = {
|
type ReturnToActiveCallActionType = ReadonlyDeep<{
|
||||||
type: 'calling/RETURN_TO_ACTIVE_CALL';
|
type: 'calling/RETURN_TO_ACTIVE_CALL';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SetLocalAudioActionType = {
|
type SetLocalAudioActionType = ReadonlyDeep<{
|
||||||
type: 'calling/SET_LOCAL_AUDIO_FULFILLED';
|
type: 'calling/SET_LOCAL_AUDIO_FULFILLED';
|
||||||
payload: SetLocalAudioType;
|
payload: SetLocalAudioType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SetLocalVideoFulfilledActionType = {
|
type SetLocalVideoFulfilledActionType = ReadonlyDeep<{
|
||||||
type: 'calling/SET_LOCAL_VIDEO_FULFILLED';
|
type: 'calling/SET_LOCAL_VIDEO_FULFILLED';
|
||||||
payload: SetLocalVideoType;
|
payload: SetLocalVideoType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SetPresentingFulfilledActionType = {
|
type SetPresentingFulfilledActionType = ReadonlyDeep<{
|
||||||
type: 'calling/SET_PRESENTING';
|
type: 'calling/SET_PRESENTING';
|
||||||
payload?: PresentedSource;
|
payload?: PresentedSource;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type SetPresentingSourcesActionType = {
|
type SetPresentingSourcesActionType = {
|
||||||
type: 'calling/SET_PRESENTING_SOURCES';
|
type: 'calling/SET_PRESENTING_SOURCES';
|
||||||
payload: Array<PresentableSource>;
|
payload: Array<PresentableSource>;
|
||||||
};
|
};
|
||||||
|
|
||||||
type SetOutgoingRingActionType = {
|
type SetOutgoingRingActionType = ReadonlyDeep<{
|
||||||
type: 'calling/SET_OUTGOING_RING';
|
type: 'calling/SET_OUTGOING_RING';
|
||||||
payload: boolean;
|
payload: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type StartDirectCallActionType = {
|
type StartDirectCallActionType = ReadonlyDeep<{
|
||||||
type: 'calling/START_DIRECT_CALL';
|
type: 'calling/START_DIRECT_CALL';
|
||||||
payload: StartDirectCallType;
|
payload: StartDirectCallType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleNeedsScreenRecordingPermissionsActionType = {
|
type ToggleNeedsScreenRecordingPermissionsActionType = ReadonlyDeep<{
|
||||||
type: 'calling/TOGGLE_NEEDS_SCREEN_RECORDING_PERMISSIONS';
|
type: 'calling/TOGGLE_NEEDS_SCREEN_RECORDING_PERMISSIONS';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleParticipantsActionType = {
|
type ToggleParticipantsActionType = ReadonlyDeep<{
|
||||||
type: 'calling/TOGGLE_PARTICIPANTS';
|
type: 'calling/TOGGLE_PARTICIPANTS';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type TogglePipActionType = {
|
type TogglePipActionType = ReadonlyDeep<{
|
||||||
type: 'calling/TOGGLE_PIP';
|
type: 'calling/TOGGLE_PIP';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleSettingsActionType = {
|
type ToggleSettingsActionType = ReadonlyDeep<{
|
||||||
type: 'calling/TOGGLE_SETTINGS';
|
type: 'calling/TOGGLE_SETTINGS';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleSpeakerViewActionType = {
|
type ToggleSpeakerViewActionType = ReadonlyDeep<{
|
||||||
type: 'calling/TOGGLE_SPEAKER_VIEW';
|
type: 'calling/TOGGLE_SPEAKER_VIEW';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SwitchToPresentationViewActionType = {
|
type SwitchToPresentationViewActionType = ReadonlyDeep<{
|
||||||
type: 'calling/SWITCH_TO_PRESENTATION_VIEW';
|
type: 'calling/SWITCH_TO_PRESENTATION_VIEW';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SwitchFromPresentationViewActionType = {
|
type SwitchFromPresentationViewActionType = ReadonlyDeep<{
|
||||||
type: 'calling/SWITCH_FROM_PRESENTATION_VIEW';
|
type: 'calling/SWITCH_FROM_PRESENTATION_VIEW';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type CallingActionType =
|
export type CallingActionType =
|
||||||
| AcceptCallPendingActionType
|
| AcceptCallPendingActionType
|
||||||
| CancelCallActionType
|
| CancelCallActionType
|
||||||
|
@ -1545,7 +1566,7 @@ export const actions = {
|
||||||
toggleSpeakerView,
|
toggleSpeakerView,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ActionsType = typeof actions;
|
export type ActionsType = ReadonlyDeep<typeof actions>;
|
||||||
|
|
||||||
// Reducer
|
// Reducer
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import path from 'path';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type {
|
import type {
|
||||||
AddLinkPreviewActionType,
|
AddLinkPreviewActionType,
|
||||||
RemoveLinkPreviewActionType,
|
RemoveLinkPreviewActionType,
|
||||||
|
@ -86,7 +87,7 @@ import { drop } from '../../util/drop';
|
||||||
import { strictAssert } from '../../util/assert';
|
import { strictAssert } from '../../util/assert';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type ComposerStateByConversationType = {
|
type ComposerStateByConversationType = {
|
||||||
attachments: ReadonlyArray<AttachmentDraftType>;
|
attachments: ReadonlyArray<AttachmentDraftType>;
|
||||||
focusCounter: number;
|
focusCounter: number;
|
||||||
|
@ -98,11 +99,13 @@ type ComposerStateByConversationType = {
|
||||||
shouldSendHighQualityAttachments?: boolean;
|
shouldSendHighQualityAttachments?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type QuotedMessageType = Pick<
|
export type QuotedMessageType = Pick<
|
||||||
MessageAttributesType,
|
MessageAttributesType,
|
||||||
'conversationId' | 'quote'
|
'conversationId' | 'quote'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type ComposerStateType = {
|
export type ComposerStateType = {
|
||||||
conversations: Record<string, ComposerStateByConversationType>;
|
conversations: Record<string, ComposerStateByConversationType>;
|
||||||
};
|
};
|
||||||
|
@ -134,14 +137,15 @@ const SET_HIGH_QUALITY_SETTING = 'composer/SET_HIGH_QUALITY_SETTING';
|
||||||
const SET_QUOTED_MESSAGE = 'composer/SET_QUOTED_MESSAGE';
|
const SET_QUOTED_MESSAGE = 'composer/SET_QUOTED_MESSAGE';
|
||||||
const SET_COMPOSER_DISABLED = 'composer/SET_COMPOSER_DISABLED';
|
const SET_COMPOSER_DISABLED = 'composer/SET_COMPOSER_DISABLED';
|
||||||
|
|
||||||
type AddPendingAttachmentActionType = {
|
type AddPendingAttachmentActionType = ReadonlyDeep<{
|
||||||
type: typeof ADD_PENDING_ATTACHMENT;
|
type: typeof ADD_PENDING_ATTACHMENT;
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
attachment: AttachmentDraftType;
|
attachment: AttachmentDraftType;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type ReplaceAttachmentsActionType = {
|
export type ReplaceAttachmentsActionType = {
|
||||||
type: typeof REPLACE_ATTACHMENTS;
|
type: typeof REPLACE_ATTACHMENTS;
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -150,36 +154,37 @@ export type ReplaceAttachmentsActionType = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ResetComposerActionType = {
|
export type ResetComposerActionType = ReadonlyDeep<{
|
||||||
type: typeof RESET_COMPOSER;
|
type: typeof RESET_COMPOSER;
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SetComposerDisabledStateActionType = {
|
type SetComposerDisabledStateActionType = ReadonlyDeep<{
|
||||||
type: typeof SET_COMPOSER_DISABLED;
|
type: typeof SET_COMPOSER_DISABLED;
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
value: boolean;
|
value: boolean;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type SetFocusActionType = {
|
export type SetFocusActionType = ReadonlyDeep<{
|
||||||
type: typeof SET_FOCUS;
|
type: typeof SET_FOCUS;
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SetHighQualitySettingActionType = {
|
type SetHighQualitySettingActionType = ReadonlyDeep<{
|
||||||
type: typeof SET_HIGH_QUALITY_SETTING;
|
type: typeof SET_HIGH_QUALITY_SETTING;
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
value: boolean;
|
value: boolean;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type SetQuotedMessageActionType = {
|
export type SetQuotedMessageActionType = {
|
||||||
type: typeof SET_QUOTED_MESSAGE;
|
type: typeof SET_QUOTED_MESSAGE;
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -188,6 +193,7 @@ export type SetQuotedMessageActionType = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type ComposerActionType =
|
type ComposerActionType =
|
||||||
| AddLinkPreviewActionType
|
| AddLinkPreviewActionType
|
||||||
| AddPendingAttachmentActionType
|
| AddPendingAttachmentActionType
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
without,
|
without,
|
||||||
} from 'lodash';
|
} from 'lodash';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { AttachmentType } from '../../types/Attachment';
|
import type { AttachmentType } from '../../types/Attachment';
|
||||||
import type { StateType as RootStateType } from '../reducer';
|
import type { StateType as RootStateType } from '../reducer';
|
||||||
import * as groups from '../../groups';
|
import * as groups from '../../groups';
|
||||||
|
@ -152,27 +153,31 @@ import {
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type DBConversationType = {
|
export type DBConversationType = ReadonlyDeep<{
|
||||||
id: string;
|
id: string;
|
||||||
activeAt?: number;
|
activeAt?: number;
|
||||||
lastMessage?: string | null;
|
lastMessage?: string | null;
|
||||||
type: string;
|
type: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export const InteractionModes = ['mouse', 'keyboard'] as const;
|
export const InteractionModes = ['mouse', 'keyboard'] as const;
|
||||||
export type InteractionModeType = typeof InteractionModes[number];
|
export type InteractionModeType = ReadonlyDeep<typeof InteractionModes[number]>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type MessageType = MessageAttributesType & {
|
export type MessageType = MessageAttributesType & {
|
||||||
interactionType?: InteractionModeType;
|
interactionType?: InteractionModeType;
|
||||||
};
|
};
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type MessageWithUIFieldsType = MessageAttributesType & {
|
export type MessageWithUIFieldsType = MessageAttributesType & {
|
||||||
displayLimit?: number;
|
displayLimit?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ConversationTypes = ['direct', 'group'] as const;
|
export const ConversationTypes = ['direct', 'group'] as const;
|
||||||
export type ConversationTypeType = typeof ConversationTypes[number];
|
export type ConversationTypeType = ReadonlyDeep<
|
||||||
|
typeof ConversationTypes[number]
|
||||||
|
>;
|
||||||
|
|
||||||
export type LastMessageType = Readonly<
|
export type LastMessageType = ReadonlyDeep<
|
||||||
| {
|
| {
|
||||||
status?: LastMessageStatus;
|
status?: LastMessageStatus;
|
||||||
text: string;
|
text: string;
|
||||||
|
@ -182,154 +187,161 @@ export type LastMessageType = Readonly<
|
||||||
| { deletedForEveryone: true }
|
| { deletedForEveryone: true }
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type ConversationType = {
|
export type ConversationType = ReadonlyDeep<
|
||||||
id: string;
|
{
|
||||||
uuid?: UUIDStringType;
|
id: string;
|
||||||
pni?: UUIDStringType;
|
uuid?: UUIDStringType;
|
||||||
e164?: string;
|
pni?: UUIDStringType;
|
||||||
name?: string;
|
e164?: string;
|
||||||
systemGivenName?: string;
|
name?: string;
|
||||||
systemFamilyName?: string;
|
systemGivenName?: string;
|
||||||
familyName?: string;
|
systemFamilyName?: string;
|
||||||
firstName?: string;
|
familyName?: string;
|
||||||
profileName?: string;
|
firstName?: string;
|
||||||
username?: string;
|
profileName?: string;
|
||||||
about?: string;
|
username?: string;
|
||||||
aboutText?: string;
|
about?: string;
|
||||||
aboutEmoji?: string;
|
aboutText?: string;
|
||||||
avatars?: ReadonlyArray<AvatarDataType>;
|
aboutEmoji?: string;
|
||||||
avatarPath?: string;
|
avatars?: ReadonlyArray<AvatarDataType>;
|
||||||
avatarHash?: string;
|
avatarPath?: string;
|
||||||
profileAvatarPath?: string;
|
avatarHash?: string;
|
||||||
unblurredAvatarPath?: string;
|
profileAvatarPath?: string;
|
||||||
areWeAdmin?: boolean;
|
unblurredAvatarPath?: string;
|
||||||
areWePending?: boolean;
|
areWeAdmin?: boolean;
|
||||||
areWePendingApproval?: boolean;
|
areWePending?: boolean;
|
||||||
canChangeTimer?: boolean;
|
areWePendingApproval?: boolean;
|
||||||
canEditGroupInfo?: boolean;
|
canChangeTimer?: boolean;
|
||||||
canAddNewMembers?: boolean;
|
canEditGroupInfo?: boolean;
|
||||||
color?: AvatarColorType;
|
canAddNewMembers?: boolean;
|
||||||
conversationColor?: ConversationColorType;
|
color?: AvatarColorType;
|
||||||
customColor?: CustomColorType;
|
conversationColor?: ConversationColorType;
|
||||||
customColorId?: string;
|
customColor?: CustomColorType;
|
||||||
discoveredUnregisteredAt?: number;
|
customColorId?: string;
|
||||||
hideStory?: boolean;
|
discoveredUnregisteredAt?: number;
|
||||||
isArchived?: boolean;
|
hideStory?: boolean;
|
||||||
isBlocked?: boolean;
|
isArchived?: boolean;
|
||||||
isGroupV1AndDisabled?: boolean;
|
isBlocked?: boolean;
|
||||||
isPinned?: boolean;
|
isGroupV1AndDisabled?: boolean;
|
||||||
isUntrusted?: boolean;
|
isPinned?: boolean;
|
||||||
isVerified?: boolean;
|
isUntrusted?: boolean;
|
||||||
activeAt?: number;
|
isVerified?: boolean;
|
||||||
timestamp?: number;
|
activeAt?: number;
|
||||||
inboxPosition?: number;
|
timestamp?: number;
|
||||||
left?: boolean;
|
inboxPosition?: number;
|
||||||
lastMessage?: LastMessageType;
|
left?: boolean;
|
||||||
markedUnread?: boolean;
|
lastMessage?: LastMessageType;
|
||||||
phoneNumber?: string;
|
markedUnread?: boolean;
|
||||||
membersCount?: number;
|
phoneNumber?: string;
|
||||||
hasMessages?: boolean;
|
membersCount?: number;
|
||||||
accessControlAddFromInviteLink?: number;
|
hasMessages?: boolean;
|
||||||
accessControlAttributes?: number;
|
accessControlAddFromInviteLink?: number;
|
||||||
accessControlMembers?: number;
|
accessControlAttributes?: number;
|
||||||
announcementsOnly?: boolean;
|
accessControlMembers?: number;
|
||||||
announcementsOnlyReady?: boolean;
|
announcementsOnly?: boolean;
|
||||||
expireTimer?: DurationInSeconds;
|
announcementsOnlyReady?: boolean;
|
||||||
memberships?: ReadonlyArray<{
|
expireTimer?: DurationInSeconds;
|
||||||
uuid: UUIDStringType;
|
memberships?: ReadonlyArray<{
|
||||||
isAdmin: boolean;
|
uuid: UUIDStringType;
|
||||||
}>;
|
isAdmin: boolean;
|
||||||
pendingMemberships?: ReadonlyArray<{
|
}>;
|
||||||
uuid: UUIDStringType;
|
pendingMemberships?: ReadonlyArray<{
|
||||||
addedByUserId?: UUIDStringType;
|
uuid: UUIDStringType;
|
||||||
}>;
|
addedByUserId?: UUIDStringType;
|
||||||
pendingApprovalMemberships?: ReadonlyArray<{
|
}>;
|
||||||
uuid: UUIDStringType;
|
pendingApprovalMemberships?: ReadonlyArray<{
|
||||||
}>;
|
uuid: UUIDStringType;
|
||||||
bannedMemberships?: ReadonlyArray<UUIDStringType>;
|
}>;
|
||||||
muteExpiresAt?: number;
|
bannedMemberships?: ReadonlyArray<UUIDStringType>;
|
||||||
dontNotifyForMentionsIfMuted?: boolean;
|
muteExpiresAt?: number;
|
||||||
isMe: boolean;
|
dontNotifyForMentionsIfMuted?: boolean;
|
||||||
lastUpdated?: number;
|
isMe: boolean;
|
||||||
// This is used by the CompositionInput for @mentions
|
lastUpdated?: number;
|
||||||
sortedGroupMembers?: ReadonlyArray<ConversationType>;
|
// This is used by the CompositionInput for @mentions
|
||||||
title: string;
|
sortedGroupMembers?: ReadonlyArray<ConversationType>;
|
||||||
titleNoDefault?: string;
|
title: string;
|
||||||
searchableTitle?: string;
|
titleNoDefault?: string;
|
||||||
unreadCount?: number;
|
searchableTitle?: string;
|
||||||
isSelected?: boolean;
|
unreadCount?: number;
|
||||||
isFetchingUUID?: boolean;
|
isSelected?: boolean;
|
||||||
typingContactId?: string;
|
isFetchingUUID?: boolean;
|
||||||
recentMediaItems?: ReadonlyArray<MediaItemType>;
|
typingContactId?: string;
|
||||||
profileSharing?: boolean;
|
recentMediaItems?: ReadonlyArray<MediaItemType>;
|
||||||
|
profileSharing?: boolean;
|
||||||
|
|
||||||
shouldShowDraft?: boolean;
|
shouldShowDraft?: boolean;
|
||||||
draftText?: string;
|
draftText?: string;
|
||||||
draftBodyRanges?: DraftBodyRangesType;
|
draftBodyRanges?: DraftBodyRangesType;
|
||||||
draftPreview?: string;
|
draftPreview?: string;
|
||||||
|
|
||||||
sharedGroupNames: ReadonlyArray<string>;
|
sharedGroupNames: ReadonlyArray<string>;
|
||||||
groupDescription?: string;
|
groupDescription?: string;
|
||||||
groupVersion?: 1 | 2;
|
groupVersion?: 1 | 2;
|
||||||
groupId?: string;
|
groupId?: string;
|
||||||
groupLink?: string;
|
groupLink?: string;
|
||||||
messageRequestsEnabled?: boolean;
|
messageRequestsEnabled?: boolean;
|
||||||
acceptedMessageRequest: boolean;
|
acceptedMessageRequest: boolean;
|
||||||
secretParams?: string;
|
secretParams?: string;
|
||||||
publicParams?: string;
|
publicParams?: string;
|
||||||
profileKey?: string;
|
profileKey?: string;
|
||||||
voiceNotePlaybackRate?: number;
|
voiceNotePlaybackRate?: number;
|
||||||
|
|
||||||
badges: ReadonlyArray<
|
badges: ReadonlyArray<
|
||||||
|
| {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
id: string;
|
||||||
|
expiresAt: number;
|
||||||
|
isVisible: boolean;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
} & (
|
||||||
| {
|
| {
|
||||||
id: string;
|
type: 'direct';
|
||||||
|
storySendMode?: undefined;
|
||||||
|
acknowledgedGroupNameCollisions?: undefined;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
id: string;
|
type: 'group';
|
||||||
expiresAt: number;
|
storySendMode: StorySendMode;
|
||||||
isVisible: boolean;
|
acknowledgedGroupNameCollisions: GroupNameCollisionsWithIdsByTitle;
|
||||||
}
|
}
|
||||||
>;
|
)
|
||||||
} & (
|
>;
|
||||||
| {
|
export type ProfileDataType = ReadonlyDeep<
|
||||||
type: 'direct';
|
{
|
||||||
storySendMode?: undefined;
|
firstName: string;
|
||||||
acknowledgedGroupNameCollisions?: undefined;
|
} & Pick<ConversationType, 'aboutEmoji' | 'aboutText' | 'familyName'>
|
||||||
}
|
>;
|
||||||
| {
|
|
||||||
type: 'group';
|
|
||||||
storySendMode: StorySendMode;
|
|
||||||
acknowledgedGroupNameCollisions: GroupNameCollisionsWithIdsByTitle;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
export type ProfileDataType = {
|
|
||||||
firstName: string;
|
|
||||||
} & Pick<ConversationType, 'aboutEmoji' | 'aboutText' | 'familyName'>;
|
|
||||||
|
|
||||||
export type ConversationLookupType = {
|
export type ConversationLookupType = ReadonlyDeep<{
|
||||||
[key: string]: ConversationType;
|
[key: string]: ConversationType;
|
||||||
};
|
}>;
|
||||||
export type CustomError = Error & {
|
export type CustomError = ReadonlyDeep<
|
||||||
identifier?: string;
|
Error & {
|
||||||
number?: string;
|
identifier?: string;
|
||||||
};
|
number?: string;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
type MessagePointerType = {
|
type MessagePointerType = ReadonlyDeep<{
|
||||||
id: string;
|
id: string;
|
||||||
received_at: number;
|
received_at: number;
|
||||||
sent_at?: number;
|
sent_at?: number;
|
||||||
};
|
}>;
|
||||||
type MessageMetricsType = {
|
type MessageMetricsType = ReadonlyDeep<{
|
||||||
newest?: MessagePointerType;
|
newest?: MessagePointerType;
|
||||||
oldest?: MessagePointerType;
|
oldest?: MessagePointerType;
|
||||||
oldestUnseen?: MessagePointerType;
|
oldestUnseen?: MessagePointerType;
|
||||||
totalUnseen: number;
|
totalUnseen: number;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type MessageLookupType = {
|
export type MessageLookupType = {
|
||||||
[key: string]: MessageWithUIFieldsType;
|
[key: string]: MessageWithUIFieldsType;
|
||||||
};
|
};
|
||||||
export type ConversationMessageType = {
|
export type ConversationMessageType = ReadonlyDeep<{
|
||||||
isNearBottom?: boolean;
|
isNearBottom?: boolean;
|
||||||
messageChangeCounter: number;
|
messageChangeCounter: number;
|
||||||
messageIds: ReadonlyArray<string>;
|
messageIds: ReadonlyArray<string>;
|
||||||
|
@ -337,13 +349,13 @@ export type ConversationMessageType = {
|
||||||
metrics: MessageMetricsType;
|
metrics: MessageMetricsType;
|
||||||
scrollToMessageId?: string;
|
scrollToMessageId?: string;
|
||||||
scrollToMessageCounter: number;
|
scrollToMessageCounter: number;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type MessagesByConversationType = {
|
export type MessagesByConversationType = ReadonlyDeep<{
|
||||||
[key: string]: ConversationMessageType | undefined;
|
[key: string]: ConversationMessageType | undefined;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type PreJoinConversationType = {
|
export type PreJoinConversationType = ReadonlyDeep<{
|
||||||
avatar?: {
|
avatar?: {
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
url?: string;
|
url?: string;
|
||||||
|
@ -352,9 +364,9 @@ export type PreJoinConversationType = {
|
||||||
memberCount: number;
|
memberCount: number;
|
||||||
title: string;
|
title: string;
|
||||||
approvalRequired: boolean;
|
approvalRequired: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ComposerGroupCreationState = {
|
type ComposerGroupCreationState = ReadonlyDeep<{
|
||||||
groupAvatar: undefined | Uint8Array;
|
groupAvatar: undefined | Uint8Array;
|
||||||
groupName: string;
|
groupName: string;
|
||||||
groupExpireTimer: DurationInSeconds;
|
groupExpireTimer: DurationInSeconds;
|
||||||
|
@ -362,13 +374,13 @@ type ComposerGroupCreationState = {
|
||||||
recommendedGroupSizeModalState: OneTimeModalState;
|
recommendedGroupSizeModalState: OneTimeModalState;
|
||||||
selectedConversationIds: ReadonlyArray<string>;
|
selectedConversationIds: ReadonlyArray<string>;
|
||||||
userAvatarData: ReadonlyArray<AvatarDataType>;
|
userAvatarData: ReadonlyArray<AvatarDataType>;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type DistributionVerificationData = {
|
type DistributionVerificationData = ReadonlyDeep<{
|
||||||
uuidsNeedingVerification: ReadonlyArray<UUIDStringType>;
|
uuidsNeedingVerification: Array<UUIDStringType>;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type ConversationVerificationData =
|
export type ConversationVerificationData = ReadonlyDeep<
|
||||||
| {
|
| {
|
||||||
type: ConversationVerificationState.PendingVerification;
|
type: ConversationVerificationState.PendingVerification;
|
||||||
uuidsNeedingVerification: ReadonlyArray<UUIDStringType>;
|
uuidsNeedingVerification: ReadonlyArray<UUIDStringType>;
|
||||||
|
@ -378,14 +390,14 @@ export type ConversationVerificationData =
|
||||||
| {
|
| {
|
||||||
type: ConversationVerificationState.VerificationCancelled;
|
type: ConversationVerificationState.VerificationCancelled;
|
||||||
canceledAt: number;
|
canceledAt: number;
|
||||||
};
|
}
|
||||||
|
|
||||||
type VerificationDataByConversation = Record<
|
|
||||||
string,
|
|
||||||
ConversationVerificationData
|
|
||||||
>;
|
>;
|
||||||
|
|
||||||
type ComposerStateType =
|
type VerificationDataByConversation = ReadonlyDeep<
|
||||||
|
Record<string, ConversationVerificationData>
|
||||||
|
>;
|
||||||
|
|
||||||
|
type ComposerStateType = ReadonlyDeep<
|
||||||
| {
|
| {
|
||||||
step: ComposerStep.StartDirectConversation;
|
step: ComposerStep.StartDirectConversation;
|
||||||
searchTerm: string;
|
searchTerm: string;
|
||||||
|
@ -403,9 +415,10 @@ type ComposerStateType =
|
||||||
(
|
(
|
||||||
| { isCreating: false; hasError: boolean }
|
| { isCreating: false; hasError: boolean }
|
||||||
| { isCreating: true; hasError: false }
|
| { isCreating: true; hasError: false }
|
||||||
));
|
))
|
||||||
|
>;
|
||||||
|
|
||||||
type ContactSpoofingReviewStateType =
|
type ContactSpoofingReviewStateType = ReadonlyDeep<
|
||||||
| {
|
| {
|
||||||
type: ContactSpoofingType.DirectConversationWithSameTitle;
|
type: ContactSpoofingType.DirectConversationWithSameTitle;
|
||||||
safeConversationId: string;
|
safeConversationId: string;
|
||||||
|
@ -413,9 +426,11 @@ type ContactSpoofingReviewStateType =
|
||||||
| {
|
| {
|
||||||
type: ContactSpoofingType.MultipleGroupMembersWithSameTitle;
|
type: ContactSpoofingType.MultipleGroupMembersWithSameTitle;
|
||||||
groupConversationId: string;
|
groupConversationId: string;
|
||||||
};
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
export type ConversationsStateType = {
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep -- FIXME
|
||||||
|
export type ConversationsStateType = Readonly<{
|
||||||
preJoinConversation?: PreJoinConversationType;
|
preJoinConversation?: PreJoinConversationType;
|
||||||
invitedUuidsForNewlyCreatedGroup?: ReadonlyArray<string>;
|
invitedUuidsForNewlyCreatedGroup?: ReadonlyArray<string>;
|
||||||
conversationLookup: ConversationLookupType;
|
conversationLookup: ConversationLookupType;
|
||||||
|
@ -444,7 +459,7 @@ export type ConversationsStateType = {
|
||||||
// Note: it's very important that both of these locations are always kept up to date
|
// Note: it's very important that both of these locations are always kept up to date
|
||||||
messagesLookup: MessageLookupType;
|
messagesLookup: MessageLookupType;
|
||||||
messagesByConversation: MessagesByConversationType;
|
messagesByConversation: MessagesByConversationType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|
||||||
|
@ -502,35 +517,37 @@ export const SET_VOICE_NOTE_PLAYBACK_RATE =
|
||||||
'conversations/SET_VOICE_NOTE_PLAYBACK_RATE';
|
'conversations/SET_VOICE_NOTE_PLAYBACK_RATE';
|
||||||
export const CONVERSATION_UNLOADED = 'CONVERSATION_UNLOADED';
|
export const CONVERSATION_UNLOADED = 'CONVERSATION_UNLOADED';
|
||||||
|
|
||||||
export type CancelVerificationDataByConversationActionType = {
|
export type CancelVerificationDataByConversationActionType = ReadonlyDeep<{
|
||||||
type: typeof CANCEL_CONVERSATION_PENDING_VERIFICATION;
|
type: typeof CANCEL_CONVERSATION_PENDING_VERIFICATION;
|
||||||
payload: {
|
payload: {
|
||||||
canceledAt: number;
|
canceledAt: number;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type ClearGroupCreationErrorActionType = { type: 'CLEAR_GROUP_CREATION_ERROR' };
|
type ClearGroupCreationErrorActionType = ReadonlyDeep<{
|
||||||
type ClearInvitedUuidsForNewlyCreatedGroupActionType = {
|
type: 'CLEAR_GROUP_CREATION_ERROR';
|
||||||
|
}>;
|
||||||
|
type ClearInvitedUuidsForNewlyCreatedGroupActionType = ReadonlyDeep<{
|
||||||
type: 'CLEAR_INVITED_UUIDS_FOR_NEWLY_CREATED_GROUP';
|
type: 'CLEAR_INVITED_UUIDS_FOR_NEWLY_CREATED_GROUP';
|
||||||
};
|
}>;
|
||||||
type ClearVerificationDataByConversationActionType = {
|
type ClearVerificationDataByConversationActionType = ReadonlyDeep<{
|
||||||
type: typeof CLEAR_CONVERSATIONS_PENDING_VERIFICATION;
|
type: typeof CLEAR_CONVERSATIONS_PENDING_VERIFICATION;
|
||||||
};
|
}>;
|
||||||
type ClearCancelledVerificationActionType = {
|
type ClearCancelledVerificationActionType = ReadonlyDeep<{
|
||||||
type: typeof CLEAR_CANCELLED_VERIFICATION;
|
type: typeof CLEAR_CANCELLED_VERIFICATION;
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type CloseContactSpoofingReviewActionType = {
|
type CloseContactSpoofingReviewActionType = ReadonlyDeep<{
|
||||||
type: 'CLOSE_CONTACT_SPOOFING_REVIEW';
|
type: 'CLOSE_CONTACT_SPOOFING_REVIEW';
|
||||||
};
|
}>;
|
||||||
type CloseMaximumGroupSizeModalActionType = {
|
type CloseMaximumGroupSizeModalActionType = ReadonlyDeep<{
|
||||||
type: 'CLOSE_MAXIMUM_GROUP_SIZE_MODAL';
|
type: 'CLOSE_MAXIMUM_GROUP_SIZE_MODAL';
|
||||||
};
|
}>;
|
||||||
type CloseRecommendedGroupSizeModalActionType = {
|
type CloseRecommendedGroupSizeModalActionType = ReadonlyDeep<{
|
||||||
type: 'CLOSE_RECOMMENDED_GROUP_SIZE_MODAL';
|
type: 'CLOSE_RECOMMENDED_GROUP_SIZE_MODAL';
|
||||||
};
|
}>;
|
||||||
type ColorsChangedActionType = {
|
type ColorsChangedActionType = ReadonlyDeep<{
|
||||||
type: typeof COLORS_CHANGED;
|
type: typeof COLORS_CHANGED;
|
||||||
payload: {
|
payload: {
|
||||||
conversationColor?: ConversationColorType;
|
conversationColor?: ConversationColorType;
|
||||||
|
@ -539,41 +556,41 @@ type ColorsChangedActionType = {
|
||||||
value: CustomColorType;
|
value: CustomColorType;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type ColorSelectedPayloadType = {
|
type ColorSelectedPayloadType = ReadonlyDeep<{
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
conversationColor?: ConversationColorType;
|
conversationColor?: ConversationColorType;
|
||||||
customColorData?: {
|
customColorData?: {
|
||||||
id: string;
|
id: string;
|
||||||
value: CustomColorType;
|
value: CustomColorType;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
export type ColorSelectedActionType = {
|
export type ColorSelectedActionType = ReadonlyDeep<{
|
||||||
type: typeof COLOR_SELECTED;
|
type: typeof COLOR_SELECTED;
|
||||||
payload: ColorSelectedPayloadType;
|
payload: ColorSelectedPayloadType;
|
||||||
};
|
}>;
|
||||||
type ComposeDeleteAvatarActionType = {
|
type ComposeDeleteAvatarActionType = ReadonlyDeep<{
|
||||||
type: typeof COMPOSE_REMOVE_AVATAR;
|
type: typeof COMPOSE_REMOVE_AVATAR;
|
||||||
payload: AvatarDataType;
|
payload: AvatarDataType;
|
||||||
};
|
}>;
|
||||||
type ComposeReplaceAvatarsActionType = {
|
type ComposeReplaceAvatarsActionType = ReadonlyDeep<{
|
||||||
type: typeof COMPOSE_REPLACE_AVATAR;
|
type: typeof COMPOSE_REPLACE_AVATAR;
|
||||||
payload: {
|
payload: {
|
||||||
curr: AvatarDataType;
|
curr: AvatarDataType;
|
||||||
prev?: AvatarDataType;
|
prev?: AvatarDataType;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type ComposeSaveAvatarActionType = {
|
type ComposeSaveAvatarActionType = ReadonlyDeep<{
|
||||||
type: typeof COMPOSE_ADD_AVATAR;
|
type: typeof COMPOSE_ADD_AVATAR;
|
||||||
payload: AvatarDataType;
|
payload: AvatarDataType;
|
||||||
};
|
}>;
|
||||||
type CustomColorRemovedActionType = {
|
type CustomColorRemovedActionType = ReadonlyDeep<{
|
||||||
type: typeof CUSTOM_COLOR_REMOVED;
|
type: typeof CUSTOM_COLOR_REMOVED;
|
||||||
payload: {
|
payload: {
|
||||||
colorId: string;
|
colorId: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type DiscardMessagesActionType = {
|
type DiscardMessagesActionType = ReadonlyDeep<{
|
||||||
type: typeof DISCARD_MESSAGES;
|
type: typeof DISCARD_MESSAGES;
|
||||||
payload: Readonly<
|
payload: Readonly<
|
||||||
| {
|
| {
|
||||||
|
@ -582,71 +599,72 @@ type DiscardMessagesActionType = {
|
||||||
}
|
}
|
||||||
| { conversationId: string; numberToKeepAtTop: number }
|
| { conversationId: string; numberToKeepAtTop: number }
|
||||||
>;
|
>;
|
||||||
};
|
}>;
|
||||||
type SetPreJoinConversationActionType = {
|
type SetPreJoinConversationActionType = ReadonlyDeep<{
|
||||||
type: 'SET_PRE_JOIN_CONVERSATION';
|
type: 'SET_PRE_JOIN_CONVERSATION';
|
||||||
payload: {
|
payload: {
|
||||||
data: PreJoinConversationType | undefined;
|
data: PreJoinConversationType | undefined;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ConversationAddedActionType = {
|
type ConversationAddedActionType = ReadonlyDeep<{
|
||||||
type: 'CONVERSATION_ADDED';
|
type: 'CONVERSATION_ADDED';
|
||||||
payload: {
|
payload: {
|
||||||
id: string;
|
id: string;
|
||||||
data: ConversationType;
|
data: ConversationType;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
export type ConversationChangedActionType = {
|
export type ConversationChangedActionType = ReadonlyDeep<{
|
||||||
type: 'CONVERSATION_CHANGED';
|
type: 'CONVERSATION_CHANGED';
|
||||||
payload: {
|
payload: {
|
||||||
id: string;
|
id: string;
|
||||||
data: ConversationType;
|
data: ConversationType;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
export type ConversationRemovedActionType = {
|
export type ConversationRemovedActionType = ReadonlyDeep<{
|
||||||
type: 'CONVERSATION_REMOVED';
|
type: 'CONVERSATION_REMOVED';
|
||||||
payload: {
|
payload: {
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
export type ConversationUnloadedActionType = {
|
export type ConversationUnloadedActionType = ReadonlyDeep<{
|
||||||
type: typeof CONVERSATION_UNLOADED;
|
type: typeof CONVERSATION_UNLOADED;
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type CreateGroupPendingActionType = {
|
type CreateGroupPendingActionType = ReadonlyDeep<{
|
||||||
type: 'CREATE_GROUP_PENDING';
|
type: 'CREATE_GROUP_PENDING';
|
||||||
};
|
}>;
|
||||||
type CreateGroupFulfilledActionType = {
|
type CreateGroupFulfilledActionType = ReadonlyDeep<{
|
||||||
type: 'CREATE_GROUP_FULFILLED';
|
type: 'CREATE_GROUP_FULFILLED';
|
||||||
payload: {
|
payload: {
|
||||||
invitedUuids: ReadonlyArray<UUIDStringType>;
|
invitedUuids: ReadonlyArray<UUIDStringType>;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type CreateGroupRejectedActionType = {
|
type CreateGroupRejectedActionType = ReadonlyDeep<{
|
||||||
type: 'CREATE_GROUP_REJECTED';
|
type: 'CREATE_GROUP_REJECTED';
|
||||||
};
|
}>;
|
||||||
export type RemoveAllConversationsActionType = {
|
export type RemoveAllConversationsActionType = ReadonlyDeep<{
|
||||||
type: 'CONVERSATIONS_REMOVE_ALL';
|
type: 'CONVERSATIONS_REMOVE_ALL';
|
||||||
payload: null;
|
payload: null;
|
||||||
};
|
}>;
|
||||||
export type MessageSelectedActionType = {
|
export type MessageSelectedActionType = ReadonlyDeep<{
|
||||||
type: 'MESSAGE_SELECTED';
|
type: 'MESSAGE_SELECTED';
|
||||||
payload: {
|
payload: {
|
||||||
messageId: string;
|
messageId: string;
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type ConversationStoppedByMissingVerificationActionType = {
|
type ConversationStoppedByMissingVerificationActionType = ReadonlyDeep<{
|
||||||
type: typeof CONVERSATION_STOPPED_BY_MISSING_VERIFICATION;
|
type: typeof CONVERSATION_STOPPED_BY_MISSING_VERIFICATION;
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
distributionId?: string;
|
distributionId?: string;
|
||||||
untrustedUuids: ReadonlyArray<UUIDStringType>;
|
untrustedUuids: ReadonlyArray<UUIDStringType>;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep -- FIXME
|
||||||
export type MessageChangedActionType = {
|
export type MessageChangedActionType = {
|
||||||
type: typeof MESSAGE_CHANGED;
|
type: typeof MESSAGE_CHANGED;
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -655,22 +673,23 @@ export type MessageChangedActionType = {
|
||||||
data: MessageAttributesType;
|
data: MessageAttributesType;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
export type MessageDeletedActionType = {
|
export type MessageDeletedActionType = ReadonlyDeep<{
|
||||||
type: typeof MESSAGE_DELETED;
|
type: typeof MESSAGE_DELETED;
|
||||||
payload: {
|
payload: {
|
||||||
id: string;
|
id: string;
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
export type MessageExpandedActionType = {
|
export type MessageExpandedActionType = ReadonlyDeep<{
|
||||||
type: 'MESSAGE_EXPANDED';
|
type: 'MESSAGE_EXPANDED';
|
||||||
payload: {
|
payload: {
|
||||||
id: string;
|
id: string;
|
||||||
displayLimit: number;
|
displayLimit: number;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type MessagesAddedActionType = {
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep -- FIXME
|
||||||
|
export type MessagesAddedActionType = Readonly<{
|
||||||
type: 'MESSAGES_ADDED';
|
type: 'MESSAGES_ADDED';
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
|
@ -679,27 +698,28 @@ export type MessagesAddedActionType = {
|
||||||
isNewMessage: boolean;
|
isNewMessage: boolean;
|
||||||
messages: ReadonlyArray<MessageAttributesType>;
|
messages: ReadonlyArray<MessageAttributesType>;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type MessageExpiredActionType = {
|
export type MessageExpiredActionType = ReadonlyDeep<{
|
||||||
type: typeof MESSAGE_EXPIRED;
|
type: typeof MESSAGE_EXPIRED;
|
||||||
payload: {
|
payload: {
|
||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type RepairNewestMessageActionType = {
|
export type RepairNewestMessageActionType = ReadonlyDeep<{
|
||||||
type: 'REPAIR_NEWEST_MESSAGE';
|
type: 'REPAIR_NEWEST_MESSAGE';
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
export type RepairOldestMessageActionType = {
|
export type RepairOldestMessageActionType = ReadonlyDeep<{
|
||||||
type: 'REPAIR_OLDEST_MESSAGE';
|
type: 'REPAIR_OLDEST_MESSAGE';
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type MessagesResetActionType = {
|
export type MessagesResetActionType = {
|
||||||
type: 'MESSAGES_RESET';
|
type: 'MESSAGES_RESET';
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -712,132 +732,135 @@ export type MessagesResetActionType = {
|
||||||
unboundedFetch: boolean;
|
unboundedFetch: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
export type SetMessageLoadingStateActionType = {
|
export type SetMessageLoadingStateActionType = ReadonlyDeep<{
|
||||||
type: 'SET_MESSAGE_LOADING_STATE';
|
type: 'SET_MESSAGE_LOADING_STATE';
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
messageLoadingState: undefined | TimelineMessageLoadingState;
|
messageLoadingState: undefined | TimelineMessageLoadingState;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
export type SetIsNearBottomActionType = {
|
export type SetIsNearBottomActionType = ReadonlyDeep<{
|
||||||
type: 'SET_NEAR_BOTTOM';
|
type: 'SET_NEAR_BOTTOM';
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
isNearBottom: boolean;
|
isNearBottom: boolean;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
export type ScrollToMessageActionType = {
|
export type ScrollToMessageActionType = ReadonlyDeep<{
|
||||||
type: 'SCROLL_TO_MESSAGE';
|
type: 'SCROLL_TO_MESSAGE';
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
messageId: string;
|
messageId: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
export type ClearSelectedMessageActionType = {
|
export type ClearSelectedMessageActionType = ReadonlyDeep<{
|
||||||
type: 'CLEAR_SELECTED_MESSAGE';
|
type: 'CLEAR_SELECTED_MESSAGE';
|
||||||
payload: null;
|
payload: null;
|
||||||
};
|
}>;
|
||||||
export type ClearUnreadMetricsActionType = {
|
export type ClearUnreadMetricsActionType = ReadonlyDeep<{
|
||||||
type: 'CLEAR_UNREAD_METRICS';
|
type: 'CLEAR_UNREAD_METRICS';
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
export type SelectedConversationChangedActionType = {
|
export type SelectedConversationChangedActionType = ReadonlyDeep<{
|
||||||
type: typeof SELECTED_CONVERSATION_CHANGED;
|
type: typeof SELECTED_CONVERSATION_CHANGED;
|
||||||
payload: {
|
payload: {
|
||||||
conversationId?: string;
|
conversationId?: string;
|
||||||
messageId?: string;
|
messageId?: string;
|
||||||
switchToAssociatedView?: boolean;
|
switchToAssociatedView?: boolean;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type ReviewGroupMemberNameCollisionActionType = {
|
type ReviewGroupMemberNameCollisionActionType = ReadonlyDeep<{
|
||||||
type: 'REVIEW_GROUP_MEMBER_NAME_COLLISION';
|
type: 'REVIEW_GROUP_MEMBER_NAME_COLLISION';
|
||||||
payload: {
|
payload: {
|
||||||
groupConversationId: string;
|
groupConversationId: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type ReviewMessageRequestNameCollisionActionType = {
|
type ReviewMessageRequestNameCollisionActionType = ReadonlyDeep<{
|
||||||
type: 'REVIEW_MESSAGE_REQUEST_NAME_COLLISION';
|
type: 'REVIEW_MESSAGE_REQUEST_NAME_COLLISION';
|
||||||
payload: {
|
payload: {
|
||||||
safeConversationId: string;
|
safeConversationId: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type ShowInboxActionType = {
|
type ShowInboxActionType = ReadonlyDeep<{
|
||||||
type: 'SHOW_INBOX';
|
type: 'SHOW_INBOX';
|
||||||
payload: null;
|
payload: null;
|
||||||
};
|
}>;
|
||||||
export type ShowArchivedConversationsActionType = {
|
export type ShowArchivedConversationsActionType = ReadonlyDeep<{
|
||||||
type: 'SHOW_ARCHIVED_CONVERSATIONS';
|
type: 'SHOW_ARCHIVED_CONVERSATIONS';
|
||||||
payload: null;
|
payload: null;
|
||||||
};
|
}>;
|
||||||
type SetComposeGroupAvatarActionType = {
|
type SetComposeGroupAvatarActionType = ReadonlyDeep<{
|
||||||
type: 'SET_COMPOSE_GROUP_AVATAR';
|
type: 'SET_COMPOSE_GROUP_AVATAR';
|
||||||
payload: { groupAvatar: undefined | Uint8Array };
|
payload: { groupAvatar: undefined | Uint8Array };
|
||||||
};
|
}>;
|
||||||
type SetComposeGroupNameActionType = {
|
type SetComposeGroupNameActionType = ReadonlyDeep<{
|
||||||
type: 'SET_COMPOSE_GROUP_NAME';
|
type: 'SET_COMPOSE_GROUP_NAME';
|
||||||
payload: { groupName: string };
|
payload: { groupName: string };
|
||||||
};
|
}>;
|
||||||
type SetComposeGroupExpireTimerActionType = {
|
type SetComposeGroupExpireTimerActionType = ReadonlyDeep<{
|
||||||
type: 'SET_COMPOSE_GROUP_EXPIRE_TIMER';
|
type: 'SET_COMPOSE_GROUP_EXPIRE_TIMER';
|
||||||
payload: { groupExpireTimer: DurationInSeconds };
|
payload: { groupExpireTimer: DurationInSeconds };
|
||||||
};
|
}>;
|
||||||
type SetComposeSearchTermActionType = {
|
type SetComposeSearchTermActionType = ReadonlyDeep<{
|
||||||
type: 'SET_COMPOSE_SEARCH_TERM';
|
type: 'SET_COMPOSE_SEARCH_TERM';
|
||||||
payload: { searchTerm: string };
|
payload: { searchTerm: string };
|
||||||
};
|
}>;
|
||||||
type SetIsFetchingUUIDActionType = {
|
type SetIsFetchingUUIDActionType = ReadonlyDeep<{
|
||||||
type: 'SET_IS_FETCHING_UUID';
|
type: 'SET_IS_FETCHING_UUID';
|
||||||
payload: {
|
payload: {
|
||||||
identifier: UUIDFetchStateKeyType;
|
identifier: UUIDFetchStateKeyType;
|
||||||
isFetching: boolean;
|
isFetching: boolean;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type SetRecentMediaItemsActionType = {
|
type SetRecentMediaItemsActionType = ReadonlyDeep<{
|
||||||
type: 'SET_RECENT_MEDIA_ITEMS';
|
type: 'SET_RECENT_MEDIA_ITEMS';
|
||||||
payload: {
|
payload: {
|
||||||
id: string;
|
id: string;
|
||||||
recentMediaItems: ReadonlyArray<MediaItemType>;
|
recentMediaItems: ReadonlyArray<MediaItemType>;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type ToggleComposeEditingAvatarActionType = {
|
type ToggleComposeEditingAvatarActionType = ReadonlyDeep<{
|
||||||
type: typeof COMPOSE_TOGGLE_EDITING_AVATAR;
|
type: typeof COMPOSE_TOGGLE_EDITING_AVATAR;
|
||||||
};
|
}>;
|
||||||
type StartComposingActionType = {
|
type StartComposingActionType = ReadonlyDeep<{
|
||||||
type: 'START_COMPOSING';
|
type: 'START_COMPOSING';
|
||||||
};
|
}>;
|
||||||
type ShowChooseGroupMembersActionType = {
|
type ShowChooseGroupMembersActionType = ReadonlyDeep<{
|
||||||
type: 'SHOW_CHOOSE_GROUP_MEMBERS';
|
type: 'SHOW_CHOOSE_GROUP_MEMBERS';
|
||||||
};
|
}>;
|
||||||
type StartSettingGroupMetadataActionType = {
|
type StartSettingGroupMetadataActionType = ReadonlyDeep<{
|
||||||
type: 'START_SETTING_GROUP_METADATA';
|
type: 'START_SETTING_GROUP_METADATA';
|
||||||
};
|
}>;
|
||||||
export type ToggleConversationInChooseMembersActionType = {
|
export type ToggleConversationInChooseMembersActionType = ReadonlyDeep<{
|
||||||
type: 'TOGGLE_CONVERSATION_IN_CHOOSE_MEMBERS';
|
type: 'TOGGLE_CONVERSATION_IN_CHOOSE_MEMBERS';
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
maxRecommendedGroupSize: number;
|
maxRecommendedGroupSize: number;
|
||||||
maxGroupSize: number;
|
maxGroupSize: number;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type PushPanelActionType = {
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep -- FIXME
|
||||||
|
type PushPanelActionType = Readonly<{
|
||||||
type: typeof PUSH_PANEL;
|
type: typeof PUSH_PANEL;
|
||||||
payload: PanelRenderType;
|
payload: PanelRenderType;
|
||||||
};
|
}>;
|
||||||
type PopPanelActionType = {
|
type PopPanelActionType = ReadonlyDeep<{
|
||||||
type: typeof POP_PANEL;
|
type: typeof POP_PANEL;
|
||||||
payload: null;
|
payload: null;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ReplaceAvatarsActionType = {
|
type ReplaceAvatarsActionType = ReadonlyDeep<{
|
||||||
type: typeof REPLACE_AVATARS;
|
type: typeof REPLACE_AVATARS;
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
avatars: ReadonlyArray<AvatarDataType>;
|
avatars: ReadonlyArray<AvatarDataType>;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep -- FIXME
|
||||||
export type ConversationActionType =
|
export type ConversationActionType =
|
||||||
| CancelVerificationDataByConversationActionType
|
| CancelVerificationDataByConversationActionType
|
||||||
| ClearCancelledVerificationActionType
|
| ClearCancelledVerificationActionType
|
||||||
|
@ -1109,7 +1132,7 @@ function onMoveToInbox(conversationId: string): ShowToastActionType {
|
||||||
|
|
||||||
function acknowledgeGroupMemberNameCollisions(
|
function acknowledgeGroupMemberNameCollisions(
|
||||||
conversationId: string,
|
conversationId: string,
|
||||||
groupNameCollisions: Readonly<GroupNameCollisionsWithIdsByTitle>
|
groupNameCollisions: ReadonlyDeep<GroupNameCollisionsWithIdsByTitle>
|
||||||
): NoopActionType {
|
): NoopActionType {
|
||||||
const conversation = window.ConversationController.get(conversationId);
|
const conversation = window.ConversationController.get(conversationId);
|
||||||
if (!conversation) {
|
if (!conversation) {
|
||||||
|
@ -1907,10 +1930,10 @@ function kickOffAttachmentDownload(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type AttachmentOptions = {
|
type AttachmentOptions = ReadonlyDeep<{
|
||||||
messageId: string;
|
messageId: string;
|
||||||
attachment: AttachmentType;
|
attachment: AttachmentType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
function markAttachmentAsCorrupted(
|
function markAttachmentAsCorrupted(
|
||||||
options: AttachmentOptions
|
options: AttachmentOptions
|
||||||
|
@ -2512,13 +2535,14 @@ function reviewMessageRequestNameCollision(
|
||||||
return { type: 'REVIEW_MESSAGE_REQUEST_NAME_COLLISION', payload };
|
return { type: 'REVIEW_MESSAGE_REQUEST_NAME_COLLISION', payload };
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MessageResetOptionsType = Readonly<{
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
|
export type MessageResetOptionsType = {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
messages: ReadonlyArray<MessageAttributesType>;
|
messages: ReadonlyArray<MessageAttributesType>;
|
||||||
metrics: MessageMetricsType;
|
metrics: MessageMetricsType;
|
||||||
scrollToMessageId?: string;
|
scrollToMessageId?: string;
|
||||||
unboundedFetch?: boolean;
|
unboundedFetch?: boolean;
|
||||||
}>;
|
};
|
||||||
|
|
||||||
function messagesReset({
|
function messagesReset({
|
||||||
conversationId,
|
conversationId,
|
||||||
|
@ -2583,9 +2607,9 @@ function setIsFetchingUUID(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PushPanelForConversationActionType = (
|
export type PushPanelForConversationActionType = ReadonlyDeep<
|
||||||
panel: PanelRequestType
|
(panel: PanelRequestType) => unknown
|
||||||
) => unknown;
|
>;
|
||||||
|
|
||||||
function pushPanelForConversation(
|
function pushPanelForConversation(
|
||||||
panel: PanelRequestType
|
panel: PanelRequestType
|
||||||
|
@ -2619,7 +2643,7 @@ function pushPanelForConversation(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PopPanelForConversationActionType = () => unknown;
|
export type PopPanelForConversationActionType = ReadonlyDeep<() => unknown>;
|
||||||
|
|
||||||
function popPanelForConversation(): ThunkAction<
|
function popPanelForConversation(): ThunkAction<
|
||||||
void,
|
void,
|
||||||
|
@ -3016,11 +3040,9 @@ function loadRecentMediaItems(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SaveAttachmentActionCreatorType = (
|
export type SaveAttachmentActionCreatorType = ReadonlyDeep<
|
||||||
attachment: AttachmentType,
|
(attachment: AttachmentType, timestamp?: number, index?: number) => unknown
|
||||||
timestamp?: number,
|
>;
|
||||||
index?: number
|
|
||||||
) => unknown;
|
|
||||||
|
|
||||||
function saveAttachment(
|
function saveAttachment(
|
||||||
attachment: AttachmentType,
|
attachment: AttachmentType,
|
||||||
|
@ -3475,14 +3497,14 @@ function showInbox(): ShowInboxActionType {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShowConversationArgsType = {
|
type ShowConversationArgsType = ReadonlyDeep<{
|
||||||
conversationId?: string;
|
conversationId?: string;
|
||||||
messageId?: string;
|
messageId?: string;
|
||||||
switchToAssociatedView?: boolean;
|
switchToAssociatedView?: boolean;
|
||||||
};
|
}>;
|
||||||
export type ShowConversationType = (
|
export type ShowConversationType = ReadonlyDeep<
|
||||||
options: ShowConversationArgsType
|
(options: ShowConversationArgsType) => unknown
|
||||||
) => unknown;
|
>;
|
||||||
|
|
||||||
function showConversation({
|
function showConversation({
|
||||||
conversationId,
|
conversationId,
|
||||||
|
@ -3858,10 +3880,12 @@ function getVerificationDataForConversation({
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return same data, and we do nothing. Return undefined, and we'll delete the list.
|
// Return same data, and we do nothing. Return undefined, and we'll delete the list.
|
||||||
type DistributionVisitor = (
|
type DistributionVisitor = ReadonlyDeep<
|
||||||
id: string,
|
(
|
||||||
data: DistributionVerificationData
|
id: string,
|
||||||
) => DistributionVerificationData | undefined;
|
data: DistributionVerificationData
|
||||||
|
) => DistributionVerificationData | undefined
|
||||||
|
>;
|
||||||
|
|
||||||
function visitListsInVerificationData(
|
function visitListsInVerificationData(
|
||||||
existing: VerificationDataByConversation,
|
existing: VerificationDataByConversation,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2022 Signal Messenger, LLC
|
// Copyright 2022 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import * as log from '../../logging/log';
|
import * as log from '../../logging/log';
|
||||||
import { showToast } from '../../util/showToast';
|
import { showToast } from '../../util/showToast';
|
||||||
import * as Errors from '../../types/errors';
|
import * as Errors from '../../types/errors';
|
||||||
|
@ -10,10 +11,10 @@ import type { PromiseAction } from '../util';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type CrashReportsStateType = {
|
export type CrashReportsStateType = ReadonlyDeep<{
|
||||||
count: number;
|
count: number;
|
||||||
isPending: boolean;
|
isPending: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
|
@ -21,15 +22,16 @@ const SET_COUNT = 'crashReports/SET_COUNT';
|
||||||
const UPLOAD = 'crashReports/UPLOAD';
|
const UPLOAD = 'crashReports/UPLOAD';
|
||||||
const ERASE = 'crashReports/ERASE';
|
const ERASE = 'crashReports/ERASE';
|
||||||
|
|
||||||
type SetCrashReportCountActionType = {
|
type SetCrashReportCountActionType = ReadonlyDeep<{
|
||||||
type: typeof SET_COUNT;
|
type: typeof SET_COUNT;
|
||||||
payload: number;
|
payload: number;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CrashReportsActionType =
|
type CrashReportsActionType = ReadonlyDeep<
|
||||||
| SetCrashReportCountActionType
|
| SetCrashReportCountActionType
|
||||||
| PromiseAction<typeof UPLOAD>
|
| PromiseAction<typeof UPLOAD>
|
||||||
| PromiseAction<typeof ERASE>;
|
| PromiseAction<typeof ERASE>
|
||||||
|
>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import { take, uniq } from 'lodash';
|
import { take, uniq } from 'lodash';
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { EmojiPickDataType } from '../../components/emoji/EmojiPicker';
|
import type { EmojiPickDataType } from '../../components/emoji/EmojiPicker';
|
||||||
import dataInterface from '../../sql/Client';
|
import dataInterface from '../../sql/Client';
|
||||||
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
||||||
|
@ -12,18 +13,18 @@ const { updateEmojiUsage } = dataInterface;
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type EmojisStateType = {
|
export type EmojisStateType = ReadonlyDeep<{
|
||||||
readonly recents: Array<string>;
|
recents: Array<string>;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
type UseEmojiAction = {
|
type UseEmojiAction = ReadonlyDeep<{
|
||||||
type: 'emojis/USE_EMOJI';
|
type: 'emojis/USE_EMOJI';
|
||||||
payload: string;
|
payload: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type EmojisActionType = UseEmojiAction;
|
type EmojisActionType = ReadonlyDeep<UseEmojiAction>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
@ -64,8 +65,8 @@ function getEmptyState(): EmojisStateType {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function reducer(
|
export function reducer(
|
||||||
state: Readonly<EmojisStateType> = getEmptyState(),
|
state: EmojisStateType = getEmptyState(),
|
||||||
action: Readonly<EmojisActionType>
|
action: EmojisActionType
|
||||||
): EmojisStateType {
|
): EmojisStateType {
|
||||||
if (action.type === 'emojis/USE_EMOJI') {
|
if (action.type === 'emojis/USE_EMOJI') {
|
||||||
const { payload } = action;
|
const { payload } = action;
|
||||||
|
|
|
@ -1,22 +1,25 @@
|
||||||
// Copyright 2020 Signal Messenger, LLC
|
// Copyright 2020 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type ExpirationStateType = {
|
export type ExpirationStateType = ReadonlyDeep<{
|
||||||
hasExpired: boolean;
|
hasExpired: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
const HYDRATE_EXPIRATION_STATUS = 'expiration/HYDRATE_EXPIRATION_STATUS';
|
const HYDRATE_EXPIRATION_STATUS = 'expiration/HYDRATE_EXPIRATION_STATUS';
|
||||||
|
|
||||||
type HyrdateExpirationStatusActionType = {
|
type HyrdateExpirationStatusActionType = ReadonlyDeep<{
|
||||||
type: 'expiration/HYDRATE_EXPIRATION_STATUS';
|
type: 'expiration/HYDRATE_EXPIRATION_STATUS';
|
||||||
payload: boolean;
|
payload: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type ExpirationActionType = HyrdateExpirationStatusActionType;
|
export type ExpirationActionType =
|
||||||
|
ReadonlyDeep<HyrdateExpirationStatusActionType>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { ExplodePromiseResultType } from '../../util/explodePromise';
|
import type { ExplodePromiseResultType } from '../../util/explodePromise';
|
||||||
import type { GroupV2PendingMemberType } from '../../model-types.d';
|
import type { GroupV2PendingMemberType } from '../../model-types.d';
|
||||||
import type { PropsForMessage } from '../selectors/message';
|
import type { PropsForMessage } from '../selectors/message';
|
||||||
|
@ -21,24 +22,23 @@ import { getGroupMigrationMembers } from '../../groups';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type ForwardMessagePropsType = Omit<
|
export type ForwardMessagePropsType = ReadonlyDeep<
|
||||||
PropsForMessage,
|
Omit<PropsForMessage, 'renderingContext' | 'menu' | 'contextMenu'>
|
||||||
'renderingContext' | 'menu' | 'contextMenu'
|
|
||||||
>;
|
>;
|
||||||
export type SafetyNumberChangedBlockingDataType = Readonly<{
|
export type SafetyNumberChangedBlockingDataType = ReadonlyDeep<{
|
||||||
promiseUuid: UUIDStringType;
|
promiseUuid: UUIDStringType;
|
||||||
source?: SafetyNumberChangeSource;
|
source?: SafetyNumberChangeSource;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
type MigrateToGV2PropsType = {
|
type MigrateToGV2PropsType = ReadonlyDeep<{
|
||||||
areWeInvited: boolean;
|
areWeInvited: boolean;
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
droppedMemberIds: ReadonlyArray<string>;
|
droppedMemberIds: Array<string>;
|
||||||
hasMigrated: boolean;
|
hasMigrated: boolean;
|
||||||
invitedMemberIds: ReadonlyArray<string>;
|
invitedMemberIds: Array<string>;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type GlobalModalsStateType = Readonly<{
|
export type GlobalModalsStateType = ReadonlyDeep<{
|
||||||
addUserToAnotherGroupModalContactId?: string;
|
addUserToAnotherGroupModalContactId?: string;
|
||||||
contactModalState?: ContactModalStateType;
|
contactModalState?: ContactModalStateType;
|
||||||
errorModalProps?: {
|
errorModalProps?: {
|
||||||
|
@ -90,12 +90,12 @@ const SHOW_ERROR_MODAL = 'globalModals/SHOW_ERROR_MODAL';
|
||||||
const CLOSE_SHORTCUT_GUIDE_MODAL = 'globalModals/CLOSE_SHORTCUT_GUIDE_MODAL';
|
const CLOSE_SHORTCUT_GUIDE_MODAL = 'globalModals/CLOSE_SHORTCUT_GUIDE_MODAL';
|
||||||
const SHOW_SHORTCUT_GUIDE_MODAL = 'globalModals/SHOW_SHORTCUT_GUIDE_MODAL';
|
const SHOW_SHORTCUT_GUIDE_MODAL = 'globalModals/SHOW_SHORTCUT_GUIDE_MODAL';
|
||||||
|
|
||||||
export type ContactModalStateType = {
|
export type ContactModalStateType = ReadonlyDeep<{
|
||||||
contactId: string;
|
contactId: string;
|
||||||
conversationId?: string;
|
conversationId?: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type UserNotFoundModalStateType =
|
export type UserNotFoundModalStateType = ReadonlyDeep<
|
||||||
| {
|
| {
|
||||||
type: 'phoneNumber';
|
type: 'phoneNumber';
|
||||||
phoneNumber: string;
|
phoneNumber: string;
|
||||||
|
@ -103,119 +103,120 @@ export type UserNotFoundModalStateType =
|
||||||
| {
|
| {
|
||||||
type: 'username';
|
type: 'username';
|
||||||
username: string;
|
username: string;
|
||||||
};
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
type HideContactModalActionType = {
|
type HideContactModalActionType = ReadonlyDeep<{
|
||||||
type: typeof HIDE_CONTACT_MODAL;
|
type: typeof HIDE_CONTACT_MODAL;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ShowContactModalActionType = {
|
type ShowContactModalActionType = ReadonlyDeep<{
|
||||||
type: typeof SHOW_CONTACT_MODAL;
|
type: typeof SHOW_CONTACT_MODAL;
|
||||||
payload: ContactModalStateType;
|
payload: ContactModalStateType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type HideWhatsNewModalActionType = {
|
type HideWhatsNewModalActionType = ReadonlyDeep<{
|
||||||
type: typeof HIDE_WHATS_NEW_MODAL;
|
type: typeof HIDE_WHATS_NEW_MODAL;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ShowWhatsNewModalActionType = {
|
type ShowWhatsNewModalActionType = ReadonlyDeep<{
|
||||||
type: typeof SHOW_WHATS_NEW_MODAL;
|
type: typeof SHOW_WHATS_NEW_MODAL;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type HideUserNotFoundModalActionType = {
|
type HideUserNotFoundModalActionType = ReadonlyDeep<{
|
||||||
type: typeof HIDE_UUID_NOT_FOUND_MODAL;
|
type: typeof HIDE_UUID_NOT_FOUND_MODAL;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type ShowUserNotFoundModalActionType = {
|
export type ShowUserNotFoundModalActionType = ReadonlyDeep<{
|
||||||
type: typeof SHOW_UUID_NOT_FOUND_MODAL;
|
type: typeof SHOW_UUID_NOT_FOUND_MODAL;
|
||||||
payload: UserNotFoundModalStateType;
|
payload: UserNotFoundModalStateType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleForwardMessageModalActionType = {
|
type ToggleForwardMessageModalActionType = ReadonlyDeep<{
|
||||||
type: typeof TOGGLE_FORWARD_MESSAGE_MODAL;
|
type: typeof TOGGLE_FORWARD_MESSAGE_MODAL;
|
||||||
payload: ForwardMessagePropsType | undefined;
|
payload: ForwardMessagePropsType | undefined;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleProfileEditorActionType = {
|
type ToggleProfileEditorActionType = ReadonlyDeep<{
|
||||||
type: typeof TOGGLE_PROFILE_EDITOR;
|
type: typeof TOGGLE_PROFILE_EDITOR;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type ToggleProfileEditorErrorActionType = {
|
export type ToggleProfileEditorErrorActionType = ReadonlyDeep<{
|
||||||
type: typeof TOGGLE_PROFILE_EDITOR_ERROR;
|
type: typeof TOGGLE_PROFILE_EDITOR_ERROR;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleSafetyNumberModalActionType = {
|
type ToggleSafetyNumberModalActionType = ReadonlyDeep<{
|
||||||
type: typeof TOGGLE_SAFETY_NUMBER_MODAL;
|
type: typeof TOGGLE_SAFETY_NUMBER_MODAL;
|
||||||
payload: string | undefined;
|
payload: string | undefined;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleAddUserToAnotherGroupModalActionType = {
|
type ToggleAddUserToAnotherGroupModalActionType = ReadonlyDeep<{
|
||||||
type: typeof TOGGLE_ADD_USER_TO_ANOTHER_GROUP_MODAL;
|
type: typeof TOGGLE_ADD_USER_TO_ANOTHER_GROUP_MODAL;
|
||||||
payload: string | undefined;
|
payload: string | undefined;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleSignalConnectionsModalActionType = {
|
type ToggleSignalConnectionsModalActionType = ReadonlyDeep<{
|
||||||
type: typeof TOGGLE_SIGNAL_CONNECTIONS_MODAL;
|
type: typeof TOGGLE_SIGNAL_CONNECTIONS_MODAL;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ShowStoriesSettingsActionType = {
|
type ShowStoriesSettingsActionType = ReadonlyDeep<{
|
||||||
type: typeof SHOW_STORIES_SETTINGS;
|
type: typeof SHOW_STORIES_SETTINGS;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type HideStoriesSettingsActionType = {
|
type HideStoriesSettingsActionType = ReadonlyDeep<{
|
||||||
type: typeof HIDE_STORIES_SETTINGS;
|
type: typeof HIDE_STORIES_SETTINGS;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type StartMigrationToGV2ActionType = {
|
type StartMigrationToGV2ActionType = ReadonlyDeep<{
|
||||||
type: typeof SHOW_GV2_MIGRATION_DIALOG;
|
type: typeof SHOW_GV2_MIGRATION_DIALOG;
|
||||||
payload: MigrateToGV2PropsType;
|
payload: MigrateToGV2PropsType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CloseGV2MigrationDialogActionType = {
|
type CloseGV2MigrationDialogActionType = ReadonlyDeep<{
|
||||||
type: typeof CLOSE_GV2_MIGRATION_DIALOG;
|
type: typeof CLOSE_GV2_MIGRATION_DIALOG;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type ShowSendAnywayDialogActionType = {
|
export type ShowSendAnywayDialogActionType = ReadonlyDeep<{
|
||||||
type: typeof SHOW_SEND_ANYWAY_DIALOG;
|
type: typeof SHOW_SEND_ANYWAY_DIALOG;
|
||||||
payload: SafetyNumberChangedBlockingDataType & {
|
payload: SafetyNumberChangedBlockingDataType & {
|
||||||
untrustedByConversation: RecipientsByConversation;
|
untrustedByConversation: RecipientsByConversation;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type HideSendAnywayDialogActiontype = {
|
type HideSendAnywayDialogActiontype = ReadonlyDeep<{
|
||||||
type: typeof HIDE_SEND_ANYWAY_DIALOG;
|
type: typeof HIDE_SEND_ANYWAY_DIALOG;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type ShowStickerPackPreviewActionType = {
|
export type ShowStickerPackPreviewActionType = ReadonlyDeep<{
|
||||||
type: typeof SHOW_STICKER_PACK_PREVIEW;
|
type: typeof SHOW_STICKER_PACK_PREVIEW;
|
||||||
payload: string;
|
payload: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CloseStickerPackPreviewActionType = {
|
type CloseStickerPackPreviewActionType = ReadonlyDeep<{
|
||||||
type: typeof CLOSE_STICKER_PACK_PREVIEW;
|
type: typeof CLOSE_STICKER_PACK_PREVIEW;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CloseErrorModalActionType = {
|
type CloseErrorModalActionType = ReadonlyDeep<{
|
||||||
type: typeof CLOSE_ERROR_MODAL;
|
type: typeof CLOSE_ERROR_MODAL;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ShowErrorModalActionType = {
|
type ShowErrorModalActionType = ReadonlyDeep<{
|
||||||
type: typeof SHOW_ERROR_MODAL;
|
type: typeof SHOW_ERROR_MODAL;
|
||||||
payload: {
|
payload: {
|
||||||
description?: string;
|
description?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CloseShortcutGuideModalActionType = {
|
type CloseShortcutGuideModalActionType = ReadonlyDeep<{
|
||||||
type: typeof CLOSE_SHORTCUT_GUIDE_MODAL;
|
type: typeof CLOSE_SHORTCUT_GUIDE_MODAL;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ShowShortcutGuideModalActionType = {
|
type ShowShortcutGuideModalActionType = ReadonlyDeep<{
|
||||||
type: typeof SHOW_SHORTCUT_GUIDE_MODAL;
|
type: typeof SHOW_SHORTCUT_GUIDE_MODAL;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type GlobalModalsActionType =
|
export type GlobalModalsActionType = ReadonlyDeep<
|
||||||
| StartMigrationToGV2ActionType
|
| StartMigrationToGV2ActionType
|
||||||
| CloseGV2MigrationDialogActionType
|
| CloseGV2MigrationDialogActionType
|
||||||
| HideContactModalActionType
|
| HideContactModalActionType
|
||||||
|
@ -239,7 +240,8 @@ export type GlobalModalsActionType =
|
||||||
| ToggleProfileEditorErrorActionType
|
| ToggleProfileEditorErrorActionType
|
||||||
| ToggleSafetyNumberModalActionType
|
| ToggleSafetyNumberModalActionType
|
||||||
| ToggleAddUserToAnotherGroupModalActionType
|
| ToggleAddUserToAnotherGroupModalActionType
|
||||||
| ToggleSignalConnectionsModalActionType;
|
| ToggleSignalConnectionsModalActionType
|
||||||
|
>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
import { v4 as getGuid } from 'uuid';
|
import { v4 as getGuid } from 'uuid';
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { StateType as RootStateType } from '../reducer';
|
import type { StateType as RootStateType } from '../reducer';
|
||||||
import * as storageShim from '../../shims/storage';
|
import * as storageShim from '../../shims/storage';
|
||||||
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
||||||
|
@ -23,60 +24,61 @@ import type { ConfigMapType as RemoteConfigType } from '../../RemoteConfig';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type ItemsStateType = {
|
export type ItemsStateType = ReadonlyDeep<{
|
||||||
readonly universalExpireTimer?: number;
|
universalExpireTimer?: number;
|
||||||
|
|
||||||
readonly [key: string]: unknown;
|
[key: string]: unknown;
|
||||||
|
|
||||||
readonly remoteConfig?: RemoteConfigType;
|
remoteConfig?: RemoteConfigType;
|
||||||
|
|
||||||
// This property should always be set and this is ensured in background.ts
|
// This property should always be set and this is ensured in background.ts
|
||||||
readonly defaultConversationColor?: DefaultConversationColorType;
|
defaultConversationColor?: DefaultConversationColorType;
|
||||||
|
|
||||||
readonly customColors?: CustomColorsItemType;
|
customColors?: CustomColorsItemType;
|
||||||
|
|
||||||
readonly preferredLeftPaneWidth?: number;
|
preferredLeftPaneWidth?: number;
|
||||||
|
|
||||||
readonly preferredReactionEmoji?: ReadonlyArray<string>;
|
preferredReactionEmoji?: Array<string>;
|
||||||
|
|
||||||
readonly areWeASubscriber?: boolean;
|
areWeASubscriber?: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
type ItemPutAction = {
|
type ItemPutAction = ReadonlyDeep<{
|
||||||
type: 'items/PUT';
|
type: 'items/PUT';
|
||||||
payload: null;
|
payload: null;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ItemPutExternalAction = {
|
type ItemPutExternalAction = ReadonlyDeep<{
|
||||||
type: 'items/PUT_EXTERNAL';
|
type: 'items/PUT_EXTERNAL';
|
||||||
payload: {
|
payload: {
|
||||||
key: string;
|
key: string;
|
||||||
value: unknown;
|
value: unknown;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ItemRemoveAction = {
|
type ItemRemoveAction = ReadonlyDeep<{
|
||||||
type: 'items/REMOVE';
|
type: 'items/REMOVE';
|
||||||
payload: null;
|
payload: null;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ItemRemoveExternalAction = {
|
type ItemRemoveExternalAction = ReadonlyDeep<{
|
||||||
type: 'items/REMOVE_EXTERNAL';
|
type: 'items/REMOVE_EXTERNAL';
|
||||||
payload: string;
|
payload: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ItemsResetAction = {
|
type ItemsResetAction = ReadonlyDeep<{
|
||||||
type: 'items/RESET';
|
type: 'items/RESET';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type ItemsActionType =
|
export type ItemsActionType = ReadonlyDeep<
|
||||||
| ItemPutAction
|
| ItemPutAction
|
||||||
| ItemPutExternalAction
|
| ItemPutExternalAction
|
||||||
| ItemRemoveAction
|
| ItemRemoveAction
|
||||||
| ItemRemoveExternalAction
|
| ItemRemoveExternalAction
|
||||||
| ItemsResetAction;
|
| ItemsResetAction
|
||||||
|
>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { AttachmentType } from '../../types/Attachment';
|
import type { AttachmentType } from '../../types/Attachment';
|
||||||
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
||||||
import type { MediaItemType } from '../../types/MediaItem';
|
import type { MediaItemType } from '../../types/MediaItem';
|
||||||
|
@ -34,6 +35,7 @@ import {
|
||||||
import { showStickerPackPreview } from './globalModals';
|
import { showStickerPackPreview } from './globalModals';
|
||||||
import { useBoundActions } from '../../hooks/useBoundActions';
|
import { useBoundActions } from '../../hooks/useBoundActions';
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type LightboxStateType =
|
export type LightboxStateType =
|
||||||
| {
|
| {
|
||||||
isShowingLightbox: false;
|
isShowingLightbox: false;
|
||||||
|
@ -41,26 +43,28 @@ export type LightboxStateType =
|
||||||
| {
|
| {
|
||||||
isShowingLightbox: true;
|
isShowingLightbox: true;
|
||||||
isViewOnce: boolean;
|
isViewOnce: boolean;
|
||||||
media: ReadonlyArray<MediaItemType>;
|
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>;
|
||||||
selectedAttachmentPath: string | undefined;
|
selectedAttachmentPath: string | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const CLOSE_LIGHTBOX = 'lightbox/CLOSE';
|
const CLOSE_LIGHTBOX = 'lightbox/CLOSE';
|
||||||
const SHOW_LIGHTBOX = 'lightbox/SHOW';
|
const SHOW_LIGHTBOX = 'lightbox/SHOW';
|
||||||
|
|
||||||
type CloseLightboxActionType = {
|
type CloseLightboxActionType = ReadonlyDeep<{
|
||||||
type: typeof CLOSE_LIGHTBOX;
|
type: typeof CLOSE_LIGHTBOX;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type ShowLightboxActionType = {
|
type ShowLightboxActionType = {
|
||||||
type: typeof SHOW_LIGHTBOX;
|
type: typeof SHOW_LIGHTBOX;
|
||||||
payload: {
|
payload: {
|
||||||
isViewOnce: boolean;
|
isViewOnce: boolean;
|
||||||
media: ReadonlyArray<MediaItemType>;
|
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>;
|
||||||
selectedAttachmentPath: string | undefined;
|
selectedAttachmentPath: string | undefined;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type LightboxActionType =
|
type LightboxActionType =
|
||||||
| CloseLightboxActionType
|
| CloseLightboxActionType
|
||||||
| MessageChangedActionType
|
| MessageChangedActionType
|
||||||
|
@ -100,7 +104,7 @@ function closeLightbox(): ThunkAction<
|
||||||
|
|
||||||
function showLightboxWithMedia(
|
function showLightboxWithMedia(
|
||||||
selectedAttachmentPath: string | undefined,
|
selectedAttachmentPath: string | undefined,
|
||||||
media: ReadonlyArray<MediaItemType>
|
media: ReadonlyArray<ReadonlyDeep<MediaItemType>>
|
||||||
): ShowLightboxActionType {
|
): ShowLightboxActionType {
|
||||||
return {
|
return {
|
||||||
type: SHOW_LIGHTBOX,
|
type: SHOW_LIGHTBOX,
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
||||||
import type { LinkPreviewType } from '../../types/message/LinkPreviews';
|
import type { LinkPreviewType } from '../../types/message/LinkPreviews';
|
||||||
import type { MaybeGrabLinkPreviewOptionsType } from '../../types/LinkPreview';
|
import type { MaybeGrabLinkPreviewOptionsType } from '../../types/LinkPreview';
|
||||||
|
@ -16,35 +17,35 @@ import { useBoundActions } from '../../hooks/useBoundActions';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type LinkPreviewsStateType = {
|
export type LinkPreviewsStateType = ReadonlyDeep<{
|
||||||
readonly linkPreview?: LinkPreviewType;
|
linkPreview?: LinkPreviewType;
|
||||||
readonly source?: LinkPreviewSourceType;
|
source?: LinkPreviewSourceType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
export const ADD_PREVIEW = 'linkPreviews/ADD_PREVIEW';
|
export const ADD_PREVIEW = 'linkPreviews/ADD_PREVIEW';
|
||||||
export const REMOVE_PREVIEW = 'linkPreviews/REMOVE_PREVIEW';
|
export const REMOVE_PREVIEW = 'linkPreviews/REMOVE_PREVIEW';
|
||||||
|
|
||||||
export type AddLinkPreviewActionType = {
|
export type AddLinkPreviewActionType = ReadonlyDeep<{
|
||||||
type: 'linkPreviews/ADD_PREVIEW';
|
type: 'linkPreviews/ADD_PREVIEW';
|
||||||
payload: {
|
payload: {
|
||||||
conversationId?: string;
|
conversationId?: string;
|
||||||
linkPreview: LinkPreviewType;
|
linkPreview: LinkPreviewType;
|
||||||
source: LinkPreviewSourceType;
|
source: LinkPreviewSourceType;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type RemoveLinkPreviewActionType = {
|
export type RemoveLinkPreviewActionType = ReadonlyDeep<{
|
||||||
type: 'linkPreviews/REMOVE_PREVIEW';
|
type: 'linkPreviews/REMOVE_PREVIEW';
|
||||||
payload: {
|
payload: {
|
||||||
conversationId?: string;
|
conversationId?: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type LinkPreviewsActionType =
|
type LinkPreviewsActionType = ReadonlyDeep<
|
||||||
| AddLinkPreviewActionType
|
AddLinkPreviewActionType | RemoveLinkPreviewActionType
|
||||||
| RemoveLinkPreviewActionType;
|
>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { isDownloading, hasFailed } from '../../types/Attachment';
|
||||||
import { isNotNil } from '../../util/isNotNil';
|
import { isNotNil } from '../../util/isNotNil';
|
||||||
import { useBoundActions } from '../../hooks/useBoundActions';
|
import { useBoundActions } from '../../hooks/useBoundActions';
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type MediaType = {
|
type MediaType = {
|
||||||
path: string;
|
path: string;
|
||||||
objectURL: string;
|
objectURL: string;
|
||||||
|
@ -44,6 +45,7 @@ type MediaType = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type MediaGalleryStateType = {
|
export type MediaGalleryStateType = {
|
||||||
documents: Array<MediaItemType>;
|
documents: Array<MediaItemType>;
|
||||||
media: Array<MediaType>;
|
media: Array<MediaType>;
|
||||||
|
@ -51,6 +53,7 @@ export type MediaGalleryStateType = {
|
||||||
|
|
||||||
const LOAD_MEDIA_ITEMS = 'mediaGallery/LOAD_MEDIA_ITEMS';
|
const LOAD_MEDIA_ITEMS = 'mediaGallery/LOAD_MEDIA_ITEMS';
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type LoadMediaItemslActionType = {
|
type LoadMediaItemslActionType = {
|
||||||
type: typeof LOAD_MEDIA_ITEMS;
|
type: typeof LOAD_MEDIA_ITEMS;
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -59,6 +62,7 @@ type LoadMediaItemslActionType = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type MediaGalleryActionType =
|
type MediaGalleryActionType =
|
||||||
| ConversationUnloadedActionType
|
| ConversationUnloadedActionType
|
||||||
| LoadMediaItemslActionType
|
| LoadMediaItemslActionType
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
// Copyright 2020 Signal Messenger, LLC
|
// Copyright 2020 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import { SocketStatus } from '../../types/SocketStatus';
|
import { SocketStatus } from '../../types/SocketStatus';
|
||||||
import { trigger } from '../../shims/events';
|
import { trigger } from '../../shims/events';
|
||||||
import { assignWithNoUnnecessaryAllocation } from '../../util/assignWithNoUnnecessaryAllocation';
|
import { assignWithNoUnnecessaryAllocation } from '../../util/assignWithNoUnnecessaryAllocation';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type NetworkStateType = {
|
export type NetworkStateType = ReadonlyDeep<{
|
||||||
isOnline: boolean;
|
isOnline: boolean;
|
||||||
socketStatus: SocketStatus;
|
socketStatus: SocketStatus;
|
||||||
withinConnectingGracePeriod: boolean;
|
withinConnectingGracePeriod: boolean;
|
||||||
challengeStatus: 'required' | 'pending' | 'idle';
|
challengeStatus: 'required' | 'pending' | 'idle';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
|
@ -21,36 +22,37 @@ const CLOSE_CONNECTING_GRACE_PERIOD = 'network/CLOSE_CONNECTING_GRACE_PERIOD';
|
||||||
const RELINK_DEVICE = 'network/RELINK_DEVICE';
|
const RELINK_DEVICE = 'network/RELINK_DEVICE';
|
||||||
const SET_CHALLENGE_STATUS = 'network/SET_CHALLENGE_STATUS';
|
const SET_CHALLENGE_STATUS = 'network/SET_CHALLENGE_STATUS';
|
||||||
|
|
||||||
export type CheckNetworkStatusPayloadType = {
|
export type CheckNetworkStatusPayloadType = ReadonlyDeep<{
|
||||||
isOnline: boolean;
|
isOnline: boolean;
|
||||||
socketStatus: SocketStatus;
|
socketStatus: SocketStatus;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CheckNetworkStatusAction = {
|
type CheckNetworkStatusAction = ReadonlyDeep<{
|
||||||
type: 'network/CHECK_NETWORK_STATUS';
|
type: 'network/CHECK_NETWORK_STATUS';
|
||||||
payload: CheckNetworkStatusPayloadType;
|
payload: CheckNetworkStatusPayloadType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CloseConnectingGracePeriodActionType = {
|
type CloseConnectingGracePeriodActionType = ReadonlyDeep<{
|
||||||
type: 'network/CLOSE_CONNECTING_GRACE_PERIOD';
|
type: 'network/CLOSE_CONNECTING_GRACE_PERIOD';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type RelinkDeviceActionType = {
|
type RelinkDeviceActionType = ReadonlyDeep<{
|
||||||
type: 'network/RELINK_DEVICE';
|
type: 'network/RELINK_DEVICE';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SetChallengeStatusActionType = {
|
type SetChallengeStatusActionType = ReadonlyDeep<{
|
||||||
type: 'network/SET_CHALLENGE_STATUS';
|
type: 'network/SET_CHALLENGE_STATUS';
|
||||||
payload: {
|
payload: {
|
||||||
challengeStatus: NetworkStateType['challengeStatus'];
|
challengeStatus: NetworkStateType['challengeStatus'];
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type NetworkActionType =
|
export type NetworkActionType = ReadonlyDeep<
|
||||||
| CheckNetworkStatusAction
|
| CheckNetworkStatusAction
|
||||||
| CloseConnectingGracePeriodActionType
|
| CloseConnectingGracePeriodActionType
|
||||||
| RelinkDeviceActionType
|
| RelinkDeviceActionType
|
||||||
| SetChallengeStatusActionType;
|
| SetChallengeStatusActionType
|
||||||
|
>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
// Copyright 2019 Signal Messenger, LLC
|
// Copyright 2019 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
export type NoopActionType = {
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
|
|
||||||
|
export type NoopActionType = ReadonlyDeep<{
|
||||||
type: 'NOOP';
|
type: 'NOOP';
|
||||||
payload: null;
|
payload: null;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export function noopAction(): NoopActionType {
|
export function noopAction(): NoopActionType {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import * as log from '../../logging/log';
|
import * as log from '../../logging/log';
|
||||||
import * as Errors from '../../types/errors';
|
import * as Errors from '../../types/errors';
|
||||||
import { replaceIndex } from '../../util/replaceIndex';
|
import { replaceIndex } from '../../util/replaceIndex';
|
||||||
|
@ -16,7 +17,7 @@ import { convertShortName } from '../../components/emoji/lib';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type PreferredReactionsStateType = {
|
export type PreferredReactionsStateType = ReadonlyDeep<{
|
||||||
customizePreferredReactionsModal?: {
|
customizePreferredReactionsModal?: {
|
||||||
draftPreferredReactions: Array<string>;
|
draftPreferredReactions: Array<string>;
|
||||||
originalPreferredReactions: Array<string>;
|
originalPreferredReactions: Array<string>;
|
||||||
|
@ -25,7 +26,7 @@ export type PreferredReactionsStateType = {
|
||||||
| { isSaving: true; hadSaveError: false }
|
| { isSaving: true; hadSaveError: false }
|
||||||
| { isSaving: false; hadSaveError: boolean }
|
| { isSaving: false; hadSaveError: boolean }
|
||||||
);
|
);
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
|
@ -46,45 +47,47 @@ const SAVE_PREFERRED_REACTIONS_REJECTED =
|
||||||
const SELECT_DRAFT_EMOJI_TO_BE_REPLACED =
|
const SELECT_DRAFT_EMOJI_TO_BE_REPLACED =
|
||||||
'preferredReactions/SELECT_DRAFT_EMOJI_TO_BE_REPLACED';
|
'preferredReactions/SELECT_DRAFT_EMOJI_TO_BE_REPLACED';
|
||||||
|
|
||||||
type CancelCustomizePreferredReactionsModalActionType = {
|
type CancelCustomizePreferredReactionsModalActionType = ReadonlyDeep<{
|
||||||
type: typeof CANCEL_CUSTOMIZE_PREFERRED_REACTIONS_MODAL;
|
type: typeof CANCEL_CUSTOMIZE_PREFERRED_REACTIONS_MODAL;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type DeselectDraftEmojiActionType = { type: typeof DESELECT_DRAFT_EMOJI };
|
type DeselectDraftEmojiActionType = ReadonlyDeep<{
|
||||||
|
type: typeof DESELECT_DRAFT_EMOJI;
|
||||||
|
}>;
|
||||||
|
|
||||||
type OpenCustomizePreferredReactionsModalActionType = {
|
type OpenCustomizePreferredReactionsModalActionType = ReadonlyDeep<{
|
||||||
type: typeof OPEN_CUSTOMIZE_PREFERRED_REACTIONS_MODAL;
|
type: typeof OPEN_CUSTOMIZE_PREFERRED_REACTIONS_MODAL;
|
||||||
payload: {
|
payload: {
|
||||||
originalPreferredReactions: Array<string>;
|
originalPreferredReactions: Array<string>;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ReplaceSelectedDraftEmojiActionType = {
|
type ReplaceSelectedDraftEmojiActionType = ReadonlyDeep<{
|
||||||
type: typeof REPLACE_SELECTED_DRAFT_EMOJI;
|
type: typeof REPLACE_SELECTED_DRAFT_EMOJI;
|
||||||
payload: string;
|
payload: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ResetDraftEmojiActionType = {
|
type ResetDraftEmojiActionType = ReadonlyDeep<{
|
||||||
type: typeof RESET_DRAFT_EMOJI;
|
type: typeof RESET_DRAFT_EMOJI;
|
||||||
payload: { skinTone: number };
|
payload: { skinTone: number };
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SavePreferredReactionsFulfilledActionType = {
|
type SavePreferredReactionsFulfilledActionType = ReadonlyDeep<{
|
||||||
type: typeof SAVE_PREFERRED_REACTIONS_FULFILLED;
|
type: typeof SAVE_PREFERRED_REACTIONS_FULFILLED;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SavePreferredReactionsPendingActionType = {
|
type SavePreferredReactionsPendingActionType = ReadonlyDeep<{
|
||||||
type: typeof SAVE_PREFERRED_REACTIONS_PENDING;
|
type: typeof SAVE_PREFERRED_REACTIONS_PENDING;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SavePreferredReactionsRejectedActionType = {
|
type SavePreferredReactionsRejectedActionType = ReadonlyDeep<{
|
||||||
type: typeof SAVE_PREFERRED_REACTIONS_REJECTED;
|
type: typeof SAVE_PREFERRED_REACTIONS_REJECTED;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SelectDraftEmojiToBeReplacedActionType = {
|
type SelectDraftEmojiToBeReplacedActionType = ReadonlyDeep<{
|
||||||
type: typeof SELECT_DRAFT_EMOJI_TO_BE_REPLACED;
|
type: typeof SELECT_DRAFT_EMOJI_TO_BE_REPLACED;
|
||||||
payload: number;
|
payload: number;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Action creators
|
// Action creators
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2020 Signal Messenger, LLC
|
// Copyright 2020 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import { generateSecurityNumberBlock } from '../../util/safetyNumber';
|
import { generateSecurityNumberBlock } from '../../util/safetyNumber';
|
||||||
import type { ConversationType } from './conversations';
|
import type { ConversationType } from './conversations';
|
||||||
import {
|
import {
|
||||||
|
@ -10,17 +11,17 @@ import {
|
||||||
import * as log from '../../logging/log';
|
import * as log from '../../logging/log';
|
||||||
import * as Errors from '../../types/errors';
|
import * as Errors from '../../types/errors';
|
||||||
|
|
||||||
export type SafetyNumberContactType = {
|
export type SafetyNumberContactType = ReadonlyDeep<{
|
||||||
safetyNumber: string;
|
safetyNumber: string;
|
||||||
safetyNumberChanged?: boolean;
|
safetyNumberChanged?: boolean;
|
||||||
verificationDisabled: boolean;
|
verificationDisabled: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type SafetyNumberStateType = {
|
export type SafetyNumberStateType = ReadonlyDeep<{
|
||||||
contacts: {
|
contacts: {
|
||||||
[key: string]: SafetyNumberContactType;
|
[key: string]: SafetyNumberContactType;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
const GENERATE = 'safetyNumber/GENERATE';
|
const GENERATE = 'safetyNumber/GENERATE';
|
||||||
const GENERATE_FULFILLED = 'safetyNumber/GENERATE_FULFILLED';
|
const GENERATE_FULFILLED = 'safetyNumber/GENERATE_FULFILLED';
|
||||||
|
@ -28,51 +29,52 @@ const TOGGLE_VERIFIED = 'safetyNumber/TOGGLE_VERIFIED';
|
||||||
const TOGGLE_VERIFIED_FULFILLED = 'safetyNumber/TOGGLE_VERIFIED_FULFILLED';
|
const TOGGLE_VERIFIED_FULFILLED = 'safetyNumber/TOGGLE_VERIFIED_FULFILLED';
|
||||||
const TOGGLE_VERIFIED_PENDING = 'safetyNumber/TOGGLE_VERIFIED_PENDING';
|
const TOGGLE_VERIFIED_PENDING = 'safetyNumber/TOGGLE_VERIFIED_PENDING';
|
||||||
|
|
||||||
type GenerateAsyncActionType = {
|
type GenerateAsyncActionType = ReadonlyDeep<{
|
||||||
contact: ConversationType;
|
contact: ConversationType;
|
||||||
safetyNumber: string;
|
safetyNumber: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type GenerateActionType = {
|
type GenerateActionType = ReadonlyDeep<{
|
||||||
type: 'safetyNumber/GENERATE';
|
type: 'safetyNumber/GENERATE';
|
||||||
payload: Promise<GenerateAsyncActionType>;
|
payload: Promise<GenerateAsyncActionType>;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type GenerateFulfilledActionType = {
|
type GenerateFulfilledActionType = ReadonlyDeep<{
|
||||||
type: 'safetyNumber/GENERATE_FULFILLED';
|
type: 'safetyNumber/GENERATE_FULFILLED';
|
||||||
payload: GenerateAsyncActionType;
|
payload: GenerateAsyncActionType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleVerifiedAsyncActionType = {
|
type ToggleVerifiedAsyncActionType = ReadonlyDeep<{
|
||||||
contact: ConversationType;
|
contact: ConversationType;
|
||||||
safetyNumber?: string;
|
safetyNumber?: string;
|
||||||
safetyNumberChanged?: boolean;
|
safetyNumberChanged?: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleVerifiedActionType = {
|
type ToggleVerifiedActionType = ReadonlyDeep<{
|
||||||
type: 'safetyNumber/TOGGLE_VERIFIED';
|
type: 'safetyNumber/TOGGLE_VERIFIED';
|
||||||
payload: {
|
payload: {
|
||||||
data: { contact: ConversationType };
|
data: { contact: ConversationType };
|
||||||
promise: Promise<ToggleVerifiedAsyncActionType>;
|
promise: Promise<ToggleVerifiedAsyncActionType>;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleVerifiedPendingActionType = {
|
type ToggleVerifiedPendingActionType = ReadonlyDeep<{
|
||||||
type: 'safetyNumber/TOGGLE_VERIFIED_PENDING';
|
type: 'safetyNumber/TOGGLE_VERIFIED_PENDING';
|
||||||
payload: ToggleVerifiedAsyncActionType;
|
payload: ToggleVerifiedAsyncActionType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleVerifiedFulfilledActionType = {
|
type ToggleVerifiedFulfilledActionType = ReadonlyDeep<{
|
||||||
type: 'safetyNumber/TOGGLE_VERIFIED_FULFILLED';
|
type: 'safetyNumber/TOGGLE_VERIFIED_FULFILLED';
|
||||||
payload: ToggleVerifiedAsyncActionType;
|
payload: ToggleVerifiedAsyncActionType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type SafetyNumberActionType =
|
export type SafetyNumberActionType = ReadonlyDeep<
|
||||||
| GenerateActionType
|
| GenerateActionType
|
||||||
| GenerateFulfilledActionType
|
| GenerateFulfilledActionType
|
||||||
| ToggleVerifiedActionType
|
| ToggleVerifiedActionType
|
||||||
| ToggleVerifiedPendingActionType
|
| ToggleVerifiedPendingActionType
|
||||||
| ToggleVerifiedFulfilledActionType;
|
| ToggleVerifiedFulfilledActionType
|
||||||
|
>;
|
||||||
|
|
||||||
function generate(contact: ConversationType): GenerateActionType {
|
function generate(contact: ConversationType): GenerateActionType {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import type { ThunkAction, ThunkDispatch } from 'redux-thunk';
|
import type { ThunkAction, ThunkDispatch } from 'redux-thunk';
|
||||||
import { debounce, omit, reject } from 'lodash';
|
import { debounce, omit, reject } from 'lodash';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { StateType as RootStateType } from '../reducer';
|
import type { StateType as RootStateType } from '../reducer';
|
||||||
import { cleanSearchTerm } from '../../util/cleanSearchTerm';
|
import { cleanSearchTerm } from '../../util/cleanSearchTerm';
|
||||||
import { filterAndSortConversationsByRecent } from '../../util/filterAndSortConversations';
|
import { filterAndSortConversationsByRecent } from '../../util/filterAndSortConversations';
|
||||||
|
@ -43,15 +44,17 @@ const {
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type MessageSearchResultType = MessageType & {
|
export type MessageSearchResultType = ReadonlyDeep<
|
||||||
snippet?: string;
|
MessageType & {
|
||||||
};
|
snippet?: string;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
export type MessageSearchResultLookupType = {
|
export type MessageSearchResultLookupType = ReadonlyDeep<{
|
||||||
[id: string]: MessageSearchResultType;
|
[id: string]: MessageSearchResultType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type SearchStateType = {
|
export type SearchStateType = ReadonlyDeep<{
|
||||||
startSearchCounter: number;
|
startSearchCounter: number;
|
||||||
searchConversationId?: string;
|
searchConversationId?: string;
|
||||||
contactIds: Array<string>;
|
contactIds: Array<string>;
|
||||||
|
@ -64,49 +67,49 @@ export type SearchStateType = {
|
||||||
// Loading state
|
// Loading state
|
||||||
discussionsLoading: boolean;
|
discussionsLoading: boolean;
|
||||||
messagesLoading: boolean;
|
messagesLoading: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
type SearchMessagesResultsFulfilledActionType = {
|
type SearchMessagesResultsFulfilledActionType = ReadonlyDeep<{
|
||||||
type: 'SEARCH_MESSAGES_RESULTS_FULFILLED';
|
type: 'SEARCH_MESSAGES_RESULTS_FULFILLED';
|
||||||
payload: {
|
payload: {
|
||||||
messages: Array<MessageSearchResultType>;
|
messages: Array<MessageSearchResultType>;
|
||||||
query: string;
|
query: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type SearchDiscussionsResultsFulfilledActionType = {
|
type SearchDiscussionsResultsFulfilledActionType = ReadonlyDeep<{
|
||||||
type: 'SEARCH_DISCUSSIONS_RESULTS_FULFILLED';
|
type: 'SEARCH_DISCUSSIONS_RESULTS_FULFILLED';
|
||||||
payload: {
|
payload: {
|
||||||
conversationIds: Array<string>;
|
conversationIds: Array<string>;
|
||||||
contactIds: Array<string>;
|
contactIds: Array<string>;
|
||||||
query: string;
|
query: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type UpdateSearchTermActionType = {
|
type UpdateSearchTermActionType = ReadonlyDeep<{
|
||||||
type: 'SEARCH_UPDATE';
|
type: 'SEARCH_UPDATE';
|
||||||
payload: {
|
payload: {
|
||||||
query: string;
|
query: string;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
type StartSearchActionType = {
|
type StartSearchActionType = ReadonlyDeep<{
|
||||||
type: 'SEARCH_START';
|
type: 'SEARCH_START';
|
||||||
payload: null;
|
payload: null;
|
||||||
};
|
}>;
|
||||||
type ClearSearchActionType = {
|
type ClearSearchActionType = ReadonlyDeep<{
|
||||||
type: 'SEARCH_CLEAR';
|
type: 'SEARCH_CLEAR';
|
||||||
payload: null;
|
payload: null;
|
||||||
};
|
}>;
|
||||||
type ClearConversationSearchActionType = {
|
type ClearConversationSearchActionType = ReadonlyDeep<{
|
||||||
type: 'CLEAR_CONVERSATION_SEARCH';
|
type: 'CLEAR_CONVERSATION_SEARCH';
|
||||||
payload: null;
|
payload: null;
|
||||||
};
|
}>;
|
||||||
type SearchInConversationActionType = {
|
type SearchInConversationActionType = ReadonlyDeep<{
|
||||||
type: 'SEARCH_IN_CONVERSATION';
|
type: 'SEARCH_IN_CONVERSATION';
|
||||||
payload: { searchConversationId: string };
|
payload: { searchConversationId: string };
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type SearchActionType =
|
export type SearchActionType = ReadonlyDeep<
|
||||||
| SearchMessagesResultsFulfilledActionType
|
| SearchMessagesResultsFulfilledActionType
|
||||||
| SearchDiscussionsResultsFulfilledActionType
|
| SearchDiscussionsResultsFulfilledActionType
|
||||||
| UpdateSearchTermActionType
|
| UpdateSearchTermActionType
|
||||||
|
@ -118,7 +121,8 @@ export type SearchActionType =
|
||||||
| RemoveAllConversationsActionType
|
| RemoveAllConversationsActionType
|
||||||
| SelectedConversationChangedActionType
|
| SelectedConversationChangedActionType
|
||||||
| ShowArchivedConversationsActionType
|
| ShowArchivedConversationsActionType
|
||||||
| ConversationUnloadedActionType;
|
| ConversationUnloadedActionType
|
||||||
|
>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import type { Dictionary } from 'lodash';
|
import type { Dictionary } from 'lodash';
|
||||||
import { omit, reject } from 'lodash';
|
import { omit, reject } from 'lodash';
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type {
|
import type {
|
||||||
StickerPackStatusType,
|
StickerPackStatusType,
|
||||||
StickerType as StickerDBType,
|
StickerType as StickerDBType,
|
||||||
|
@ -24,23 +25,23 @@ const { getRecentStickers, updateStickerLastUsed } = dataInterface;
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type StickersStateType = {
|
export type StickersStateType = ReadonlyDeep<{
|
||||||
readonly installedPack: string | null;
|
installedPack: string | null;
|
||||||
readonly packs: Dictionary<StickerPackDBType>;
|
packs: Dictionary<StickerPackDBType>;
|
||||||
readonly recentStickers: Array<RecentStickerType>;
|
recentStickers: Array<RecentStickerType>;
|
||||||
readonly blessedPacks: Dictionary<boolean>;
|
blessedPacks: Dictionary<boolean>;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// These are for the React components
|
// These are for the React components
|
||||||
|
|
||||||
export type StickerType = {
|
export type StickerType = ReadonlyDeep<{
|
||||||
readonly id: number;
|
id: number;
|
||||||
readonly packId: string;
|
packId: string;
|
||||||
readonly emoji?: string;
|
emoji?: string;
|
||||||
readonly url: string;
|
url: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type StickerPackType = Readonly<{
|
export type StickerPackType = ReadonlyDeep<{
|
||||||
id: string;
|
id: string;
|
||||||
key: string;
|
key: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -56,76 +57,76 @@ export type StickerPackType = Readonly<{
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
type StickerPackAddedAction = {
|
type StickerPackAddedAction = ReadonlyDeep<{
|
||||||
type: 'stickers/STICKER_PACK_ADDED';
|
type: 'stickers/STICKER_PACK_ADDED';
|
||||||
payload: StickerPackDBType;
|
payload: StickerPackDBType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type StickerAddedAction = {
|
type StickerAddedAction = ReadonlyDeep<{
|
||||||
type: 'stickers/STICKER_ADDED';
|
type: 'stickers/STICKER_ADDED';
|
||||||
payload: StickerDBType;
|
payload: StickerDBType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type InstallStickerPackPayloadType = {
|
type InstallStickerPackPayloadType = ReadonlyDeep<{
|
||||||
packId: string;
|
packId: string;
|
||||||
fromSync: boolean;
|
fromSync: boolean;
|
||||||
status: 'installed';
|
status: 'installed';
|
||||||
installedAt: number;
|
installedAt: number;
|
||||||
recentStickers: Array<RecentStickerType>;
|
recentStickers: Array<RecentStickerType>;
|
||||||
};
|
}>;
|
||||||
type InstallStickerPackAction = {
|
type InstallStickerPackAction = ReadonlyDeep<{
|
||||||
type: 'stickers/INSTALL_STICKER_PACK';
|
type: 'stickers/INSTALL_STICKER_PACK';
|
||||||
payload: Promise<InstallStickerPackPayloadType>;
|
payload: Promise<InstallStickerPackPayloadType>;
|
||||||
};
|
}>;
|
||||||
type InstallStickerPackFulfilledAction = {
|
type InstallStickerPackFulfilledAction = ReadonlyDeep<{
|
||||||
type: 'stickers/INSTALL_STICKER_PACK_FULFILLED';
|
type: 'stickers/INSTALL_STICKER_PACK_FULFILLED';
|
||||||
payload: InstallStickerPackPayloadType;
|
payload: InstallStickerPackPayloadType;
|
||||||
};
|
}>;
|
||||||
type ClearInstalledStickerPackAction = {
|
type ClearInstalledStickerPackAction = ReadonlyDeep<{
|
||||||
type: 'stickers/CLEAR_INSTALLED_STICKER_PACK';
|
type: 'stickers/CLEAR_INSTALLED_STICKER_PACK';
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type UninstallStickerPackPayloadType = {
|
type UninstallStickerPackPayloadType = ReadonlyDeep<{
|
||||||
packId: string;
|
packId: string;
|
||||||
fromSync: boolean;
|
fromSync: boolean;
|
||||||
status: 'downloaded';
|
status: 'downloaded';
|
||||||
installedAt?: undefined;
|
installedAt?: undefined;
|
||||||
recentStickers: Array<RecentStickerType>;
|
recentStickers: Array<RecentStickerType>;
|
||||||
};
|
}>;
|
||||||
type UninstallStickerPackAction = {
|
type UninstallStickerPackAction = ReadonlyDeep<{
|
||||||
type: 'stickers/UNINSTALL_STICKER_PACK';
|
type: 'stickers/UNINSTALL_STICKER_PACK';
|
||||||
payload: Promise<UninstallStickerPackPayloadType>;
|
payload: Promise<UninstallStickerPackPayloadType>;
|
||||||
};
|
}>;
|
||||||
type UninstallStickerPackFulfilledAction = {
|
type UninstallStickerPackFulfilledAction = ReadonlyDeep<{
|
||||||
type: 'stickers/UNINSTALL_STICKER_PACK_FULFILLED';
|
type: 'stickers/UNINSTALL_STICKER_PACK_FULFILLED';
|
||||||
payload: UninstallStickerPackPayloadType;
|
payload: UninstallStickerPackPayloadType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type StickerPackUpdatedAction = {
|
type StickerPackUpdatedAction = ReadonlyDeep<{
|
||||||
type: 'stickers/STICKER_PACK_UPDATED';
|
type: 'stickers/STICKER_PACK_UPDATED';
|
||||||
payload: { packId: string; patch: Partial<StickerPackDBType> };
|
payload: { packId: string; patch: Partial<StickerPackDBType> };
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type StickerPackRemovedAction = {
|
type StickerPackRemovedAction = ReadonlyDeep<{
|
||||||
type: 'stickers/REMOVE_STICKER_PACK';
|
type: 'stickers/REMOVE_STICKER_PACK';
|
||||||
payload: string;
|
payload: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type UseStickerPayloadType = {
|
type UseStickerPayloadType = ReadonlyDeep<{
|
||||||
packId: string;
|
packId: string;
|
||||||
stickerId: number;
|
stickerId: number;
|
||||||
time: number;
|
time: number;
|
||||||
};
|
}>;
|
||||||
type UseStickerAction = {
|
type UseStickerAction = ReadonlyDeep<{
|
||||||
type: 'stickers/USE_STICKER';
|
type: 'stickers/USE_STICKER';
|
||||||
payload: Promise<UseStickerPayloadType>;
|
payload: Promise<UseStickerPayloadType>;
|
||||||
};
|
}>;
|
||||||
type UseStickerFulfilledAction = {
|
type UseStickerFulfilledAction = ReadonlyDeep<{
|
||||||
type: 'stickers/USE_STICKER_FULFILLED';
|
type: 'stickers/USE_STICKER_FULFILLED';
|
||||||
payload: UseStickerPayloadType;
|
payload: UseStickerPayloadType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type StickersActionType =
|
export type StickersActionType = ReadonlyDeep<
|
||||||
| ClearInstalledStickerPackAction
|
| ClearInstalledStickerPackAction
|
||||||
| StickerAddedAction
|
| StickerAddedAction
|
||||||
| StickerPackAddedAction
|
| StickerPackAddedAction
|
||||||
|
@ -134,7 +135,8 @@ export type StickersActionType =
|
||||||
| StickerPackUpdatedAction
|
| StickerPackUpdatedAction
|
||||||
| StickerPackRemovedAction
|
| StickerPackRemovedAction
|
||||||
| UseStickerFulfilledAction
|
| UseStickerFulfilledAction
|
||||||
| NoopActionType;
|
| NoopActionType
|
||||||
|
>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import type { ThunkAction, ThunkDispatch } from 'redux-thunk';
|
import type { ThunkAction, ThunkDispatch } from 'redux-thunk';
|
||||||
import { isEqual, pick } from 'lodash';
|
import { isEqual, pick } from 'lodash';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import * as Errors from '../../types/errors';
|
import * as Errors from '../../types/errors';
|
||||||
import type { AttachmentType } from '../../types/Attachment';
|
import type { AttachmentType } from '../../types/Attachment';
|
||||||
import type { DraftBodyRangesType } from '../../types/Util';
|
import type { DraftBodyRangesType } from '../../types/Util';
|
||||||
|
@ -60,44 +61,46 @@ import { SHOW_TOAST } from './toast';
|
||||||
import { ToastType } from '../../types/Toast';
|
import { ToastType } from '../../types/Toast';
|
||||||
import type { ShowToastActionType } from './toast';
|
import type { ShowToastActionType } from './toast';
|
||||||
|
|
||||||
export type StoryDataType = {
|
export type StoryDataType = ReadonlyDeep<
|
||||||
attachment?: AttachmentType;
|
{
|
||||||
hasReplies?: boolean;
|
attachment?: AttachmentType;
|
||||||
hasRepliesFromSelf?: boolean;
|
hasReplies?: boolean;
|
||||||
messageId: string;
|
hasRepliesFromSelf?: boolean;
|
||||||
startedDownload?: boolean;
|
messageId: string;
|
||||||
} & Pick<
|
startedDownload?: boolean;
|
||||||
MessageAttributesType,
|
} & Pick<
|
||||||
| 'canReplyToStory'
|
MessageAttributesType,
|
||||||
| 'conversationId'
|
| 'canReplyToStory'
|
||||||
| 'deletedForEveryone'
|
| 'conversationId'
|
||||||
| 'reactions'
|
| 'deletedForEveryone'
|
||||||
| 'readAt'
|
| 'reactions'
|
||||||
| 'readStatus'
|
| 'readAt'
|
||||||
| 'sendStateByConversationId'
|
| 'readStatus'
|
||||||
| 'source'
|
| 'sendStateByConversationId'
|
||||||
| 'sourceUuid'
|
| 'source'
|
||||||
| 'storyDistributionListId'
|
| 'sourceUuid'
|
||||||
| 'timestamp'
|
| 'storyDistributionListId'
|
||||||
| 'type'
|
| 'timestamp'
|
||||||
| 'storyRecipientsVersion'
|
| 'type'
|
||||||
> & {
|
| 'storyRecipientsVersion'
|
||||||
// don't want the fields to be optional as in MessageAttributesType
|
> & {
|
||||||
expireTimer: DurationInSeconds | undefined;
|
// don't want the fields to be optional as in MessageAttributesType
|
||||||
expirationStartTimestamp: number | undefined;
|
expireTimer: DurationInSeconds | undefined;
|
||||||
sourceDevice: number;
|
expirationStartTimestamp: number | undefined;
|
||||||
};
|
sourceDevice: number;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
export type SelectedStoryDataType = {
|
export type SelectedStoryDataType = ReadonlyDeep<{
|
||||||
currentIndex: number;
|
currentIndex: number;
|
||||||
messageId: string;
|
messageId: string;
|
||||||
numStories: number;
|
numStories: number;
|
||||||
storyViewMode: StoryViewModeType;
|
storyViewMode: StoryViewModeType;
|
||||||
unviewedStoryConversationIdsSorted: Array<string>;
|
unviewedStoryConversationIdsSorted: Array<string>;
|
||||||
viewTarget?: StoryViewTargetType;
|
viewTarget?: StoryViewTargetType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type AddStoryData =
|
export type AddStoryData = ReadonlyDeep<
|
||||||
| {
|
| {
|
||||||
type: 'Media';
|
type: 'Media';
|
||||||
file: File;
|
file: File;
|
||||||
|
@ -107,8 +110,10 @@ export type AddStoryData =
|
||||||
type: 'Text';
|
type: 'Text';
|
||||||
sending?: boolean;
|
sending?: boolean;
|
||||||
}
|
}
|
||||||
| undefined;
|
| undefined
|
||||||
|
>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type RecipientsByConversation = Record<
|
export type RecipientsByConversation = Record<
|
||||||
string, // conversationId
|
string, // conversationId
|
||||||
{
|
{
|
||||||
|
@ -125,6 +130,7 @@ export type RecipientsByConversation = Record<
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type StoriesStateType = Readonly<{
|
export type StoriesStateType = Readonly<{
|
||||||
addStoryData: AddStoryData;
|
addStoryData: AddStoryData;
|
||||||
hasAllStoriesUnmuted: boolean;
|
hasAllStoriesUnmuted: boolean;
|
||||||
|
@ -157,20 +163,21 @@ const SET_ADD_STORY_DATA = 'stories/SET_ADD_STORY_DATA';
|
||||||
const SET_STORY_SENDING = 'stories/SET_STORY_SENDING';
|
const SET_STORY_SENDING = 'stories/SET_STORY_SENDING';
|
||||||
const SET_HAS_ALL_STORIES_UNMUTED = 'stories/SET_HAS_ALL_STORIES_UNMUTED';
|
const SET_HAS_ALL_STORIES_UNMUTED = 'stories/SET_HAS_ALL_STORIES_UNMUTED';
|
||||||
|
|
||||||
type DOEStoryActionType = {
|
type DOEStoryActionType = ReadonlyDeep<{
|
||||||
type: typeof DOE_STORY;
|
type: typeof DOE_STORY;
|
||||||
payload: string;
|
payload: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ListMembersVerified = {
|
type ListMembersVerified = ReadonlyDeep<{
|
||||||
type: typeof LIST_MEMBERS_VERIFIED;
|
type: typeof LIST_MEMBERS_VERIFIED;
|
||||||
payload: {
|
payload: {
|
||||||
conversationId: string;
|
conversationId: string;
|
||||||
distributionId: string | undefined;
|
distributionId: string | undefined;
|
||||||
uuids: Array<UUIDStringType>;
|
uuids: Array<UUIDStringType>;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
type LoadStoryRepliesActionType = {
|
type LoadStoryRepliesActionType = {
|
||||||
type: typeof LOAD_STORY_REPLIES;
|
type: typeof LOAD_STORY_REPLIES;
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -179,62 +186,63 @@ type LoadStoryRepliesActionType = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
type MarkStoryReadActionType = {
|
type MarkStoryReadActionType = ReadonlyDeep<{
|
||||||
type: typeof MARK_STORY_READ;
|
type: typeof MARK_STORY_READ;
|
||||||
payload: {
|
payload: {
|
||||||
messageId: string;
|
messageId: string;
|
||||||
readAt: number;
|
readAt: number;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type QueueStoryDownloadActionType = {
|
type QueueStoryDownloadActionType = ReadonlyDeep<{
|
||||||
type: typeof QUEUE_STORY_DOWNLOAD;
|
type: typeof QUEUE_STORY_DOWNLOAD;
|
||||||
payload: string;
|
payload: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SendStoryModalOpenStateChanged = {
|
type SendStoryModalOpenStateChanged = ReadonlyDeep<{
|
||||||
type: typeof SEND_STORY_MODAL_OPEN_STATE_CHANGED;
|
type: typeof SEND_STORY_MODAL_OPEN_STATE_CHANGED;
|
||||||
payload: number | undefined;
|
payload: number | undefined;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type StoryChangedActionType = {
|
type StoryChangedActionType = ReadonlyDeep<{
|
||||||
type: typeof STORY_CHANGED;
|
type: typeof STORY_CHANGED;
|
||||||
payload: StoryDataType;
|
payload: StoryDataType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ToggleViewActionType = {
|
type ToggleViewActionType = ReadonlyDeep<{
|
||||||
type: typeof TOGGLE_VIEW;
|
type: typeof TOGGLE_VIEW;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ViewStoryActionType = {
|
type ViewStoryActionType = ReadonlyDeep<{
|
||||||
type: typeof VIEW_STORY;
|
type: typeof VIEW_STORY;
|
||||||
payload: SelectedStoryDataType | undefined;
|
payload: SelectedStoryDataType | undefined;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type StoryReplyDeletedActionType = {
|
type StoryReplyDeletedActionType = ReadonlyDeep<{
|
||||||
type: typeof STORY_REPLY_DELETED;
|
type: typeof STORY_REPLY_DELETED;
|
||||||
payload: string;
|
payload: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type RemoveAllStoriesActionType = {
|
type RemoveAllStoriesActionType = ReadonlyDeep<{
|
||||||
type: typeof REMOVE_ALL_STORIES;
|
type: typeof REMOVE_ALL_STORIES;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SetAddStoryDataType = {
|
type SetAddStoryDataType = ReadonlyDeep<{
|
||||||
type: typeof SET_ADD_STORY_DATA;
|
type: typeof SET_ADD_STORY_DATA;
|
||||||
payload: AddStoryData;
|
payload: AddStoryData;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SetStorySendingType = {
|
type SetStorySendingType = ReadonlyDeep<{
|
||||||
type: typeof SET_STORY_SENDING;
|
type: typeof SET_STORY_SENDING;
|
||||||
payload: boolean;
|
payload: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SetHasAllStoriesUnmutedType = {
|
type SetHasAllStoriesUnmutedType = ReadonlyDeep<{
|
||||||
type: typeof SET_HAS_ALL_STORIES_UNMUTED;
|
type: typeof SET_HAS_ALL_STORIES_UNMUTED;
|
||||||
payload: boolean;
|
payload: boolean;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type StoriesActionType =
|
export type StoriesActionType =
|
||||||
| DOEStoryActionType
|
| DOEStoryActionType
|
||||||
| ListMembersVerified
|
| ListMembersVerified
|
||||||
|
@ -817,11 +825,13 @@ const getSelectedStoryDataForConversationId = (
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ViewUserStoriesActionCreatorType = (opts: {
|
export type ViewUserStoriesActionCreatorType = ReadonlyDeep<
|
||||||
conversationId: string;
|
(opts: {
|
||||||
storyViewMode?: StoryViewModeType;
|
conversationId: string;
|
||||||
viewTarget?: StoryViewTargetType;
|
storyViewMode?: StoryViewModeType;
|
||||||
}) => unknown;
|
viewTarget?: StoryViewTargetType;
|
||||||
|
}) => unknown
|
||||||
|
>;
|
||||||
|
|
||||||
const viewUserStories: ViewUserStoriesActionCreatorType = ({
|
const viewUserStories: ViewUserStoriesActionCreatorType = ({
|
||||||
conversationId,
|
conversationId,
|
||||||
|
@ -886,7 +896,7 @@ function removeAllStories(): RemoveAllStoriesActionType {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type ViewStoryOptionsType =
|
type ViewStoryOptionsType = ReadonlyDeep<
|
||||||
| {
|
| {
|
||||||
closeViewer: true;
|
closeViewer: true;
|
||||||
}
|
}
|
||||||
|
@ -895,15 +905,18 @@ type ViewStoryOptionsType =
|
||||||
storyViewMode: StoryViewModeType;
|
storyViewMode: StoryViewModeType;
|
||||||
viewDirection?: StoryViewDirectionType;
|
viewDirection?: StoryViewDirectionType;
|
||||||
viewTarget?: StoryViewTargetType;
|
viewTarget?: StoryViewTargetType;
|
||||||
};
|
}
|
||||||
|
>;
|
||||||
|
|
||||||
export type ViewStoryActionCreatorType = (
|
export type ViewStoryActionCreatorType = ReadonlyDeep<
|
||||||
opts: ViewStoryOptionsType
|
(opts: ViewStoryOptionsType) => unknown
|
||||||
) => unknown;
|
>;
|
||||||
|
|
||||||
export type DispatchableViewStoryType = (
|
export type DispatchableViewStoryType = ReadonlyDeep<
|
||||||
opts: ViewStoryOptionsType
|
(
|
||||||
) => ThunkAction<void, RootStateType, unknown, ViewStoryActionType>;
|
opts: ViewStoryOptionsType
|
||||||
|
) => ThunkAction<void, RootStateType, unknown, ViewStoryActionType>
|
||||||
|
>;
|
||||||
|
|
||||||
const viewStory: ViewStoryActionCreatorType = (
|
const viewStory: ViewStoryActionCreatorType = (
|
||||||
opts
|
opts
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import { omit } from 'lodash';
|
import { omit } from 'lodash';
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { StateType as RootStateType } from '../reducer';
|
import type { StateType as RootStateType } from '../reducer';
|
||||||
import type { StoryDistributionWithMembersType } from '../../sql/Interface';
|
import type { StoryDistributionWithMembersType } from '../../sql/Interface';
|
||||||
import type { UUIDStringType } from '../../types/UUID';
|
import type { UUIDStringType } from '../../types/UUID';
|
||||||
|
@ -19,18 +20,18 @@ import { useBoundActions } from '../../hooks/useBoundActions';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type StoryDistributionListDataType = {
|
export type StoryDistributionListDataType = ReadonlyDeep<{
|
||||||
id: UUIDStringType;
|
id: UUIDStringType;
|
||||||
deletedAtTimestamp?: number;
|
deletedAtTimestamp?: number;
|
||||||
name: string;
|
name: string;
|
||||||
allowsReplies: boolean;
|
allowsReplies: boolean;
|
||||||
isBlockList: boolean;
|
isBlockList: boolean;
|
||||||
memberUuids: Array<UUIDStringType>;
|
memberUuids: Array<UUIDStringType>;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type StoryDistributionListStateType = {
|
export type StoryDistributionListStateType = ReadonlyDeep<{
|
||||||
distributionLists: Array<StoryDistributionListDataType>;
|
distributionLists: Array<StoryDistributionListDataType>;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
|
@ -43,65 +44,65 @@ export const MODIFY_LIST = 'storyDistributionLists/MODIFY_LIST';
|
||||||
const RESET_MY_STORIES = 'storyDistributionLists/RESET_MY_STORIES';
|
const RESET_MY_STORIES = 'storyDistributionLists/RESET_MY_STORIES';
|
||||||
export const VIEWERS_CHANGED = 'storyDistributionLists/VIEWERS_CHANGED';
|
export const VIEWERS_CHANGED = 'storyDistributionLists/VIEWERS_CHANGED';
|
||||||
|
|
||||||
type AllowRepliesChangedActionType = {
|
type AllowRepliesChangedActionType = ReadonlyDeep<{
|
||||||
type: typeof ALLOW_REPLIES_CHANGED;
|
type: typeof ALLOW_REPLIES_CHANGED;
|
||||||
payload: {
|
payload: {
|
||||||
listId: string;
|
listId: string;
|
||||||
allowsReplies: boolean;
|
allowsReplies: boolean;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CreateListActionType = {
|
type CreateListActionType = ReadonlyDeep<{
|
||||||
type: typeof CREATE_LIST;
|
type: typeof CREATE_LIST;
|
||||||
payload: StoryDistributionListDataType;
|
payload: StoryDistributionListDataType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type DeleteListActionType = {
|
type DeleteListActionType = ReadonlyDeep<{
|
||||||
type: typeof DELETE_LIST;
|
type: typeof DELETE_LIST;
|
||||||
payload: {
|
payload: {
|
||||||
listId: string;
|
listId: string;
|
||||||
deletedAtTimestamp: number;
|
deletedAtTimestamp: number;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type HideMyStoriesFromActionType = {
|
type HideMyStoriesFromActionType = ReadonlyDeep<{
|
||||||
type: typeof HIDE_MY_STORIES_FROM;
|
type: typeof HIDE_MY_STORIES_FROM;
|
||||||
payload: Array<UUIDStringType>;
|
payload: Array<UUIDStringType>;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ModifyDistributionListType = Omit<
|
type ModifyDistributionListType = ReadonlyDeep<
|
||||||
StoryDistributionListDataType,
|
Omit<StoryDistributionListDataType, 'memberUuids'> & {
|
||||||
'memberUuids'
|
membersToAdd: Array<UUIDStringType>;
|
||||||
> & {
|
membersToRemove: Array<UUIDStringType>;
|
||||||
membersToAdd: Array<UUIDStringType>;
|
}
|
||||||
membersToRemove: Array<UUIDStringType>;
|
>;
|
||||||
};
|
|
||||||
|
|
||||||
export type ModifyListActionType = {
|
export type ModifyListActionType = ReadonlyDeep<{
|
||||||
type: typeof MODIFY_LIST;
|
type: typeof MODIFY_LIST;
|
||||||
payload: ModifyDistributionListType;
|
payload: ModifyDistributionListType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ResetMyStoriesActionType = {
|
type ResetMyStoriesActionType = ReadonlyDeep<{
|
||||||
type: typeof RESET_MY_STORIES;
|
type: typeof RESET_MY_STORIES;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ViewersChangedActionType = {
|
type ViewersChangedActionType = ReadonlyDeep<{
|
||||||
type: typeof VIEWERS_CHANGED;
|
type: typeof VIEWERS_CHANGED;
|
||||||
payload: {
|
payload: {
|
||||||
listId: string;
|
listId: string;
|
||||||
memberUuids: Array<UUIDStringType>;
|
memberUuids: Array<UUIDStringType>;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type StoryDistributionListsActionType =
|
export type StoryDistributionListsActionType = ReadonlyDeep<
|
||||||
| AllowRepliesChangedActionType
|
| AllowRepliesChangedActionType
|
||||||
| CreateListActionType
|
| CreateListActionType
|
||||||
| DeleteListActionType
|
| DeleteListActionType
|
||||||
| HideMyStoriesFromActionType
|
| HideMyStoriesFromActionType
|
||||||
| ModifyListActionType
|
| ModifyListActionType
|
||||||
| ResetMyStoriesActionType
|
| ResetMyStoriesActionType
|
||||||
| ViewersChangedActionType;
|
| ViewersChangedActionType
|
||||||
|
>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
@ -503,7 +504,7 @@ export function getEmptyState(): StoryDistributionListStateType {
|
||||||
}
|
}
|
||||||
|
|
||||||
function replaceDistributionListData(
|
function replaceDistributionListData(
|
||||||
distributionLists: Array<StoryDistributionListDataType>,
|
distributionLists: ReadonlyArray<StoryDistributionListDataType>,
|
||||||
listId: string,
|
listId: string,
|
||||||
getNextDistributionListData: (
|
getNextDistributionListData: (
|
||||||
list: StoryDistributionListDataType
|
list: StoryDistributionListDataType
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
import type { BoundActionCreatorsMapObject } from '../../hooks/useBoundActions';
|
||||||
import type { NoopActionType } from './noop';
|
import type { NoopActionType } from './noop';
|
||||||
import type { ReplacementValuesType } from '../../types/Util';
|
import type { ReplacementValuesType } from '../../types/Util';
|
||||||
|
@ -11,6 +12,7 @@ import type { ToastType } from '../../types/Toast';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type ToastStateType = {
|
export type ToastStateType = {
|
||||||
toast?: {
|
toast?: {
|
||||||
toastType: ToastType;
|
toastType: ToastType;
|
||||||
|
@ -23,10 +25,11 @@ export type ToastStateType = {
|
||||||
const HIDE_TOAST = 'toast/HIDE_TOAST';
|
const HIDE_TOAST = 'toast/HIDE_TOAST';
|
||||||
export const SHOW_TOAST = 'toast/SHOW_TOAST';
|
export const SHOW_TOAST = 'toast/SHOW_TOAST';
|
||||||
|
|
||||||
type HideToastActionType = {
|
type HideToastActionType = ReadonlyDeep<{
|
||||||
type: typeof HIDE_TOAST;
|
type: typeof HIDE_TOAST;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type ShowToastActionType = {
|
export type ShowToastActionType = {
|
||||||
type: typeof SHOW_TOAST;
|
type: typeof SHOW_TOAST;
|
||||||
payload: {
|
payload: {
|
||||||
|
@ -35,6 +38,7 @@ export type ShowToastActionType = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
export type ToastActionType = HideToastActionType | ShowToastActionType;
|
export type ToastActionType = HideToastActionType | ShowToastActionType;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
@ -53,10 +57,12 @@ function openFileInFolder(target: string): NoopActionType {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ShowToastActionCreatorType = (
|
export type ShowToastActionCreatorType = ReadonlyDeep<
|
||||||
toastType: ToastType,
|
(
|
||||||
parameters?: ReplacementValuesType
|
toastType: ToastType,
|
||||||
) => ShowToastActionType;
|
parameters?: ReplacementValuesType
|
||||||
|
) => ShowToastActionType
|
||||||
|
>;
|
||||||
|
|
||||||
export const showToast: ShowToastActionCreatorType = (
|
export const showToast: ShowToastActionCreatorType = (
|
||||||
toastType,
|
toastType,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import * as updateIpc from '../../shims/updateIpc';
|
import * as updateIpc from '../../shims/updateIpc';
|
||||||
import { DialogType } from '../../types/Dialogs';
|
import { DialogType } from '../../types/Dialogs';
|
||||||
import { DAY } from '../../util/durations';
|
import { DAY } from '../../util/durations';
|
||||||
|
@ -9,14 +10,14 @@ import type { StateType as RootStateType } from '../reducer';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type UpdatesStateType = {
|
export type UpdatesStateType = ReadonlyDeep<{
|
||||||
dialogType: DialogType;
|
dialogType: DialogType;
|
||||||
didSnooze: boolean;
|
didSnooze: boolean;
|
||||||
downloadSize?: number;
|
downloadSize?: number;
|
||||||
downloadedSize?: number;
|
downloadedSize?: number;
|
||||||
showEventsCount: number;
|
showEventsCount: number;
|
||||||
version?: string;
|
version?: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
|
@ -26,43 +27,44 @@ const SNOOZE_UPDATE = 'updates/SNOOZE_UPDATE';
|
||||||
const START_UPDATE = 'updates/START_UPDATE';
|
const START_UPDATE = 'updates/START_UPDATE';
|
||||||
const UNSNOOZE_UPDATE = 'updates/UNSNOOZE_UPDATE';
|
const UNSNOOZE_UPDATE = 'updates/UNSNOOZE_UPDATE';
|
||||||
|
|
||||||
export type UpdateDialogOptionsType = {
|
export type UpdateDialogOptionsType = ReadonlyDeep<{
|
||||||
downloadSize?: number;
|
downloadSize?: number;
|
||||||
downloadedSize?: number;
|
downloadedSize?: number;
|
||||||
version?: string;
|
version?: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type DismissDialogActionType = {
|
type DismissDialogActionType = ReadonlyDeep<{
|
||||||
type: typeof DISMISS_DIALOG;
|
type: typeof DISMISS_DIALOG;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type ShowUpdateDialogActionType = {
|
export type ShowUpdateDialogActionType = ReadonlyDeep<{
|
||||||
type: typeof SHOW_UPDATE_DIALOG;
|
type: typeof SHOW_UPDATE_DIALOG;
|
||||||
payload: {
|
payload: {
|
||||||
dialogType: DialogType;
|
dialogType: DialogType;
|
||||||
otherState: UpdateDialogOptionsType;
|
otherState: UpdateDialogOptionsType;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SnoozeUpdateActionType = {
|
type SnoozeUpdateActionType = ReadonlyDeep<{
|
||||||
type: typeof SNOOZE_UPDATE;
|
type: typeof SNOOZE_UPDATE;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type StartUpdateActionType = {
|
type StartUpdateActionType = ReadonlyDeep<{
|
||||||
type: typeof START_UPDATE;
|
type: typeof START_UPDATE;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type UnsnoozeUpdateActionType = {
|
type UnsnoozeUpdateActionType = ReadonlyDeep<{
|
||||||
type: typeof UNSNOOZE_UPDATE;
|
type: typeof UNSNOOZE_UPDATE;
|
||||||
payload: DialogType;
|
payload: DialogType;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type UpdatesActionType =
|
export type UpdatesActionType = ReadonlyDeep<
|
||||||
| DismissDialogActionType
|
| DismissDialogActionType
|
||||||
| ShowUpdateDialogActionType
|
| ShowUpdateDialogActionType
|
||||||
| SnoozeUpdateActionType
|
| SnoozeUpdateActionType
|
||||||
| StartUpdateActionType
|
| StartUpdateActionType
|
||||||
| UnsnoozeUpdateActionType;
|
| UnsnoozeUpdateActionType
|
||||||
|
>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2019 Signal Messenger, LLC
|
// Copyright 2019 Signal Messenger, LLC
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import { trigger } from '../../shims/events';
|
import { trigger } from '../../shims/events';
|
||||||
|
|
||||||
import type { LocaleMessagesType } from '../../types/I18N';
|
import type { LocaleMessagesType } from '../../types/I18N';
|
||||||
|
@ -13,7 +14,8 @@ import { ThemeType } from '../../types/Util';
|
||||||
|
|
||||||
// State
|
// State
|
||||||
|
|
||||||
export type UserStateType = {
|
// eslint-disable-next-line local-rules/type-alias-readonlydeep
|
||||||
|
export type UserStateType = Readonly<{
|
||||||
attachmentsPath: string;
|
attachmentsPath: string;
|
||||||
i18n: LocalizerType;
|
i18n: LocalizerType;
|
||||||
interactionMode: 'mouse' | 'keyboard';
|
interactionMode: 'mouse' | 'keyboard';
|
||||||
|
@ -33,11 +35,11 @@ export type UserStateType = {
|
||||||
tempPath: string;
|
tempPath: string;
|
||||||
theme: ThemeType;
|
theme: ThemeType;
|
||||||
version: string;
|
version: string;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
type UserChangedActionType = {
|
type UserChangedActionType = ReadonlyDeep<{
|
||||||
type: 'USER_CHANGED';
|
type: 'USER_CHANGED';
|
||||||
payload: {
|
payload: {
|
||||||
ourConversationId?: string;
|
ourConversationId?: string;
|
||||||
|
@ -52,9 +54,9 @@ type UserChangedActionType = {
|
||||||
isMainWindowFullScreen?: boolean;
|
isMainWindowFullScreen?: boolean;
|
||||||
menuOptions?: MenuOptionsType;
|
menuOptions?: MenuOptionsType;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
export type UserActionType = UserChangedActionType;
|
export type UserActionType = ReadonlyDeep<UserChangedActionType>;
|
||||||
|
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import type { ThunkAction } from 'redux-thunk';
|
import type { ThunkAction } from 'redux-thunk';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { UsernameReservationType } from '../../types/Username';
|
import type { UsernameReservationType } from '../../types/Username';
|
||||||
import { ReserveUsernameError } from '../../types/Username';
|
import { ReserveUsernameError } from '../../types/Username';
|
||||||
import * as usernameServices from '../../services/username';
|
import * as usernameServices from '../../services/username';
|
||||||
|
@ -27,14 +28,14 @@ import { showToast } from './toast';
|
||||||
import { ToastType } from '../../types/Toast';
|
import { ToastType } from '../../types/Toast';
|
||||||
import type { ToastActionType } from './toast';
|
import type { ToastActionType } from './toast';
|
||||||
|
|
||||||
export type UsernameReservationStateType = Readonly<{
|
export type UsernameReservationStateType = ReadonlyDeep<{
|
||||||
state: UsernameReservationState;
|
state: UsernameReservationState;
|
||||||
reservation?: UsernameReservationType;
|
reservation?: UsernameReservationType;
|
||||||
error?: UsernameReservationError;
|
error?: UsernameReservationError;
|
||||||
abortController?: AbortController;
|
abortController?: AbortController;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export type UsernameStateType = Readonly<{
|
export type UsernameStateType = ReadonlyDeep<{
|
||||||
// ProfileEditor
|
// ProfileEditor
|
||||||
editState: UsernameEditState;
|
editState: UsernameEditState;
|
||||||
|
|
||||||
|
@ -52,44 +53,51 @@ const RESERVE_USERNAME = 'username/RESERVE_USERNAME';
|
||||||
const CONFIRM_USERNAME = 'username/CONFIRM_USERNAME';
|
const CONFIRM_USERNAME = 'username/CONFIRM_USERNAME';
|
||||||
const DELETE_USERNAME = 'username/DELETE_USERNAME';
|
const DELETE_USERNAME = 'username/DELETE_USERNAME';
|
||||||
|
|
||||||
type SetUsernameEditStateActionType = {
|
type SetUsernameEditStateActionType = ReadonlyDeep<{
|
||||||
type: typeof SET_USERNAME_EDIT_STATE;
|
type: typeof SET_USERNAME_EDIT_STATE;
|
||||||
payload: {
|
payload: {
|
||||||
editState: UsernameEditState;
|
editState: UsernameEditState;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type OpenUsernameReservationModalActionType = {
|
type OpenUsernameReservationModalActionType = ReadonlyDeep<{
|
||||||
type: typeof OPEN_USERNAME_RESERVATION_MODAL;
|
type: typeof OPEN_USERNAME_RESERVATION_MODAL;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type CloseUsernameReservationModalActionType = {
|
type CloseUsernameReservationModalActionType = ReadonlyDeep<{
|
||||||
type: typeof CLOSE_USERNAME_RESERVATION_MODAL;
|
type: typeof CLOSE_USERNAME_RESERVATION_MODAL;
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type SetUsernameReservationErrorActionType = {
|
type SetUsernameReservationErrorActionType = ReadonlyDeep<{
|
||||||
type: typeof SET_USERNAME_RESERVATION_ERROR;
|
type: typeof SET_USERNAME_RESERVATION_ERROR;
|
||||||
payload: {
|
payload: {
|
||||||
error: UsernameReservationError | undefined;
|
error: UsernameReservationError | undefined;
|
||||||
};
|
};
|
||||||
};
|
}>;
|
||||||
|
|
||||||
type ReserveUsernameActionType = PromiseAction<
|
type ReserveUsernameActionType = ReadonlyDeep<
|
||||||
typeof RESERVE_USERNAME,
|
PromiseAction<
|
||||||
ReserveUsernameResultType | undefined,
|
typeof RESERVE_USERNAME,
|
||||||
{ abortController: AbortController }
|
ReserveUsernameResultType | undefined,
|
||||||
|
{ abortController: AbortController }
|
||||||
|
>
|
||||||
|
>;
|
||||||
|
type ConfirmUsernameActionType = ReadonlyDeep<
|
||||||
|
PromiseAction<typeof CONFIRM_USERNAME, void>
|
||||||
|
>;
|
||||||
|
type DeleteUsernameActionType = ReadonlyDeep<
|
||||||
|
PromiseAction<typeof DELETE_USERNAME, void>
|
||||||
>;
|
>;
|
||||||
type ConfirmUsernameActionType = PromiseAction<typeof CONFIRM_USERNAME, void>;
|
|
||||||
type DeleteUsernameActionType = PromiseAction<typeof DELETE_USERNAME, void>;
|
|
||||||
|
|
||||||
export type UsernameActionType =
|
export type UsernameActionType = ReadonlyDeep<
|
||||||
| SetUsernameEditStateActionType
|
| SetUsernameEditStateActionType
|
||||||
| OpenUsernameReservationModalActionType
|
| OpenUsernameReservationModalActionType
|
||||||
| CloseUsernameReservationModalActionType
|
| CloseUsernameReservationModalActionType
|
||||||
| SetUsernameReservationErrorActionType
|
| SetUsernameReservationErrorActionType
|
||||||
| ReserveUsernameActionType
|
| ReserveUsernameActionType
|
||||||
| ConfirmUsernameActionType
|
| ConfirmUsernameActionType
|
||||||
| DeleteUsernameActionType;
|
| DeleteUsernameActionType
|
||||||
|
>;
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
setUsernameEditState,
|
setUsernameEditState,
|
||||||
|
@ -133,7 +141,7 @@ export function setUsernameReservationError(
|
||||||
|
|
||||||
const INPUT_DELAY_MS = 500;
|
const INPUT_DELAY_MS = 500;
|
||||||
|
|
||||||
export type ReserveUsernameOptionsType = Readonly<{
|
export type ReserveUsernameOptionsType = ReadonlyDeep<{
|
||||||
doReserveUsername?: typeof usernameServices.reserveUsername;
|
doReserveUsername?: typeof usernameServices.reserveUsername;
|
||||||
delay?: number;
|
delay?: number;
|
||||||
}>;
|
}>;
|
||||||
|
@ -194,7 +202,7 @@ export function reserveUsername(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ConfirmUsernameOptionsType = Readonly<{
|
export type ConfirmUsernameOptionsType = ReadonlyDeep<{
|
||||||
doConfirmUsername?: typeof usernameServices.confirmUsername;
|
doConfirmUsername?: typeof usernameServices.confirmUsername;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
@ -221,7 +229,7 @@ export function confirmUsername({
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DeleteUsernameOptionsType = Readonly<{
|
export type DeleteUsernameOptionsType = ReadonlyDeep<{
|
||||||
doDeleteUsername?: typeof usernameServices.deleteUsername;
|
doDeleteUsername?: typeof usernameServices.deleteUsername;
|
||||||
|
|
||||||
// Only for testing
|
// Only for testing
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { MediaItemType } from '../../types/MediaItem';
|
import type { MediaItemType } from '../../types/MediaItem';
|
||||||
import type { StateType } from '../reducer';
|
import type { StateType } from '../reducer';
|
||||||
import type { LightboxStateType } from '../ducks/lightbox';
|
import type { LightboxStateType } from '../ducks/lightbox';
|
||||||
|
@ -36,6 +37,6 @@ export const getSelectedIndex = createSelector(
|
||||||
|
|
||||||
export const getMedia = createSelector(
|
export const getMedia = createSelector(
|
||||||
getLightboxState,
|
getLightboxState,
|
||||||
(state): ReadonlyArray<MediaItemType> =>
|
(state): ReadonlyArray<ReadonlyDeep<MediaItemType>> =>
|
||||||
state.isShowingLightbox ? state.media : []
|
state.isShowingLightbox ? state.media : []
|
||||||
);
|
);
|
||||||
|
|
|
@ -125,7 +125,7 @@ export const getRecentStickers = createSelector(
|
||||||
getStickersPath,
|
getStickersPath,
|
||||||
getTempPath,
|
getTempPath,
|
||||||
(
|
(
|
||||||
recents: Array<RecentStickerType>,
|
recents: ReadonlyArray<RecentStickerType>,
|
||||||
packs: Dictionary<StickerPackDBType>,
|
packs: Dictionary<StickerPackDBType>,
|
||||||
stickersPath: string,
|
stickersPath: string,
|
||||||
tempPath: string
|
tempPath: string
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { MediaGallery } from '../../components/conversation/media-gallery/MediaG
|
||||||
import { getMediaGalleryState } from '../selectors/mediaGallery';
|
import { getMediaGalleryState } from '../selectors/mediaGallery';
|
||||||
import { useConversationsActions } from '../ducks/conversations';
|
import { useConversationsActions } from '../ducks/conversations';
|
||||||
import { useLightboxActions } from '../ducks/lightbox';
|
import { useLightboxActions } from '../ducks/lightbox';
|
||||||
|
|
||||||
import { useMediaGalleryActions } from '../ducks/mediaGallery';
|
import { useMediaGalleryActions } from '../ducks/mediaGallery';
|
||||||
|
|
||||||
export type PropsType = {
|
export type PropsType = {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import type { GetConversationByIdType } from '../selectors/conversations';
|
import type { GetConversationByIdType } from '../selectors/conversations';
|
||||||
import type { LocalizerType } from '../../types/Util';
|
import type { LocalizerType } from '../../types/Util';
|
||||||
import type { MediaItemType } from '../../types/MediaItem';
|
import type { MediaItemType } from '../../types/MediaItem';
|
||||||
|
@ -33,7 +34,10 @@ export function SmartLightbox(): JSX.Element | null {
|
||||||
|
|
||||||
const isShowingLightbox = useSelector<StateType, boolean>(shouldShowLightbox);
|
const isShowingLightbox = useSelector<StateType, boolean>(shouldShowLightbox);
|
||||||
const isViewOnce = useSelector<StateType, boolean>(getIsViewOnce);
|
const isViewOnce = useSelector<StateType, boolean>(getIsViewOnce);
|
||||||
const media = useSelector<StateType, ReadonlyArray<MediaItemType>>(getMedia);
|
const media = useSelector<
|
||||||
|
StateType,
|
||||||
|
ReadonlyArray<ReadonlyDeep<MediaItemType>>
|
||||||
|
>(getMedia);
|
||||||
const selectedIndex = useSelector<StateType, number>(getSelectedIndex);
|
const selectedIndex = useSelector<StateType, number>(getSelectedIndex);
|
||||||
|
|
||||||
if (!isShowingLightbox) {
|
if (!isShowingLightbox) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import type { RefObject } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import { mapDispatchToProps } from '../actions';
|
import { mapDispatchToProps } from '../actions';
|
||||||
import type {
|
import type {
|
||||||
ContactSpoofingReviewPropType,
|
ContactSpoofingReviewPropType,
|
||||||
|
@ -103,7 +104,7 @@ function renderTypingBubble(id: string): JSX.Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
const getWarning = (
|
const getWarning = (
|
||||||
conversation: Readonly<ConversationType>,
|
conversation: ReadonlyDeep<ConversationType>,
|
||||||
state: Readonly<StateType>
|
state: Readonly<StateType>
|
||||||
): undefined | TimelineWarningType => {
|
): undefined | TimelineWarningType => {
|
||||||
switch (conversation.type) {
|
switch (conversation.type) {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
import { mapValues, pickBy } from 'lodash';
|
import { mapValues, pickBy } from 'lodash';
|
||||||
|
import type { ReadonlyDeep } from 'type-fest';
|
||||||
import { groupBy, map, filter } from './iterables';
|
import { groupBy, map, filter } from './iterables';
|
||||||
import { getOwn } from './getOwn';
|
import { getOwn } from './getOwn';
|
||||||
import type { ConversationType } from '../state/ducks/conversations';
|
import type { ConversationType } from '../state/ducks/conversations';
|
||||||
|
@ -51,8 +52,8 @@ export function getCollisionsFromMemberships(
|
||||||
* haven't dismissed.
|
* haven't dismissed.
|
||||||
*/
|
*/
|
||||||
export const hasUnacknowledgedCollisions = (
|
export const hasUnacknowledgedCollisions = (
|
||||||
previous: Readonly<GroupNameCollisionsWithIdsByTitle>,
|
previous: ReadonlyDeep<GroupNameCollisionsWithIdsByTitle>,
|
||||||
current: Readonly<GroupNameCollisionsWithIdsByTitle>
|
current: ReadonlyDeep<GroupNameCollisionsWithIdsByTitle>
|
||||||
): boolean =>
|
): boolean =>
|
||||||
Object.entries(current).some(([title, currentIds]) => {
|
Object.entries(current).some(([title, currentIds]) => {
|
||||||
const previousIds = new Set(getOwn(previous, title) || []);
|
const previousIds = new Set(getOwn(previous, title) || []);
|
||||||
|
@ -60,7 +61,7 @@ export const hasUnacknowledgedCollisions = (
|
||||||
});
|
});
|
||||||
|
|
||||||
export const invertIdsByTitle = (
|
export const invertIdsByTitle = (
|
||||||
idsByTitle: Readonly<GroupNameCollisionsWithIdsByTitle>
|
idsByTitle: ReadonlyDeep<GroupNameCollisionsWithIdsByTitle>
|
||||||
): GroupNameCollisionsWithTitlesById => {
|
): GroupNameCollisionsWithTitlesById => {
|
||||||
const result: GroupNameCollisionsWithTitlesById = Object.create(null);
|
const result: GroupNameCollisionsWithTitlesById = Object.create(null);
|
||||||
Object.entries(idsByTitle).forEach(([title, ids]) => {
|
Object.entries(idsByTitle).forEach(([title, ids]) => {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
"lib": [
|
"lib": [
|
||||||
"dom", // Required to access `window`
|
"dom", // Required to access `window`
|
||||||
"dom.iterable",
|
"dom.iterable",
|
||||||
"es2020"
|
"es2022"
|
||||||
],
|
],
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
// "allowJs": true, // Allow javascript files to be compiled.
|
// "allowJs": true, // Allow javascript files to be compiled.
|
||||||
|
|
|
@ -17726,6 +17726,11 @@ type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.5, type-detect@^4.0.8:
|
||||||
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
|
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
|
||||||
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
|
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
|
||||||
|
|
||||||
|
type-fest@3.5.0:
|
||||||
|
version "3.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-3.5.0.tgz#df7b2ef54ea775163c56d087b33e901ce9d657f7"
|
||||||
|
integrity sha512-bI3zRmZC8K0tUz1HjbIOAGQwR2CoPQG68N5IF7gm0LBl8QSNXzkmaWnkWccCUL5uG9mCsp4sBwC8SBrNSISWew==
|
||||||
|
|
||||||
type-fest@^0.13.1:
|
type-fest@^0.13.1:
|
||||||
version "0.13.1"
|
version "0.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user