Skip to content

Commit f8d0904

Browse files
committed
fix(unfinished): store video metadata for single video item
1 parent b8b9d97 commit f8d0904

File tree

5 files changed

+156
-4
lines changed

5 files changed

+156
-4
lines changed

internal/app/update.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
119119
FormatID: msg.FormatID,
120120
IsAudioTab: msg.IsAudioTab,
121121
ABR: msg.ABR,
122-
Title: msg.SelectedVideo.Title(),
122+
Title: m.Download.SelectedVideo.Title(),
123+
Videos: []types.VideoItem{m.Download.SelectedVideo},
123124
Options: m.Search.DownloadOptions,
124125
CookiesFromBrowser: m.Search.CookiesFromBrowser,
125126
Cookies: m.Search.Cookies,
@@ -195,11 +196,21 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
195196
}
196197

197198
m.Download.SelectedVideo = types.VideoItem{VideoTitle: resumeTitle}
199+
if len(resumeVideos) > 0 {
200+
m.Download.SelectedVideo = resumeVideos[0]
201+
} else if resumeTitle != "" {
202+
m.Download.SelectedVideo = types.VideoItem{
203+
ID: msg.URL,
204+
VideoTitle: resumeTitle,
205+
}
206+
}
198207
req := types.DownloadRequest{
199208
URL: msg.URL,
200209
FormatID: resumeFormatID,
201210
IsAudioTab: false,
202211
ABR: 0,
212+
Title: m.Download.SelectedVideo.Title(),
213+
Videos: []types.VideoItem{m.Download.SelectedVideo},
203214
Options: m.Search.DownloadOptions,
204215
CookiesFromBrowser: m.Search.CookiesFromBrowser,
205216
Cookies: m.Search.Cookies,

internal/app/update_queue_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,3 +382,53 @@ func TestModelUpdateRetryCurrentQueueItemClearsError(t *testing.T) {
382382
t.Fatalf("m.Download.QueueError = %q, want empty", m.Download.QueueError)
383383
}
384384
}
385+
386+
func TestModelUpdateStartResumeDownloadUsesVideoInfoFromUnfinishedItem(t *testing.T) {
387+
m := newQueueTestModel(t)
388+
389+
updated, cmd := m.Update(types.StartResumeDownloadMsg{
390+
URL: "https://www.youtube.com/watch?v=abc123",
391+
FormatID: "best",
392+
Title: "Fallback Title",
393+
Videos: []types.VideoItem{
394+
{
395+
ID: "https://www.youtube.com/watch?v=abc123",
396+
VideoTitle: "Real Video Title",
397+
Channel: "Real Channel",
398+
Duration: 120,
399+
},
400+
},
401+
})
402+
m = updated.(*Model)
403+
404+
if cmd == nil {
405+
t.Fatalf("expected non-nil download command")
406+
}
407+
if m.Download.SelectedVideo.VideoTitle != "Real Video Title" {
408+
t.Fatalf("SelectedVideo.VideoTitle = %q, want %q", m.Download.SelectedVideo.VideoTitle, "Real Video Title")
409+
}
410+
if m.Download.SelectedVideo.Channel != "Real Channel" {
411+
t.Fatalf("SelectedVideo.Channel = %q, want %q", m.Download.SelectedVideo.Channel, "Real Channel")
412+
}
413+
}
414+
415+
func TestModelUpdateStartResumeDownloadFallbacksToTitleAndURL(t *testing.T) {
416+
m := newQueueTestModel(t)
417+
418+
updated, cmd := m.Update(types.StartResumeDownloadMsg{
419+
URL: "https://www.youtube.com/watch?v=xyz789",
420+
FormatID: "best",
421+
Title: "Stored Title",
422+
})
423+
m = updated.(*Model)
424+
425+
if cmd == nil {
426+
t.Fatalf("expected non-nil download command")
427+
}
428+
if m.Download.SelectedVideo.VideoTitle != "Stored Title" {
429+
t.Fatalf("SelectedVideo.VideoTitle = %q, want %q", m.Download.SelectedVideo.VideoTitle, "Stored Title")
430+
}
431+
if m.Download.SelectedVideo.ID != "https://www.youtube.com/watch?v=xyz789" {
432+
t.Fatalf("SelectedVideo.ID = %q, want URL", m.Download.SelectedVideo.ID)
433+
}
434+
}

