|
| 1 | +import * as colorette from 'colorette'; |
| 2 | + |
| 3 | +export interface ProgressBarOptions { |
| 4 | + width?: number; |
| 5 | + platform?: string; |
| 6 | + unicode?: boolean; |
| 7 | +} |
| 8 | + |
| 9 | +export const IS_SYMBOL_SUPPORTED = |
| 10 | + process.platform !== 'win32' || |
| 11 | + Boolean(process.env.CI) || |
| 12 | + process.env.TERM === 'xterm-256color'; |
| 13 | + |
| 14 | +function colorizePlatform(text: string, platform?: string): string { |
| 15 | + if (!platform) return colorette.green(text); |
| 16 | + const p = platform.toLowerCase(); |
| 17 | + if (p.includes('ios')) return colorette.blue(text); |
| 18 | + if (p.includes('android')) return colorette.green(text); |
| 19 | + return colorette.green(text); |
| 20 | +} |
| 21 | + |
| 22 | +export function renderProgressBar( |
| 23 | + percentage: number, |
| 24 | + { |
| 25 | + width = 16, |
| 26 | + platform, |
| 27 | + unicode = IS_SYMBOL_SUPPORTED, |
| 28 | + }: ProgressBarOptions = {} |
| 29 | +): string { |
| 30 | + const clamped = Math.max(0, Math.min(100, Math.round(percentage))); |
| 31 | + const filled = Math.round((clamped / 100) * width); |
| 32 | + const empty = Math.max(0, width - filled); |
| 33 | + |
| 34 | + const fullChar = unicode ? '=' : '#'; |
| 35 | + const emptyChar = unicode ? '-' : '.'; |
| 36 | + |
| 37 | + const filledStrColored = colorizePlatform(fullChar.repeat(filled), platform); |
| 38 | + const emptyStr = emptyChar.repeat(empty); |
| 39 | + |
| 40 | + return `[${filledStrColored}${emptyStr}]`; |
| 41 | +} |
| 42 | + |
| 43 | +export function colorizePlatformLabel(platform: string, label: string): string { |
| 44 | + const p = platform.toLowerCase(); |
| 45 | + if (p.includes('ios')) return colorette.blue(label); |
| 46 | + if (p.includes('android')) return colorette.green(label); |
| 47 | + return label; |
| 48 | +} |
| 49 | + |
| 50 | +export class Spinner { |
| 51 | + private index = 0; |
| 52 | + getNext(): string { |
| 53 | + const frames = IS_SYMBOL_SUPPORTED |
| 54 | + ? ['⠋', '⠙', '⠸', '⠴', '⠦', '⠇'] |
| 55 | + : ['-', '\\', '|', '/']; |
| 56 | + const frame = frames[this.index % frames.length]; |
| 57 | + this.index += 1; |
| 58 | + return frame; |
| 59 | + } |
| 60 | +} |
| 61 | + |
| 62 | +export function formatSecondsOneDecimal(ms: number): string { |
| 63 | + return `${(ms / 1000).toFixed(1)}s`; |
| 64 | +} |
| 65 | + |
| 66 | +export function formatElapsed(start: number, now: number): string { |
| 67 | + const ms = Math.max(0, now - start); |
| 68 | + if (ms < 1000) return `${(ms / 1000).toFixed(1)}s`; |
| 69 | + if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`; |
| 70 | + const minutes = Math.floor(ms / 60_000); |
| 71 | + const seconds = Math.floor((ms % 60_000) / 1000) |
| 72 | + .toString() |
| 73 | + .padStart(2, '0'); |
| 74 | + return `${minutes}:${seconds}`; |
| 75 | +} |
| 76 | + |
| 77 | +export function buildInProgressMessageParts( |
| 78 | + platform: string, |
| 79 | + percentage: number, |
| 80 | + options: { width?: number; maxPlatformNameWidth?: number } = {} |
| 81 | +): [string, string] { |
| 82 | + const { width = 16, maxPlatformNameWidth = platform.length } = options; |
| 83 | + const bar = renderProgressBar(percentage, { width, platform }); |
| 84 | + const percentText = `${Math.floor(percentage).toString().padStart(3, ' ')}%`; |
| 85 | + const barAndPercent = `${bar}${percentText}`; |
| 86 | + const platformPadded = platform.padEnd(maxPlatformNameWidth, ' '); |
| 87 | + const platformColored = colorizePlatformLabel(platform, platformPadded); |
| 88 | + return [barAndPercent, platformColored]; |
| 89 | +} |
| 90 | + |
| 91 | +export function buildDoneMessageParts( |
| 92 | + platform: string, |
| 93 | + timeMs: number, |
| 94 | + options: { maxPlatformNameWidth?: number } = {} |
| 95 | +): [string, string, string, string] { |
| 96 | + const { maxPlatformNameWidth = platform.length } = options; |
| 97 | + const platformPadded = platform.padEnd(maxPlatformNameWidth, ' '); |
| 98 | + const platformColored = colorizePlatformLabel(platform, platformPadded); |
| 99 | + const timeColored = colorizePlatformLabel( |
| 100 | + platform, |
| 101 | + formatSecondsOneDecimal(timeMs) |
| 102 | + ); |
| 103 | + return ['Compiled', platformColored, 'in', timeColored]; |
| 104 | +} |
0 commit comments