-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
/
art.ts
108 lines (85 loc) · 3.37 KB
/
art.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import { useSelector } from 'react-redux';
import { createSelector } from 'reselect';
import type { ArtImageData } from '../types.d';
import type { ArtPath, StateArtData, StateToastData } from '../slices/art';
import type { RootState } from '../store';
import { ArtType, MIN_STICKERS, MAX_STICKERS } from '../constants';
import { assert } from '../util/assert';
export const useTitle = (): string =>
useSelector(({ art }: RootState) => art.title);
export const useAuthor = (): string =>
useSelector(({ art }: RootState) => art.author);
export const useCover = (): ArtImageData | undefined =>
useSelector(({ art }: RootState) => art.cover);
export const useArtType = (): ArtType =>
useSelector(({ art }: RootState) => art.artType);
export const useArtOrder = (): ReadonlyArray<ArtPath> =>
useSelector(({ art }: RootState) => art.order);
export const useArtData = (src: ArtPath): StateArtData | undefined =>
useSelector(({ art }: RootState) => art.data[src]);
export const useArtReady = (): boolean =>
useSelector(({ art }: RootState) => {
assert(art.artType === ArtType.Sticker, 'Unexpected art type');
const min = MIN_STICKERS;
const max = MAX_STICKERS;
return (
art.order.length >= min &&
art.order.length <= max &&
Object.values(art.data).every(({ imageData }) => Boolean(imageData))
);
});
export const useEmojisReady = (): boolean =>
useSelector(({ art }: RootState) =>
Object.values(art.data).every(({ emoji }) => {
if (!emoji?.emoji) {
return false;
}
assert(art.artType === ArtType.Sticker, 'Unexpected art type');
return true;
})
);
export const useAllDataValid = (): boolean => {
const artReady = useArtReady();
const emojisReady = useEmojisReady();
const cover = useCover();
const title = useTitle();
const author = useAuthor();
return !!(artReady && emojisReady && cover && title && author);
};
const selectUrl = createSelector(
({ art }: RootState) => art.artType,
({ art }: RootState) => art.packId,
({ art }: RootState) => art.packKey,
(artType, id, key) => {
assert(artType === ArtType.Sticker, 'Unexpected art type');
return `https://signal.art/addstickers/#pack_id=${id}&pack_key=${key}`;
}
);
export const usePackUrl = (): string => useSelector(selectUrl);
export const useToasts = (): ReadonlyArray<StateToastData> =>
useSelector(({ art }: RootState) => art.toasts);
export const useAddMoreCount = (): number =>
useSelector(({ art }: RootState) => {
assert(art.artType === ArtType.Sticker, 'Unexpected art type');
const min = MIN_STICKERS;
return Math.min(Math.max(min - art.order.length, 0), min);
});
const selectOrderedData = createSelector(
({ art }: RootState) => art.order,
({ art }: RootState) => art.data,
(order, data) =>
order.map(id => data[id]).filter((x): x is StateArtData => x !== undefined)
);
export const useSelectOrderedData = (): ReadonlyArray<StateArtData> =>
useSelector(selectOrderedData);
const selectOrderedImagePaths = createSelector(
selectOrderedData,
(data: ReadonlyArray<StateArtData>): ReadonlyArray<ArtPath> =>
data
.map(({ imageData }) => imageData?.src)
.filter((src): src is ArtPath => src !== undefined)
);
export const useOrderedImagePaths = (): ReadonlyArray<ArtPath> =>
useSelector(selectOrderedImagePaths);