{"version":3,"file":"progress.cjs","names":["Emitter","useDispose","uname"],"sources":["../../../src/common/exec/progress.ts"],"sourcesContent":["// Inspired by https://developer.apple.com/documentation/foundation/progress\n\nimport { arrayRemoveElement } from '../data/array'\nimport { useDispose } from '../dispose-defer'\nimport { Emitter } from '../msg/emitter'\nimport { uname } from '../uuid'\n\nexport interface ProgressOptions {\n  totalUnits?: number\n  completeUnits?: number\n  resetWhenFinished?: boolean\n  name?: string\n}\n\n/**\n * Progress helper with these properties:\n *\n * - `totalUnits` and `completedUnits` for progress\n * - Can be cancelled\n * - Sends events on cancel, changed and dispose\n * - Supports children and propagates values.\n *   Total progress is sum of all units in the tree.\n * - On `dispose` child removes itself from parent.\n */\nexport class Progress extends Emitter<{\n  progressCancelled: (progress: Progress) => void\n  progressChanged: (progress: Progress) => void\n  progressDispose: (progress: Progress) => void\n}> {\n  private _totalUnits: number\n  private _completedUnits: number\n  private _isCancelled = false\n  private _resetWhenFinished = true\n  private _children: Progress[] = []\n\n  dispose = useDispose()\n  name: string\n\n  constructor(opt: ProgressOptions = {}) {\n    super()\n\n    this._totalUnits = opt.totalUnits ?? 0\n    this._completedUnits = opt.completeUnits ?? 0\n    this._resetWhenFinished = opt.resetWhenFinished ?? true\n    this.name = opt.name ?? uname('progress')\n\n    // Make sure to cleanup also children\n    this.dispose.add(async () => {\n      for (const child of this._children)\n        await child.dispose()\n      await this.emit('progressDispose', this)\n    })\n  }\n\n  /** Notify others about changes and reset on completion, if flag is set. */\n  private update() {\n    void this.emit('progressChanged', this)\n\n    if (this._isCancelled && this._resetWhenFinished) {\n      if (this.getTotalUnits() <= this.getCompletedUnits())\n        this.reset()\n    }\n  }\n\n  /** Fresh start */\n  reset() {\n    if (this._isCancelled) {\n      this._isCancelled = false\n      for (const child of this._children)\n        child.reset()\n      this.update()\n    }\n  }\n\n  /** Notify and mark as cancelled. May take some time before having an effect. */\n  async cancel() {\n    if (!this._isCancelled) {\n      this._isCancelled = true\n      await this.emit('progressCancelled', this)\n      for (const child of this._children)\n        await child.cancel()\n      this.update()\n    }\n  }\n\n  /** Add child progress, which count into its parents units. On `dispose` it will auto remove itself from parent. */\n  addChild(child: Progress) {\n    child.on('progressDispose', () => this.removeChild(child))\n    child.on('progressChanged', () => this.update())\n    if (!this._children.includes(child))\n      this._children.push(child)\n    this.update()\n  }\n\n  /** Create child progress.  */\n  createChildProgress(opt?: ProgressOptions) {\n    const progress = new Progress(opt)\n    this.addChild(progress)\n    return progress\n  }\n\n  removeChild(child: Progress) {\n    arrayRemoveElement(this._children, child)\n    this.update()\n  }\n\n  /** Total units including children */\n  getTotalUnits(): number {\n    if (this.isIndeterminate())\n      return 0\n    let units = this._totalUnits\n    for (const child of this._children)\n      units += child.getTotalUnits()\n    return units\n  }\n\n  /** Completed units including children */\n  getCompletedUnits(): number {\n    if (this.isIndeterminate())\n      return 0\n    let units = this._completedUnits\n    for (const child of this._children)\n      units += child.getCompletedUnits()\n    return units\n    //  return Math.min(this.getTotalUnits(), units)\n  }\n\n  /** Cannot calculate progress, because totalUnits are missing. Special representation in UI. */\n  isIndeterminate(): boolean {\n    return this._totalUnits <= 0 && this._children.length <= 0\n  }\n\n  isCancelled() {\n    return this._isCancelled\n  }\n\n  /** Either disposed or all units completed. */\n  isFinished() {\n    return this.dispose.isDisposed() || (!this.isIndeterminate() && (this.getTotalUnits() <= this.getCompletedUnits()))\n  }\n\n  /** Value from 0 to 1, where 1 is 100% completeness. */\n  getFraction() {\n    if (this.isIndeterminate())\n      return 0\n    let value = this.getCompletedUnits() / this.getTotalUnits()\n    if (Number.isNaN(value))\n      value = 0\n    return Math.min(1, Math.max(0, value))\n  }\n\n  getChildrenCount() {\n    return this._children.length\n  }\n\n  /** Change total units. */\n  setTotalUnits(units: number, completedUnits?: number) {\n    this._totalUnits = units\n    if (completedUnits != null)\n      this._completedUnits = completedUnits\n    this.update()\n  }\n\n  /** Relatively change total units. */\n  incTotalUnits(step = 1) {\n    this._totalUnits += step\n    this.update()\n  }\n\n  /** Set fixed number of completed units. */\n  setCompletetedUnits(units: number) {\n    this._completedUnits = units\n    this.update()\n  }\n\n  /** Set to 100% without disposing. */\n  setCompleted() {\n    this._completedUnits = this._totalUnits\n    this.update()\n  }\n\n  /** Dynamically change completed units. */\n  incCompletedUnits(step = 1) {\n    this._completedUnits += step\n    this.update()\n  }\n\n  /** Progress tree to string for debuggin purposes. Consider using `name` attribute of Progress. */\n  toString(indent = 0) {\n    let s = `${'  '.repeat(indent)}${this.name}: ${this._completedUnits} of ${this._totalUnits} units, ${Math.floor(this.getFraction() * 100)} %, cancel=${this._isCancelled}\\n`\n    for (const child of this._children)\n      s += child.toString(indent + 1)\n    if (indent === 0)\n      return s.trim()\n    return s\n  }\n}\n"],"mappings":"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"}