UI 복잡 버전 234 RED→GREEN 완료(docs/UI_USECASES.md §A~§J): 라이브 테마 전환(DynamicResource 전환+ThemeResolver+HighContrast 테마, 재시작 없음), 디자인 토큰 체계·WCAG 대비 결함 5건 수정, 설정창 카테고리 내비/검색 재구성+AppConfig 40여 속성, 다운로드 관리자(속도/ETA/세그먼트맵/전체 일시정지-이어받기/CSV 내보내기/예약 게이트/중복 확인), 라이브러리·아카이브·작업공간·재생목록·즐겨찾기 편집 뷰, 접근성(자동화 속성 30여 개·커스텀 피어·docs/ACCESSIBILITY.md), 인터랙션(휠 클릭 새 탭·XButton 탐색·F12·영역 캡처·프로필 전환), 상태/알림(토스트·알림센터·온보딩·CrashReportDialog). 보강 테스트 35건+실창 E2E 4건(StaDispatcher 기반 — 프록시 설정이 기시작 핸들러를 건드리는 크래시 실결함 수정 포함) — 453/453 GREEN. 이전 미커밋 작업(CI 워크플로·Mdns·QueueHub·UpdateChecker·AGENTS/CLAUDE·빌드 스크립트) 일괄 포함
This commit is contained in:
parent
5a0ce730b2
commit
17f2f91152
88 changed files with 9463 additions and 1127 deletions
84
VideoDownloader.Core/Update/UpdateChecker.cs
Normal file
84
VideoDownloader.Core/Update/UpdateChecker.cs
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
using System.Text.Json;
|
||||
|
||||
namespace VideoDownloader.Core.Update;
|
||||
|
||||
/// <summary>GitHub 릴리스의 설치 자산 하나.</summary>
|
||||
public sealed record UpdateAsset(string Name, string DownloadUrl);
|
||||
|
||||
/// <summary>업데이트 확인 결과. LatestVersion 은 태그의 v 접두를 뗀 정규형.</summary>
|
||||
public sealed record UpdateCheckResult(bool IsNewer, string CurrentVersion, string LatestVersion, string ReleaseUrl, UpdateAsset? Asset);
|
||||
|
||||
/// <summary>
|
||||
/// DEPLOYMENT_PLAN §6 자동 업데이트 v1 — GitHub Releases latest 태그 폴링(무의존·전 OS 공통).
|
||||
/// 설치를 자동 적용하지 않고 릴리스/자산 URL 만 돌려준다(설치는 사람 관문).
|
||||
/// </summary>
|
||||
public sealed class UpdateChecker
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
|
||||
public UpdateChecker(HttpMessageHandler? handler = null)
|
||||
{
|
||||
_http = handler == null ? new HttpClient() : new HttpClient(handler);
|
||||
_http.DefaultRequestHeaders.UserAgent.ParseAdd("VideoDownloader-UpdateCheck"); // GitHub API 는 UA 필수
|
||||
_http.Timeout = TimeSpan.FromSeconds(15);
|
||||
}
|
||||
|
||||
/// <summary>"v1.2.3"/"1.2.3.0" 을 관대하게 비교. 어느 쪽이든 파싱 불가면 false(갱신 아님).</summary>
|
||||
public static bool IsNewer(string current, string latest) =>
|
||||
TryParse(current, out var cur) && TryParse(latest, out var lat) && lat > cur;
|
||||
|
||||
private static bool TryParse(string s, out Version version)
|
||||
{
|
||||
s = s.Trim().TrimStart('v', 'V');
|
||||
if (!s.Contains('.')) s += ".0"; // Version.TryParse 는 최소 2파트 요구
|
||||
return Version.TryParse(s, out version!);
|
||||
}
|
||||
|
||||
/// <summary>RID(win-x64 등)에 맞는 설치 자산 선택. "x64" 판정에서 arm64 를 먼저 배제한다.</summary>
|
||||
public static UpdateAsset? SelectAsset(IEnumerable<UpdateAsset> assets, string rid)
|
||||
{
|
||||
var parts = rid.Split('-');
|
||||
var os = parts[0];
|
||||
var arch = parts[^1];
|
||||
foreach (var asset in assets)
|
||||
{
|
||||
var name = asset.Name.ToLowerInvariant();
|
||||
var isArm = name.Contains("arm64");
|
||||
if (arch == "arm64" ? !isArm : isArm || !name.Contains(arch)) continue;
|
||||
var osMatch = os switch
|
||||
{
|
||||
"win" => name.EndsWith(".exe") || name.EndsWith(".msi"),
|
||||
"linux" => name.EndsWith(".tar.gz") || name.EndsWith(".appimage") || name.EndsWith(".deb"),
|
||||
"osx" => name.EndsWith(".dmg"),
|
||||
_ => false,
|
||||
};
|
||||
if (osMatch) return asset;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>repo("owner/repo")의 latest 릴리스를 조회한다. API 실패는 HttpRequestException 으로 드러난다.</summary>
|
||||
public async Task<UpdateCheckResult> CheckAsync(string repo, string currentVersion, string rid, CancellationToken ct = default)
|
||||
{
|
||||
using var res = await _http.GetAsync($"https://api.github.com/repos/{repo}/releases/latest", ct);
|
||||
res.EnsureSuccessStatusCode();
|
||||
using var doc = JsonDocument.Parse(await res.Content.ReadAsStringAsync(ct));
|
||||
var root = doc.RootElement;
|
||||
|
||||
var tag = root.GetProperty("tag_name").GetString() ?? "";
|
||||
var releaseUrl = root.TryGetProperty("html_url", out var h) ? h.GetString() ?? "" : "";
|
||||
var assets = new List<UpdateAsset>();
|
||||
if (root.TryGetProperty("assets", out var arr) && arr.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
foreach (var a in arr.EnumerateArray())
|
||||
{
|
||||
assets.Add(new UpdateAsset(
|
||||
a.GetProperty("name").GetString() ?? "",
|
||||
a.GetProperty("browser_download_url").GetString() ?? ""));
|
||||
}
|
||||
}
|
||||
|
||||
return new UpdateCheckResult(
|
||||
IsNewer(currentVersion, tag), currentVersion, tag.TrimStart('v', 'V'), releaseUrl, SelectAsset(assets, rid));
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue