const tickingStream = Stream.tick(Duration.seconds(1));
const interactionStream = Stream.async<number>((emit) => {
['mousemove', 'keydown', 'mousedown', 'touchstart'].forEach((event) => {
document.addEventListener(event, () => void emit(Effect.succeed(Chunk.of(Date.now()))), {
signal: abortController.signal,
});
});
});
const inactiveStream = Stream.fromEventListener(document, 'visibilitychange').pipe(
Stream.map(() => (document.visibilityState === 'visible' ? Option.none() : Option.some(Date.now()))),
);
yield* Stream.runForEach(tickingStream, () =>
Effect.gen(function* () {
// ... evaluate the last emitted events from both interactionStream and inactiveStream
// and close / open a latch if certain thresholds are exceeded
}),
).pipe(Effect.interruptible, Effect.forkScoped);
const tickingStream = Stream.tick(Duration.seconds(1));
const interactionStream = Stream.async<number>((emit) => {
['mousemove', 'keydown', 'mousedown', 'touchstart'].forEach((event) => {
document.addEventListener(event, () => void emit(Effect.succeed(Chunk.of(Date.now()))), {
signal: abortController.signal,
});
});
});
const inactiveStream = Stream.fromEventListener(document, 'visibilitychange').pipe(
Stream.map(() => (document.visibilityState === 'visible' ? Option.none() : Option.some(Date.now()))),
);
yield* Stream.runForEach(tickingStream, () =>
Effect.gen(function* () {
// ... evaluate the last emitted events from both interactionStream and inactiveStream
// and close / open a latch if certain thresholds are exceeded
}),
).pipe(Effect.interruptible, Effect.forkScoped);