internal/utils/download.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ import (
1919

2020
func StartDownload(dm *DownloadManager, program *tea.Program, req types.DownloadRequest) tea.Cmd {
2121
return tea.Cmd(func() tea.Msg {
22+
videos := req.Videos
23+
if len(videos) == 0 && req.Title != "" {
24+
videos = []types.VideoItem{{ID: req.URL, VideoTitle: req.Title}}
25+
}
26+
2227
key := req.UnfinishedKey
2328
if key == "" {
2429
key = req.URL
@@ -33,7 +38,7 @@ func StartDownload(dm *DownloadManager, program *tea.Program, req types.Download
3338
Title: title,
3439
Desc: req.UnfinishedDesc,
3540
URLs: req.URLs,
36-
Videos: req.Videos,
41+
Videos: videos,
3742
Timestamp: time.Now(),
3843
}
3944

internal/utils/download_integration_test.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,17 @@ func setupUnfinishedFilePath(t *testing.T) {
9696
})
9797
}
9898

99+
func setupDownloadConfigDir(t *testing.T) {
100+
t.Helper()
101+
102+
orig := config.GetConfigDir
103+
dir := filepath.Join(t.TempDir(), "config")
104+
config.GetConfigDir = func() string { return dir }
105+
t.Cleanup(func() {
106+
config.GetConfigDir = orig
107+
})
108+
}
109+
99110
func waitForManagerReady(t *testing.T, dm *DownloadManager) {
100111
t.Helper()
101112

@@ -284,3 +295,80 @@ func TestDoDownload_CancelSendsCancelled(t *testing.T) {
284295
t.Fatalf("expected cancellation error, got: %q", last.Err)
285296
}
286297
}
298+
299+
func TestStartDownload_PersistsSingleVideoInfoForResume(t *testing.T) {
300+
setupUnfinishedFilePath(t)
301+
setupDownloadConfigDir(t)
302+
303+
m, p := runCollectorProgram(t)
304+
_ = m
305+
dm := NewDownloadManager()
306+
307+
cmd := StartDownload(dm, p, types.DownloadRequest{
308+
URL: "https://www.youtube.com/watch?v=abc123",
309+
FormatID: "best",
310+
Title: "Saved Title",
311+
})
312+
if cmd == nil {
313+
t.Fatalf("expected non-nil start command")
314+
}
315+
316+
msg := cmd()
317+
if msg != nil {
318+
t.Fatalf("start command msg = %T, want nil", msg)
319+
}
320+
321+
entry := GetUnfinishedByURL("https://www.youtube.com/watch?v=abc123")
322+
if entry == nil {
323+
t.Fatalf("expected unfinished entry to exist")
324+
}
325+
if len(entry.Videos) != 1 {
326+
t.Fatalf("entry.Videos len = %d, want 1", len(entry.Videos))
327+
}
328+
if entry.Videos[0].ID != "https://www.youtube.com/watch?v=abc123" {
329+
t.Fatalf("entry.Videos[0].ID = %q, want URL", entry.Videos[0].ID)
330+
}
331+
if entry.Videos[0].VideoTitle != "Saved Title" {
332+
t.Fatalf("entry.Videos[0].VideoTitle = %q, want %q", entry.Videos[0].VideoTitle, "Saved Title")
333+
}
334+
}
335+
336+
func TestStartDownload_PersistsFullSingleVideoMetadata(t *testing.T) {
337+
setupUnfinishedFilePath(t)
338+
setupDownloadConfigDir(t)
339+
340+
_, p := runCollectorProgram(t)
341+
dm := NewDownloadManager()
342+
343+
video := types.VideoItem{
344+
ID: "https://www.youtube.com/watch?v=meta123",
345+
VideoTitle: "Meta Title",
346+
Desc: "Meta Description",
347+
Views: 12345,
348+
Duration: 321,
349+
Channel: "Meta Channel",
350+
}
351+
352+
cmd := StartDownload(dm, p, types.DownloadRequest{
353+
URL: video.ID,
354+
FormatID: "best",
355+
Title: video.Title(),
356+
Videos: []types.VideoItem{video},
357+
})
358+
if cmd == nil {
359+
t.Fatalf("expected non-nil start command")
360+
}
361+
_ = cmd()
362+
363+
entry := GetUnfinishedByURL(video.ID)
364+
if entry == nil {
365+
t.Fatalf("expected unfinished entry to exist")
366+
}
367+
if len(entry.Videos) != 1 {
368+
t.Fatalf("entry.Videos len = %d, want 1", len(entry.Videos))
369+
}
370+
got := entry.Videos[0]
371+
if got.Desc != "Meta Description" || got.Views != 12345 || got.Duration != 321 || got.Channel != "Meta Channel" {
372+
t.Fatalf("video metadata not preserved: %+v", got)
373+
}
374+
}

internal/utils/download_windows.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ package utils
55
import (
66
"log"
77

8-
"github.com/xdagiz/xytz/internal/types"
9-
108
tea "github.com/charmbracelet/bubbletea"
119
)
1210

0 commit comments

Comments
 (0)