/
ViewDescriptorsSet.ts
112 lines (96 loc) · 2.87 KB
/
ViewDescriptorsSet.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
109
110
111
112
import { useRef } from 'react';
import { makeMutable } from './core';
import { SharedValue } from './commonTypes';
import { Descriptor } from './hook/commonTypes';
import { Platform } from 'react-native';
export interface ViewRefSet<T> {
items: Set<T>;
add: (item: T) => void;
remove: (item: T) => void;
}
export interface ViewDescriptorsSet {
batchToRemove: Set<number>;
tags: Set<number>;
waitForInsertSync: boolean;
waitForRemoveSync: boolean;
sharableViewDescriptors: SharedValue<Descriptor[]>;
items: Descriptor[];
add: (item: Descriptor) => void;
remove: (viewTag: number) => void;
rebuildsharableViewDescriptors: (
sharableViewDescriptor: SharedValue<Descriptor[]>
) => void;
}
const scheduleUpdates =
Platform.OS === 'web' ? requestAnimationFrame : setImmediate;
export function makeViewDescriptorsSet(): ViewDescriptorsSet {
const ref = useRef<ViewDescriptorsSet | null>(null);
if (ref.current === null) {
const data: ViewDescriptorsSet = {
batchToRemove: new Set(),
tags: new Set(),
waitForInsertSync: false,
waitForRemoveSync: false,
sharableViewDescriptors: makeMutable([]),
items: [],
add: (item: Descriptor) => {
if (data.tags.has(item.tag)) {
return;
}
data.tags.add(item.tag);
data.items.push(item);
if (!data.waitForInsertSync) {
data.waitForInsertSync = true;
scheduleUpdates(() => {
data.sharableViewDescriptors.value = data.items;
data.waitForInsertSync = false;
});
}
},
remove: (viewTag: number) => {
data.batchToRemove.add(viewTag);
if (!data.waitForRemoveSync) {
data.waitForRemoveSync = true;
scheduleUpdates(() => {
const items = [];
for (const item of data.items) {
if (data.batchToRemove.has(item.tag)) {
data.tags.delete(item.tag);
} else {
items.push(item);
}
}
data.items = items;
data.sharableViewDescriptors.value = items;
data.batchToRemove = new Set();
data.waitForRemoveSync = false;
});
}
},
rebuildsharableViewDescriptors: (
sharableViewDescriptors: SharedValue<Descriptor[]>
) => {
data.sharableViewDescriptors = sharableViewDescriptors;
},
};
ref.current = data;
}
return ref.current;
}
export function makeViewsRefSet<T>(): ViewRefSet<T> {
const ref = useRef<ViewRefSet<T> | null>(null);
if (ref.current === null) {
const data: ViewRefSet<T> = {
items: new Set(),
add: (item: T) => {
if (data.items.has(item)) return;
data.items.add(item);
},
remove: (item: T) => {
data.items.delete(item);
},
};
ref.current = data;
}
return ref.current;
}