53fb6e519aa166651d5c466d47f7424e395ba447

Author
TheEdgeOfRage <git@theedgeofrage.com>
Committer
TheEdgeOfRage <git@theedgeofrage.com>
Date

Message

Support hh:mm:ss format on video progress update

Diff

This diff is truncated to protect this page.

 1diff --git a/Makefile b/Makefile
 2index 695021b3ce8c3b978addd7df1ccd574a700f00d0..c884ebc6d89acab2f4b9f2ff448beed687cffcc6 100644
 3--- a/Makefile
 4+++ b/Makefile
 5@@ -12,6 +12,7 @@ bin/air: bin
 6 	GOBIN=$(PWD)/bin go install github.com/air-verse/air@v1.63.4
 7 
 8 lint: bin/golangci-lint
 9+	templ generate
10 	go mod tidy
11 	go vet ./...
12 	bin/golangci-lint -c .golangci.yml fmt ./...
13diff --git a/handler/videos.go b/handler/videos.go
14index c2cc79d117b7445d698608f71b834fd047705d3e..a6c2837c3b9362ca56bf76a4242872ff4cc6b639 100644
15--- a/handler/videos.go
16+++ b/handler/videos.go
17@@ -4,6 +4,7 @@ import (
18 	"context"
19 	"errors"
20 	"fmt"
21+	"strconv"
22 	"strings"
23 	"sync"
24 	"time"
25@@ -108,8 +109,49 @@ func (h *handler) MarkVideoAsUnwatched(ctx context.Context, videoID string) erro
26 	return h.db.SetVideoWatchTime(ctx, videoID, nil)
27 }
28 
29+// parseTimeProgress parses a duration string in  the Go duration format, hh:mm:ss, and mm:ss to a time.Duration
30+func parseTimeProgress(progressTime string) (time.Duration, error) {
31+	// Try Go duration format first
32+	duration, err := time.ParseDuration(progressTime)
33+	if err == nil {
34+		return duration, nil
35+	}
36+
37+	// Try hh:mm:ss or mm:ss format
38+	parts := strings.Split(progressTime, ":")
39+	if len(parts) == 2 {
40+		// mm:ss format
41+		minutes, err := strconv.Atoi(parts[0])
42+		if err != nil {
43+			return 0, fmt.Errorf("invalid mm:ss format")
44+		}
45+		seconds, err := strconv.Atoi(parts[1])
46+		if err != nil {
47+			return 0, fmt.Errorf("invalid mm:ss format")
48+		}
49+		return time.Duration(minutes)*time.Minute + time.Duration(seconds)*time.Second, nil
50+	} else if len(parts) == 3 {
51+		// hh:mm:ss format
52+		hours, err := strconv.Atoi(parts[0])
53+		if err != nil {
54+			return 0, fmt.Errorf("invalid hh:mm:ss format")
55+		}
56+		minutes, err := strconv.Atoi(parts[1])
57+		if err != nil {
58+			return 0, fmt.Errorf("invalid hh:mm:ss format")
59+		}
60+		seconds, err := strconv.Atoi(parts[2])
61+		if err != nil {
62+			return 0, fmt.Errorf("invalid hh:mm:ss format")
63+		}
64+		return time.Duration(hours)*time.Hour + time.Duration(minutes)*time.Minute + time.Duration(seconds)*time.Second, nil
65+	}
66+
67+	return 0, fmt.Errorf("unsupported time format: expected Go duration, hh:mm:ss, or mm:ss")
68+}
69+
70 func (h *handler) SetVideoProgress(ctx context.Context, videoID string, progressTime string) (*models.Video, error) {
71-	progress, err := time.ParseDuration(progressTime)
72+	progress, err := parseTimeProgress(progressTime)
73 	if err != nil {
74 		return nil, fmt.Errorf("%w: %v", ErrInvalidProgress, err.Error())
75 	}
76diff --git a/pages/new_videos.templ b/pages/new_videos.templ
77index 449d4441ffab247c843d31ec0e01f94de782dd99..80b0651998b085238b76aecda0905f76c6999edb 100644
78--- a/pages/new_videos.templ
79+++ b/pages/new_videos.templ
80@@ -83,7 +83,7 @@ templ videoCard(video models.Video) {
81 					hx-swap="outerHTML"
82 					class="d-flex"
83 				>
84-					<input type="text" name="progress" placeholder="1h2m3s" class="form-control" style="width: 50%"/>
85+					<input type="text" name="progress" placeholder="mm:ss/11m22s" class="form-control" style="width: 50%"/>
86 					<button type="submit" class="btn btn-primary ms-3"><i class="bi bi-clock"></i></button>
87 				</form>
88 				<button
89diff --git a/pages/new_videos_templ.go b/pages/new_videos_templ.go
90index c2aa7f3673d58f68959f8133047a2c852f315780..5a1701ede5fceb27054bcf260e26623856aa5403 100644
91--- a/pages/new_videos_templ.go
92+++ b/pages/new_videos_templ.go
93@@ -332,7 +332,7 @@ func videoCard(video models.Video) templ.Component {
94 		if templ_7745c5c3_Err != nil {
95 			return templ_7745c5c3_Err
96 		}