Files
flipper/desktop/app/src/utils/Idler.tsx
Michel Weststrate 34c915a739 Add support for async / custom plugin export
Summary:
Sandy plugins can now set up an `onExport` handler to enable customizing the export format of a plugin: `client.onExport(callback: (idler, onStatusMessage) => Promise<state>)`

Import will be done in next diff

Reviewed By: nikoant

Differential Revision: D26124440

fbshipit-source-id: c787c79d929aa8fb484f15a9340d7c87545793cb
2021-02-01 11:43:29 -08:00

125 lines
2.5 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {CancelledPromiseError} from './errors';
import {sleep} from './promiseTimeout';
import {Idler} from 'flipper-plugin';
export class IdlerImpl implements Idler {
private lastIdle = performance.now();
private kill = false;
constructor(private interval = 16) {}
shouldIdle(): boolean {
return this.kill || performance.now() - this.lastIdle > this.interval;
}
async idle(): Promise<void> {
if (this.kill) {
throw new CancelledPromiseError('Idler got killed');
}
const now = performance.now();
if (now - this.lastIdle > this.interval) {
this.lastIdle = now;
return new Promise((resolve) => {
if (typeof requestIdleCallback !== 'undefined') {
requestIdleCallback(() => {
resolve();
});
} else {
setTimeout(resolve, 0);
}
});
}
return undefined;
}
cancel() {
this.kill = true;
}
isCancelled() {
return this.kill;
}
}
// This smills like we should be using generators :)
export class TestIdler implements Idler {
private resolver?: () => void;
private kill = false;
private autoRun = false;
private hasProgressed = false;
constructor(autorun = false) {
this.autoRun = autorun;
}
shouldIdle() {
if (this.kill) {
return true;
}
if (this.autoRun) {
return false;
}
// In turns we signal that idling is needed and that it isn't
if (!this.hasProgressed) {
this.hasProgressed = true;
return false;
}
return true;
}
async idle() {
if (this.kill) {
throw new CancelledPromiseError('Idler got killed');
}
if (this.autoRun) {
return undefined;
}
if (this.resolver) {
throw new Error('Already idling');
}
return new Promise<void>((resolve) => {
this.resolver = () => {
this.resolver = undefined;
this.hasProgressed = false;
resolve();
};
});
}
cancel() {
this.kill = true;
this.run();
}
async next() {
if (!this.resolver) {
throw new Error('Not yet idled');
}
this.resolver();
// make sure waiting promise runs first
await sleep(10);
}
/**
* Automatically progresses through all idle calls
*/
run() {
this.resolver?.();
this.autoRun = true;
}
isCancelled() {
return this.kill;
}
}