igir
Version:
🕹 A zero-setup ROM collection manager that sorts, filters, extracts or archives, patches, and reports on collections of any size on any OS.
140 lines (139 loc) • 3.85 kB
JavaScript
import Timer from "../async/timer.js";
import { logger } from "./logger.js";
import SingleBar from "./singleBar.js";
import { LIVE_REGION_PADDING, terminal } from "./terminal.js";
class MultiBar {
static RENDER_MIN_FPS = 5;
static multiBars = [];
static exitHandlersRegistered = false;
singleBars = [];
renderTimer;
stopped = false;
constructor() {
}
/**
* Create a new {@link MultiBar} instance.
*/
static create() {
if (!this.exitHandlersRegistered) {
const exitHandler = () => {
this.stop();
};
process.once("exit", exitHandler);
process.once("SIGINT", exitHandler);
process.once("SIGTERM", exitHandler);
this.exitHandlersRegistered = true;
}
const multiBar = new MultiBar();
this.multiBars.push(multiBar);
return multiBar;
}
/**
* Returns true if there are any active MultiBars.
*/
static isActive() {
return this.multiBars.length > 0;
}
/**
* Add a new {@link SingleBar} to the {@link MultiBar}.
*/
addSingleBar(options, parentSingleBar) {
const singleBar = new SingleBar(this, options);
const parentSingleBarIndex = parentSingleBar ? this.singleBars.indexOf(parentSingleBar) : void 0;
const insertionIndex = parentSingleBarIndex === void 0 ? void 0 : this.singleBars.findIndex(
(singleBar2, idx) => idx > parentSingleBarIndex && singleBar2.getIndentSize() === 0
);
if (insertionIndex === void 0 || insertionIndex === -1) {
this.singleBars.push(singleBar);
} else {
this.singleBars.splice(insertionIndex, 0, singleBar);
}
if (singleBar.getIndentSize() === 0) {
this.clearAndRender();
}
return singleBar;
}
/**
* Log the {@link SingleBar}'s last output and remove it from the live region.
*/
freezeSingleBar(singleBar) {
const idx = this.singleBars.indexOf(singleBar);
if (idx === -1) {
return;
}
singleBar.format();
const lastOutput = singleBar.getLastOutput();
this.singleBars.splice(idx, 1);
if (lastOutput !== void 0) {
logger.printFrozenBar(
`${singleBar.getIndentSize() === 0 ? "\n" : ""}${LIVE_REGION_PADDING}${lastOutput}`
);
}
this.clearAndRender();
}
/**
* Remove a {@link SingleBar}.
*/
removeSingleBar(singleBar) {
const idx = this.singleBars.indexOf(singleBar);
if (idx === -1) {
return;
}
this.singleBars.splice(idx, 1);
}
/**
* Recompute the combined live-region frame and hand it to the {@link Terminal} to draw.
*/
clearAndRender() {
if (this.stopped) {
return;
}
this.renderTimer?.cancel();
if (terminal.isInteractive()) {
this.renderTimer = Timer.setTimeout(
() => {
this.clearAndRender();
},
Math.max(1e3 / MultiBar.RENDER_MIN_FPS, 1)
);
}
const rawOutput = this.singleBars.flatMap((singleBar) => {
const lines = singleBar.format().split("\n").filter((line) => line !== "");
if (singleBar.getIndentSize() === 0) {
return ["", ...lines];
}
return lines;
}).join("\n");
terminal.setLiveRegion(rawOutput);
}
/**
* Stop the {@link MultiBar} and all of its {@link SingleBar}s.
*/
static stop() {
let multiBar = this.multiBars.shift();
while (multiBar !== void 0) {
multiBar.stop();
multiBar = this.multiBars.shift();
}
}
/**
* Stop the {@link MultiBar} and all of its {@link SingleBar}s.
*/
stop() {
if (this.stopped) {
return;
}
this.clearAndRender();
const singleBarsCopy = [...this.singleBars];
for (const progressBar of singleBarsCopy) {
progressBar.freeze();
}
this.renderTimer?.cancel();
terminal.clearLiveRegion();
this.stopped = true;
}
}
export {
MultiBar as default
};
//# sourceMappingURL=multiBar.js.map