Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5233fb8

Browse files
committed
chore: finish initial implementation of onSubscriptionAdd
1 parent 08fda7b commit 5233fb8

File tree

2 files changed

+66
-30
lines changed

2 files changed

+66
-30
lines changed

site/src/hooks/useTimeSync.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
*
44
* 1. Fill out all incomplete methods
55
* 2. Add tests
6-
* 3. See if there's a way to make sure that if you provide a type parameter to
7-
* the hook, you must also provide a select function
86
*/
97
import {
108
type FC,
@@ -308,7 +306,7 @@ export function useTimeSyncSelect<T = Date>(
308306
const subscribe = useCallback<ReactSubscriptionCallback>(
309307
(notifyReact) => {
310308
return timeSync.subscribe({
311-
targetRefreshInterval: targetRefreshInterval,
309+
targetRefreshInterval,
312310
id: hookId,
313311
onUpdate: notifyReact,
314312
select: selectForOutsideReact,

site/src/utils/TimeSync.ts

Lines changed: 65 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ export class TimeSync implements TimeSyncApi {
9898
#latestDateSnapshot: Date;
9999
#subscriptions: SubscriptionEntry[];
100100
#latestIntervalId: number | undefined;
101+
#currentRefreshInterval: number;
101102

102103
constructor(options: Partial<TimeSyncInitOptions>) {
103104
const {
@@ -116,45 +117,82 @@ export class TimeSync implements TimeSyncApi {
116117
this.#latestDateSnapshot = initialDatetime;
117118
this.#subscriptions = [];
118119
this.#latestIntervalId = undefined;
120+
this.#currentRefreshInterval = Number.POSITIVE_INFINITY;
119121
}
120122

121-
#reconcileRefreshIntervals(): void {
122-
if (this.#subscriptions.length === 0) {
123-
this.#clearInterval(this.#latestIntervalId);
124-
return;
123+
#onSubscriptionAdd(): void {
124+
if (this.#resyncOnNewSubscription) {
125+
this.#updateSnapshot();
125126
}
126127

127-
const prevFastestInterval =
128-
this.#subscriptions[0]?.targetRefreshInterval ?? Number.POSITIVE_INFINITY;
129-
if (this.#subscriptions.length > 1) {
130-
this.#subscriptions.sort(
131-
(e1, e2) => e1.targetRefreshInterval - e2.targetRefreshInterval,
132-
);
133-
}
128+
// Sort by refresh speed, descending
129+
this.#subscriptions.sort(
130+
(e1, e2) => e1.targetRefreshInterval - e2.targetRefreshInterval,
131+
);
134132

133+
const oldFastestInterval = this.#currentRefreshInterval;
135134
const newFastestInterval =
136135
this.#subscriptions[0]?.targetRefreshInterval ?? Number.POSITIVE_INFINITY;
137-
if (prevFastestInterval === newFastestInterval) {
136+
if (oldFastestInterval === newFastestInterval) {
138137
return;
139138
}
140-
if (newFastestInterval === Number.POSITIVE_INFINITY) {
141-
this.#clearInterval(this.#latestIntervalId);
139+
140+
this.#currentRefreshInterval = newFastestInterval;
141+
this.#clearInterval(this.#latestIntervalId);
142+
this.#latestIntervalId = undefined;
143+
if (this.#currentRefreshInterval === Number.POSITIVE_INFINITY) {
142144
return;
143145
}
144146

145-
/**
146-
* @todo Figure out the conditions when the interval should be set up,
147-
* and when/how it should be updated
148-
*/
149-
this.#latestIntervalId = this.#setInterval(() => {
150-
this.#latestDateSnapshot = this.#createNewDatetime(
151-
this.#latestDateSnapshot,
147+
const newTime = this.#createNewDatetime(this.#latestDateSnapshot);
148+
const elapsed =
149+
newTime.getMilliseconds() - this.#latestDateSnapshot.getMilliseconds();
150+
151+
const startNewIntervalFromScratch = () => {
152+
this.#latestIntervalId = this.#setInterval(
153+
() => this.#updateSnapshot(),
154+
this.#currentRefreshInterval,
152155
);
153-
this.#flushUpdateToSubscriptions();
154-
}, newFastestInterval);
156+
};
157+
158+
const unfulfilled = Math.max(0, this.#currentRefreshInterval - elapsed);
159+
if (unfulfilled === 0) {
160+
startNewIntervalFromScratch();
161+
return;
162+
}
163+
164+
// Feels a bit hokey to be setting a timeout via setInterval, but
165+
// didn't want to add even more data dependencies to the constructor
166+
// when setInterval can be used just fine in a pinch
167+
this.#latestIntervalId = this.#setInterval(() => {
168+
this.#clearInterval(this.#latestIntervalId);
169+
this.#latestIntervalId = undefined;
170+
startNewIntervalFromScratch();
171+
}, unfulfilled);
172+
}
173+
174+
/**
175+
* @todo This isn't done yet
176+
*/
177+
#onSubscriptionRemoval(): void {
178+
if (this.#subscriptions.length === 0) {
179+
this.#clearInterval(this.#latestIntervalId);
180+
this.#latestIntervalId = undefined;
181+
this.#currentRefreshInterval = Number.POSITIVE_INFINITY;
182+
return;
183+
}
184+
185+
const newFastestInterval =
186+
this.#subscriptions[0]?.targetRefreshInterval ?? Number.POSITIVE_INFINITY;
187+
if (newFastestInterval === this.#currentRefreshInterval) {
188+
return;
189+
}
155190
}
156191

157-
#flushUpdateToSubscriptions(): void {
192+
#updateSnapshot(): void {
193+
this.#latestDateSnapshot = this.#createNewDatetime(
194+
this.#latestDateSnapshot,
195+
);
158196
for (const subEntry of this.#subscriptions) {
159197
subEntry.onUpdate(this.#latestDateSnapshot);
160198
}
@@ -171,7 +209,7 @@ export class TimeSync implements TimeSyncApi {
171209
}
172210

173211
this.#subscriptions = updated;
174-
this.#reconcileRefreshIntervals();
212+
this.#onSubscriptionRemoval();
175213
}
176214

177215
subscribe(entry: SubscriptionEntry): void {
@@ -184,7 +222,7 @@ export class TimeSync implements TimeSyncApi {
184222
const subIndex = this.#subscriptions.findIndex((s) => s.id === entry.id);
185223
if (subIndex === -1) {
186224
this.#subscriptions.push(entry);
187-
this.#reconcileRefreshIntervals();
225+
this.#onSubscriptionAdd();
188226
return;
189227
}
190228

@@ -195,7 +233,7 @@ export class TimeSync implements TimeSyncApi {
195233

196234
this.#subscriptions[subIndex] = entry;
197235
if (prev.targetRefreshInterval !== entry.targetRefreshInterval) {
198-
this.#reconcileRefreshIntervals();
236+
this.#onSubscriptionAdd();
199237
}
200238
}
201239
}

0 commit comments

Comments
 (0)