Tauri v2 + SolidJS + SQLite + ffmpeg 사이드카로 구현한 크로스플랫폼 사진·영상 관리 앱. 로컬/NAS(SFTP·WebDAV·FTP) 소스, 가상 그리드, 인앱 재생, 태그/이동/삭제/undo, 중복 탐지, 포터블 배포. - archive-db: SQLite 스키마·마이그레이션·단일 writer 스레드 + FTS5 trigram - archive-vfs: VFS 4백엔드(local/sftp/ftp/webdav) + 자격증명(키체인/볼트) - archive-indexer: 스캔·해시·썸네일·중복탐지·태그·파일작업·유지보수 - archive-media: localhost HTTP 미디어 서버(Range) + ffmpeg 스트림 잡 - 프론트: 3-pane UI, justified 가상 그리드, 라이트박스, 중복 검토 패널 Rust 테스트 49개 통과. CI: win x64/arm64 포터블 zip + macOS universal dmg. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
54 lines
2.3 KiB
PowerShell
54 lines
2.3 KiB
PowerShell
# WebView2 CDP (Chrome DevTools Protocol) E2E helper.
|
|
# Usage: . .\scripts\cdp.ps1; Invoke-Cdp "document.title"
|
|
# Prereq: app launched with WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS=--remote-debugging-port=9223
|
|
# NOTE: ASCII only in this file (PS 5.1 reads BOM-less files as ANSI).
|
|
|
|
function Invoke-Cdp {
|
|
param(
|
|
[Parameter(Mandatory)] [string]$Expression,
|
|
[int]$Port = 9223,
|
|
[int]$TimeoutSec = 20
|
|
)
|
|
$targets = Invoke-RestMethod "http://127.0.0.1:$Port/json"
|
|
$page = $targets | Where-Object { $_.type -eq 'page' -and $_.url -notlike 'devtools*' } | Select-Object -First 1
|
|
if (-not $page) { throw "no CDP page target" }
|
|
|
|
$ws = New-Object System.Net.WebSockets.ClientWebSocket
|
|
$ct = [System.Threading.CancellationToken]::None
|
|
$uri = [Uri]$page.webSocketDebuggerUrl
|
|
$ws.ConnectAsync($uri, $ct).GetAwaiter().GetResult() | Out-Null
|
|
|
|
$msg = @{
|
|
id = 1
|
|
method = "Runtime.evaluate"
|
|
params = @{
|
|
expression = $Expression
|
|
returnByValue = $true
|
|
awaitPromise = $true
|
|
}
|
|
} | ConvertTo-Json -Depth 6 -Compress
|
|
$bytes = [System.Text.Encoding]::UTF8.GetBytes($msg)
|
|
$seg = New-Object System.ArraySegment[byte] -ArgumentList @(,$bytes)
|
|
$ws.SendAsync($seg, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $ct).GetAwaiter().GetResult() | Out-Null
|
|
|
|
$buffer = New-Object byte[] 1048576
|
|
$deadline = (Get-Date).AddSeconds($TimeoutSec)
|
|
$response = $null
|
|
while ((Get-Date) -lt $deadline) {
|
|
$sb = New-Object System.Text.StringBuilder
|
|
do {
|
|
$rseg = New-Object System.ArraySegment[byte] -ArgumentList @(,$buffer)
|
|
$result = $ws.ReceiveAsync($rseg, $ct).GetAwaiter().GetResult()
|
|
$sb.Append([System.Text.Encoding]::UTF8.GetString($buffer, 0, $result.Count)) | Out-Null
|
|
} while (-not $result.EndOfMessage)
|
|
$obj = $sb.ToString() | ConvertFrom-Json
|
|
if ($obj.id -eq 1) { $response = $obj; break }
|
|
}
|
|
$ws.Abort()
|
|
if (-not $response) { throw "CDP response timeout" }
|
|
if ($response.result.exceptionDetails) {
|
|
throw "JS exception: $($response.result.exceptionDetails.text) $($response.result.exceptionDetails.exception.description)"
|
|
}
|
|
return $response.result.result.value
|
|
}
|