273 lines
11 KiB
PowerShell
273 lines
11 KiB
PowerShell
Add-Type -AssemblyName System.Drawing
|
|
Add-Type -AssemblyName System.Windows.Forms
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
$Root = Split-Path -Parent $PSScriptRoot
|
|
$OutDir = Join-Path $Root 'store-assets'
|
|
$IconPath = Join-Path $Root '1.0.3.2_mv3\icons\128.png'
|
|
|
|
if (-not (Test-Path $OutDir)) {
|
|
New-Item -ItemType Directory -Force -Path $OutDir | Out-Null
|
|
}
|
|
|
|
function Color-Hex($hex) {
|
|
return [System.Drawing.ColorTranslator]::FromHtml($hex)
|
|
}
|
|
|
|
function New-Font($size, $style = [System.Drawing.FontStyle]::Regular) {
|
|
return New-Object System.Drawing.Font('Segoe UI', $size, $style, [System.Drawing.GraphicsUnit]::Pixel)
|
|
}
|
|
|
|
function New-Canvas($width, $height) {
|
|
$bitmap = New-Object System.Drawing.Bitmap($width, $height, [System.Drawing.Imaging.PixelFormat]::Format24bppRgb)
|
|
$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
|
|
$graphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias
|
|
$graphics.TextRenderingHint = [System.Drawing.Text.TextRenderingHint]::ClearTypeGridFit
|
|
$graphics.Clear((Color-Hex '#f4f6fb'))
|
|
return [pscustomobject]@{ Bitmap = $bitmap; Graphics = $graphics }
|
|
}
|
|
|
|
function New-RoundRectPath($x, $y, $w, $h, $r) {
|
|
$path = New-Object System.Drawing.Drawing2D.GraphicsPath
|
|
$d = $r * 2
|
|
$path.AddArc($x, $y, $d, $d, 180, 90)
|
|
$path.AddArc($x + $w - $d, $y, $d, $d, 270, 90)
|
|
$path.AddArc($x + $w - $d, $y + $h - $d, $d, $d, 0, 90)
|
|
$path.AddArc($x, $y + $h - $d, $d, $d, 90, 90)
|
|
$path.CloseFigure()
|
|
return $path
|
|
}
|
|
|
|
function Fill-RoundRect($g, $x, $y, $w, $h, $r, $color) {
|
|
$brush = New-Object System.Drawing.SolidBrush($color)
|
|
$path = New-RoundRectPath $x $y $w $h $r
|
|
$g.FillPath($brush, $path)
|
|
$path.Dispose()
|
|
$brush.Dispose()
|
|
}
|
|
|
|
function Draw-RoundRect($g, $x, $y, $w, $h, $r, $color, $width = 1) {
|
|
$pen = New-Object System.Drawing.Pen($color, $width)
|
|
$path = New-RoundRectPath $x $y $w $h $r
|
|
$g.DrawPath($pen, $path)
|
|
$path.Dispose()
|
|
$pen.Dispose()
|
|
}
|
|
|
|
function Draw-Text($g, $text, $x, $y, $size, $colorHex, $style = [System.Drawing.FontStyle]::Regular, $maxWidth = 0, $maxHeight = 0) {
|
|
$font = New-Font $size $style
|
|
$brush = New-Object System.Drawing.SolidBrush((Color-Hex $colorHex))
|
|
if ($maxWidth -gt 0) {
|
|
$rect = New-Object System.Drawing.RectangleF($x, $y, $maxWidth, $(if ($maxHeight -gt 0) { $maxHeight } else { 1000 }))
|
|
$format = New-Object System.Drawing.StringFormat
|
|
$format.Trimming = [System.Drawing.StringTrimming]::EllipsisWord
|
|
$g.DrawString($text, $font, $brush, $rect, $format)
|
|
$format.Dispose()
|
|
} else {
|
|
$g.DrawString($text, $font, $brush, [float]$x, [float]$y)
|
|
}
|
|
$brush.Dispose()
|
|
$font.Dispose()
|
|
}
|
|
|
|
function Draw-CenteredText($g, $text, $x, $y, $w, $h, $size, $colorHex, $style = [System.Drawing.FontStyle]::Regular) {
|
|
$font = New-Font $size $style
|
|
$brush = New-Object System.Drawing.SolidBrush((Color-Hex $colorHex))
|
|
$rect = New-Object System.Drawing.RectangleF($x, $y, $w, $h)
|
|
$format = New-Object System.Drawing.StringFormat
|
|
$format.Alignment = [System.Drawing.StringAlignment]::Center
|
|
$format.LineAlignment = [System.Drawing.StringAlignment]::Center
|
|
$g.DrawString($text, $font, $brush, $rect, $format)
|
|
$format.Dispose()
|
|
$brush.Dispose()
|
|
$font.Dispose()
|
|
}
|
|
|
|
function Draw-Header($g, $subtitle) {
|
|
Fill-RoundRect $g 64 48 1152 88 18 (Color-Hex '#ffffff')
|
|
Draw-RoundRect $g 64 48 1152 88 18 (Color-Hex '#dfe3ec') 1
|
|
if (Test-Path $IconPath) {
|
|
$icon = [System.Drawing.Image]::FromFile($IconPath)
|
|
$g.DrawImage($icon, 88, 66, 48, 48)
|
|
$icon.Dispose()
|
|
}
|
|
Draw-Text $g 'YouTube Line' 152 63 28 '#151922' ([System.Drawing.FontStyle]::Bold)
|
|
Draw-Text $g $subtitle 152 98 17 '#667085'
|
|
}
|
|
|
|
function Draw-Browser($g, $x, $y, $w, $h, $url = 'youtube.com/watch') {
|
|
Fill-RoundRect $g $x $y $w $h 16 (Color-Hex '#ffffff')
|
|
Draw-RoundRect $g $x $y $w $h 16 (Color-Hex '#d6dce8') 1
|
|
Fill-RoundRect $g ($x + 1) ($y + 1) ($w - 2) 56 16 (Color-Hex '#f0f3f8')
|
|
$dotColors = @('#ef4444', '#f59e0b', '#22c55e')
|
|
for ($i = 0; $i -lt 3; $i++) {
|
|
$brush = New-Object System.Drawing.SolidBrush((Color-Hex $dotColors[$i]))
|
|
$g.FillEllipse($brush, $x + 24 + ($i * 24), $y + 22, 12, 12)
|
|
$brush.Dispose()
|
|
}
|
|
Fill-RoundRect $g ($x + 118) ($y + 14) ($w - 154) 30 14 (Color-Hex '#ffffff')
|
|
Draw-Text $g $url ($x + 140) ($y + 19) 14 '#667085'
|
|
}
|
|
|
|
function Draw-Player($g, $x, $y, $w, $h, $progress, $lineColor, $showControls = $false) {
|
|
Fill-RoundRect $g $x $y $w $h 10 (Color-Hex '#111827')
|
|
$sky = New-Object System.Drawing.Drawing2D.LinearGradientBrush(
|
|
(New-Object System.Drawing.Rectangle($x, $y, $w, $h)),
|
|
(Color-Hex '#172033'),
|
|
(Color-Hex '#05070c'),
|
|
90
|
|
)
|
|
$path = New-RoundRectPath $x $y $w $h 10
|
|
$g.FillPath($sky, $path)
|
|
$path.Dispose()
|
|
$sky.Dispose()
|
|
|
|
Fill-RoundRect $g ($x + 78) ($y + 82) ($w - 156) ($h - 188) 18 (Color-Hex '#1e293b')
|
|
Draw-CenteredText $g 'Video player' ($x + 78) ($y + 92) ($w - 156) 72 28 '#e5e7eb' ([System.Drawing.FontStyle]::Bold)
|
|
Draw-CenteredText $g 'Native controls hidden' ($x + 78) ($y + 145) ($w - 156) 38 17 '#9ca3af'
|
|
|
|
$barY = $y + $h - 18
|
|
Fill-RoundRect $g ($x + 24) $barY ($w - 48) 6 3 (Color-Hex '#9ca3af')
|
|
Fill-RoundRect $g ($x + 24) $barY ([int](($w - 48) * $progress)) 6 3 (Color-Hex $lineColor)
|
|
|
|
if ($showControls) {
|
|
Fill-RoundRect $g ($x + 30) ($y + $h - 74) ($w - 60) 44 10 (Color-Hex '#000000')
|
|
Draw-Text $g '0:42 / 4:15' ($x + 84) ($y + $h - 63) 17 '#ffffff'
|
|
Fill-RoundRect $g ($x + 44) ($y + $h - 58) 18 18 3 (Color-Hex '#ffffff')
|
|
}
|
|
}
|
|
|
|
function Draw-Badge($g, $x, $y, $text, $bgHex, $fgHex) {
|
|
$font = New-Font 16 ([System.Drawing.FontStyle]::Bold)
|
|
$size = $g.MeasureString($text, $font)
|
|
$w = [int]$size.Width + 34
|
|
$h = 34
|
|
Fill-RoundRect $g $x $y $w $h 17 (Color-Hex $bgHex)
|
|
Draw-CenteredText $g $text $x $y $w $h 16 $fgHex ([System.Drawing.FontStyle]::Bold)
|
|
$font.Dispose()
|
|
return $w
|
|
}
|
|
|
|
function Draw-OptionRow($g, $x, $y, $label, $valueHex) {
|
|
Draw-Text $g $label $x ($y + 8) 18 '#344054'
|
|
Fill-RoundRect $g ($x + 230) $y 112 40 8 (Color-Hex '#f9fafb')
|
|
Draw-RoundRect $g ($x + 230) $y 112 40 8 (Color-Hex '#d0d5dd') 1
|
|
Fill-RoundRect $g ($x + 244) ($y + 10) 20 20 4 (Color-Hex $valueHex)
|
|
Draw-Text $g $valueHex ($x + 274) ($y + 9) 15 '#344054'
|
|
}
|
|
|
|
function Save-Canvas($canvas, $path) {
|
|
$canvas.Bitmap.Save($path, [System.Drawing.Imaging.ImageFormat]::Png)
|
|
$canvas.Graphics.Dispose()
|
|
$canvas.Bitmap.Dispose()
|
|
}
|
|
|
|
function New-MainScreenshot {
|
|
$c = New-Canvas 1280 800
|
|
$g = $c.Graphics
|
|
Draw-Header $g 'A persistent progress line for the YouTube player'
|
|
Draw-Browser $g 96 170 1088 536
|
|
Draw-Player $g 140 252 790 394 0.43 '#ff2f2f' $false
|
|
Draw-Text $g 'Progress stays visible' 965 274 28 '#101828' ([System.Drawing.FontStyle]::Bold) 205 120
|
|
Draw-Text $g 'Keep track of video playback even when the native controls fade out.' 965 390 19 '#475467' ([System.Drawing.FontStyle]::Regular) 185 150
|
|
Draw-Badge $g 965 500 'Always on' '#fee4e2' '#b42318' | Out-Null
|
|
Draw-Badge $g 965 547 'Clean UI' '#e0f2fe' '#026aa2' | Out-Null
|
|
Draw-Badge $g 965 594 'YouTube only' '#ecfdf3' '#027a48' | Out-Null
|
|
Save-Canvas $c (Join-Path $OutDir 'youtube-line-screenshot-main-1280x800.png')
|
|
}
|
|
|
|
function New-OptionsScreenshot {
|
|
$c = New-Canvas 1280 800
|
|
$g = $c.Graphics
|
|
Draw-Header $g 'Customize the line color, progress color, and height'
|
|
Draw-Browser $g 96 170 1088 536 'chrome-extension://options'
|
|
Fill-RoundRect $g 165 244 420 376 18 (Color-Hex '#ffffff')
|
|
Draw-RoundRect $g 165 244 420 376 18 (Color-Hex '#d0d5dd') 1
|
|
Draw-Text $g 'YouTube Line Settings' 205 287 27 '#101828' ([System.Drawing.FontStyle]::Bold)
|
|
Draw-OptionRow $g 205 356 'Background color' '#808080'
|
|
Draw-OptionRow $g 205 424 'Progress color' '#ff0000'
|
|
Draw-Text $g 'Line height' 205 500 18 '#344054'
|
|
Fill-RoundRect $g 435 492 112 40 8 (Color-Hex '#f9fafb')
|
|
Draw-RoundRect $g 435 492 112 40 8 (Color-Hex '#d0d5dd') 1
|
|
Draw-CenteredText $g '2 px' 435 492 112 40 16 '#344054'
|
|
Fill-RoundRect $g 205 560 342 44 8 (Color-Hex '#ef4444')
|
|
Draw-CenteredText $g 'Save' 205 560 342 44 17 '#ffffff' ([System.Drawing.FontStyle]::Bold)
|
|
Draw-Player $g 650 272 445 282 0.62 '#ff0000' $false
|
|
Draw-Text $g 'Live preview' 650 582 22 '#101828' ([System.Drawing.FontStyle]::Bold)
|
|
Draw-Text $g 'Your settings are stored locally in Chrome.' 650 616 17 '#667085' ([System.Drawing.FontStyle]::Regular) 420
|
|
Save-Canvas $c (Join-Path $OutDir 'youtube-line-screenshot-options-1280x800.png')
|
|
}
|
|
|
|
function New-BeforeAfterScreenshot {
|
|
$c = New-Canvas 1280 800
|
|
$g = $c.Graphics
|
|
Draw-Header $g 'See playback progress without opening the controls'
|
|
Draw-Browser $g 96 170 1088 536
|
|
Draw-Text $g 'Without extension' 158 242 24 '#475467' ([System.Drawing.FontStyle]::Bold)
|
|
Draw-Text $g 'With YouTube Line' 676 242 24 '#101828' ([System.Drawing.FontStyle]::Bold)
|
|
Draw-Player $g 150 292 450 292 0.00 '#111827' $false
|
|
Fill-RoundRect $g 176 558 398 5 3 (Color-Hex '#111827')
|
|
Draw-CenteredText $g 'Progress is hidden with controls' 150 604 450 38 17 '#667085'
|
|
Draw-Player $g 668 292 450 292 0.47 '#ff2f2f' $false
|
|
Draw-CenteredText $g 'Progress remains visible' 668 604 450 38 17 '#667085'
|
|
$pen = New-Object System.Drawing.Pen((Color-Hex '#d0d5dd'), 2)
|
|
$g.DrawLine($pen, 640, 248, 640, 652)
|
|
$pen.Dispose()
|
|
Save-Canvas $c (Join-Path $OutDir 'youtube-line-screenshot-before-after-1280x800.png')
|
|
}
|
|
|
|
function New-SmallPromoTile {
|
|
$c = New-Canvas 440 280
|
|
$g = $c.Graphics
|
|
$g.Clear((Color-Hex '#111827'))
|
|
if (Test-Path $IconPath) {
|
|
$icon = [System.Drawing.Image]::FromFile($IconPath)
|
|
$g.DrawImage($icon, 28, 28, 56, 56)
|
|
$icon.Dispose()
|
|
}
|
|
Draw-Text $g 'YouTube Line' 104 30 30 '#ffffff' ([System.Drawing.FontStyle]::Bold)
|
|
Draw-Text $g 'Keep video progress visible' 104 70 17 '#cbd5e1'
|
|
Fill-RoundRect $g 28 168 384 8 4 (Color-Hex '#94a3b8')
|
|
Fill-RoundRect $g 28 168 224 8 4 (Color-Hex '#ff3030')
|
|
Fill-RoundRect $g 28 202 180 36 18 (Color-Hex '#fee4e2')
|
|
Draw-CenteredText $g 'Always visible' 28 202 180 36 16 '#b42318' ([System.Drawing.FontStyle]::Bold)
|
|
Save-Canvas $c (Join-Path $OutDir 'youtube-line-promo-small-440x280.png')
|
|
}
|
|
|
|
function New-MarqueePromoTile {
|
|
$c = New-Canvas 1400 560
|
|
$g = $c.Graphics
|
|
$g.Clear((Color-Hex '#101828'))
|
|
|
|
if (Test-Path $IconPath) {
|
|
$icon = [System.Drawing.Image]::FromFile($IconPath)
|
|
$g.DrawImage($icon, 90, 88, 96, 96)
|
|
$icon.Dispose()
|
|
}
|
|
|
|
Draw-Text $g 'YouTube Line' 220 84 56 '#ffffff' ([System.Drawing.FontStyle]::Bold)
|
|
Draw-Text $g 'Keep video progress visible when YouTube controls fade out.' 224 154 27 '#cbd5e1' ([System.Drawing.FontStyle]::Regular) 570
|
|
|
|
Draw-Badge $g 224 240 'Always visible' '#fee4e2' '#b42318' | Out-Null
|
|
Draw-Badge $g 420 240 'Customizable' '#e0f2fe' '#026aa2' | Out-Null
|
|
Draw-Badge $g 618 240 'YouTube only' '#ecfdf3' '#027a48' | Out-Null
|
|
|
|
Fill-RoundRect $g 90 390 610 10 5 (Color-Hex '#94a3b8')
|
|
Fill-RoundRect $g 90 390 356 10 5 (Color-Hex '#ff3030')
|
|
|
|
Draw-Browser $g 820 78 470 340
|
|
Draw-Player $g 850 158 410 230 0.57 '#ff3030' $false
|
|
Fill-RoundRect $g 850 450 410 44 22 (Color-Hex '#ffffff')
|
|
Draw-CenteredText $g 'Progress line stays visible' 850 450 410 44 20 '#101828' ([System.Drawing.FontStyle]::Bold)
|
|
|
|
Save-Canvas $c (Join-Path $OutDir 'youtube-line-promo-marquee-1400x560.png')
|
|
}
|
|
|
|
New-MainScreenshot
|
|
New-OptionsScreenshot
|
|
New-BeforeAfterScreenshot
|
|
New-SmallPromoTile
|
|
New-MarqueePromoTile
|
|
|
|
Get-ChildItem -LiteralPath $OutDir -Filter '*.png' | Sort-Object Name | Select-Object FullName, Length
|