M0: remote access server - Kestrel embedded (token auth/pair/queue API/library/range streaming/web companion zero-install), QR pairing window, DownloadQueueAdapter, auto-start+palette commands. Server E2E green (102 tests)
This commit is contained in:
parent
40c1b39b70
commit
bb569acd96
15 changed files with 734 additions and 0 deletions
67
VideoDownloader.App/Services/DownloadQueueAdapter.cs
Normal file
67
VideoDownloader.App/Services/DownloadQueueAdapter.cs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
using System.Windows.Threading;
|
||||
using VideoDownloader.App.ViewModels;
|
||||
using VideoDownloader.Server;
|
||||
using VideoDownloader.Core.Detection;
|
||||
|
||||
namespace VideoDownloader.App.Services;
|
||||
|
||||
/// <summary>
|
||||
/// DownloadManager(UI 컬렉션) ↔ 서버 큐 API 브릿지. 모든 접근을 UI 디스패처로 마샬링.
|
||||
/// </summary>
|
||||
public sealed class DownloadQueueAdapter : IQueueAdapter
|
||||
{
|
||||
private readonly Core.DownloadManager _manager;
|
||||
private readonly Dispatcher _dispatcher;
|
||||
|
||||
public DownloadQueueAdapter(Core.DownloadManager manager, Dispatcher dispatcher)
|
||||
{
|
||||
_manager = manager;
|
||||
_dispatcher = dispatcher;
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<QueueItemDto>> GetItemsAsync() => _dispatcher.InvokeAsync(() =>
|
||||
(IReadOnlyList<QueueItemDto>)_manager.Items.Select(Map).ToList()).Task;
|
||||
|
||||
public Task<string> AddAsync(string url, string? title)
|
||||
{
|
||||
// 서버에서 온 URL → 감지 파이프라인으로(소셜/HLS/DASH 자동 분류)
|
||||
return _dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
if (Uri.TryCreate(url, UriKind.Absolute, out var uri) &&
|
||||
SocialSiteDetector.TryMatch(uri, out var normalized, out var label))
|
||||
{
|
||||
_manager.OnDetected(new DetectionContext(normalized, normalized, MediaKind.Social, Tag: label));
|
||||
return normalized;
|
||||
}
|
||||
var kind = MediaDetector.Classify(url, "", -1, _manager.Config) ?? MediaKind.Direct;
|
||||
_manager.OnDetected(new DetectionContext(url, url, kind, ""));
|
||||
return url;
|
||||
}).Task;
|
||||
}
|
||||
|
||||
public Task PauseAsync(string id) => _dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
var item = Find(id);
|
||||
if (item != null) _manager.Cancel(item); // v1: 제어 매핑 — 진행 항목 취소
|
||||
}).Task;
|
||||
|
||||
public Task ResumeAsync(string id) => _dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
var item = Find(id);
|
||||
if (item != null) _ = _manager.RetryDownload(item);
|
||||
}).Task;
|
||||
|
||||
public Task CancelAsync(string id) => _dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
var item = Find(id);
|
||||
if (item != null) _manager.Cancel(item);
|
||||
}).Task;
|
||||
|
||||
public event Action? Changed { add { } remove { } }
|
||||
|
||||
private DownloadItemViewModel? Find(string id) =>
|
||||
_manager.Items.FirstOrDefault(i => i.Id == id);
|
||||
|
||||
private static QueueItemDto Map(DownloadItemViewModel i) =>
|
||||
new(i.Id, i.Title, i.Url ?? "", i.Status ?? "", i.Progress);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue