summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-17 14:59:07 +0300
committerPaul Buetow <paul@buetow.org>2026-05-17 14:59:07 +0300
commit3d2009bff0edddb413819ea542678738fb63cc0c (patch)
tree53a8679920b0a3b1bc7598979c67492b51ea5fe6 /internal
parentdd3a961436868c32585b201b2da2dd5be23d609c (diff)
Add finished flag to playback progress
Diffstat (limited to 'internal')
-rw-r--r--internal/model/media.go1
-rw-r--r--internal/model/media_test.go2
-rw-r--r--internal/repository/playback_progress.go12
-rw-r--r--internal/repository/schema.go1
-rw-r--r--internal/repository/sqlite_test.go8
5 files changed, 16 insertions, 8 deletions
diff --git a/internal/model/media.go b/internal/model/media.go
index 48ab487..39ae4fd 100644
--- a/internal/model/media.go
+++ b/internal/model/media.go
@@ -121,6 +121,7 @@ type PlaybackProgress struct {
UserID int64 `json:"user_id"`
MediaID int64 `json:"media_id"`
PositionSeconds float64 `json:"position_seconds"`
+ Finished bool `json:"finished"`
UpdatedAt time.Time `json:"updated_at"`
}
diff --git a/internal/model/media_test.go b/internal/model/media_test.go
index 49d877c..1692698 100644
--- a/internal/model/media_test.go
+++ b/internal/model/media_test.go
@@ -15,7 +15,7 @@ func TestStructsInstantiate(t *testing.T) {
max := 1
_ = Share{Token: "t", MediaID: 1, CreatedBy: 1, CreatedAt: now, ExpiresAt: now, MaxUses: &max}
_ = Note{ID: 1, MediaID: 1, UserID: 1, Content: "c", CreatedAt: now, UpdatedAt: now}
- _ = PlaybackProgress{UserID: 1, MediaID: 1, PositionSeconds: 1, UpdatedAt: now}
+ _ = PlaybackProgress{UserID: 1, MediaID: 1, PositionSeconds: 1, Finished: true, UpdatedAt: now}
_ = PlaybackAccumulator{SessionID: "s", MediaID: 1, UpdatedAt: now}
_ = Favorite{UserID: 1, MediaID: 1, CreatedAt: now}
_ = MediaTag{MediaID: 1, TagID: 1}
diff --git a/internal/repository/playback_progress.go b/internal/repository/playback_progress.go
index e628388..046598a 100644
--- a/internal/repository/playback_progress.go
+++ b/internal/repository/playback_progress.go
@@ -11,8 +11,8 @@ import (
// UpsertProgress inserts or replaces playback progress.
func (s *SQLite) UpsertProgress(ctx context.Context, progress *model.PlaybackProgress) error {
_, err := s.db.ExecContext(ctx,
- `INSERT OR REPLACE INTO playback_progress (user_id, media_id, position_seconds, updated_at) VALUES (?, ?, ?, ?)`,
- progress.UserID, progress.MediaID, progress.PositionSeconds, progress.UpdatedAt,
+ `INSERT OR REPLACE INTO playback_progress (user_id, media_id, position_seconds, finished, updated_at) VALUES (?, ?, ?, ?, ?)`,
+ progress.UserID, progress.MediaID, progress.PositionSeconds, progress.Finished, progress.UpdatedAt,
)
if err != nil {
return fmt.Errorf("upsert progress: %w", err)
@@ -23,11 +23,11 @@ func (s *SQLite) UpsertProgress(ctx context.Context, progress *model.PlaybackPro
// GetProgress retrieves playback progress for a user and media.
func (s *SQLite) GetProgress(ctx context.Context, userID, mediaID int64) (*model.PlaybackProgress, error) {
row := s.db.QueryRowContext(ctx,
- `SELECT user_id, media_id, position_seconds, updated_at FROM playback_progress WHERE user_id = ? AND media_id = ?`,
+ `SELECT user_id, media_id, position_seconds, finished, updated_at FROM playback_progress WHERE user_id = ? AND media_id = ?`,
userID, mediaID,
)
var p model.PlaybackProgress
- if err := row.Scan(&p.UserID, &p.MediaID, &p.PositionSeconds, &p.UpdatedAt); err == sql.ErrNoRows {
+ if err := row.Scan(&p.UserID, &p.MediaID, &p.PositionSeconds, &p.Finished, &p.UpdatedAt); err == sql.ErrNoRows {
return nil, nil
} else if err != nil {
return nil, err
@@ -38,7 +38,7 @@ func (s *SQLite) GetProgress(ctx context.Context, userID, mediaID int64) (*model
// ListProgressByUser returns all progress records for a user.
func (s *SQLite) ListProgressByUser(ctx context.Context, userID int64) ([]model.PlaybackProgress, error) {
rows, err := s.db.QueryContext(ctx,
- `SELECT user_id, media_id, position_seconds, updated_at FROM playback_progress WHERE user_id = ? ORDER BY updated_at DESC`, userID)
+ `SELECT user_id, media_id, position_seconds, finished, updated_at FROM playback_progress WHERE user_id = ? ORDER BY updated_at DESC`, userID)
if err != nil {
return nil, fmt.Errorf("list progress: %w", err)
}
@@ -46,7 +46,7 @@ func (s *SQLite) ListProgressByUser(ctx context.Context, userID int64) ([]model.
var pp []model.PlaybackProgress
for rows.Next() {
var p model.PlaybackProgress
- if err := rows.Scan(&p.UserID, &p.MediaID, &p.PositionSeconds, &p.UpdatedAt); err != nil {
+ if err := rows.Scan(&p.UserID, &p.MediaID, &p.PositionSeconds, &p.Finished, &p.UpdatedAt); err != nil {
return nil, err
}
pp = append(pp, p)
diff --git a/internal/repository/schema.go b/internal/repository/schema.go
index a07f4ed..a49dbb7 100644
--- a/internal/repository/schema.go
+++ b/internal/repository/schema.go
@@ -83,6 +83,7 @@ CREATE TABLE IF NOT EXISTS playback_progress (
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
media_id INTEGER NOT NULL REFERENCES media(id) ON DELETE CASCADE,
position_seconds REAL NOT NULL,
+ finished BOOLEAN NOT NULL DEFAULT 0,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (user_id, media_id)
);
diff --git a/internal/repository/sqlite_test.go b/internal/repository/sqlite_test.go
index a295fa4..bbe1330 100644
--- a/internal/repository/sqlite_test.go
+++ b/internal/repository/sqlite_test.go
@@ -464,7 +464,7 @@ func TestSQLite_PlaybackProgressRepo(t *testing.T) {
uid, _ := s.CreateUser(ctx, &model.User{Username: "u", PasswordHash: "h", CreatedAt: now})
sid, _ := s.CreateSet(ctx, &model.Set{Name: "s", RootPath: "/s", CreatedAt: now})
mid, _ := s.CreateMedia(ctx, &model.Media{SetID: sid, RelPath: "a.mp4", FileName: "a.mp4", AbsPath: "/s/a.mp4", Type: model.MediaTypeVideo, CreatedAt: now})
- if err := s.UpsertProgress(ctx, &model.PlaybackProgress{UserID: uid, MediaID: mid, PositionSeconds: 42, UpdatedAt: now}); err != nil {
+ if err := s.UpsertProgress(ctx, &model.PlaybackProgress{UserID: uid, MediaID: mid, PositionSeconds: 42, Finished: true, UpdatedAt: now}); err != nil {
t.Fatalf("upsert: %v", err)
}
p, err := s.GetProgress(ctx, uid, mid)
@@ -474,10 +474,16 @@ func TestSQLite_PlaybackProgressRepo(t *testing.T) {
if p.PositionSeconds != 42 {
t.Fatalf("expected 42, got %f", p.PositionSeconds)
}
+ if !p.Finished {
+ t.Fatal("expected finished")
+ }
pp, _ := s.ListProgressByUser(ctx, uid)
if len(pp) != 1 {
t.Fatalf("expected 1, got %d", len(pp))
}
+ if !pp[0].Finished {
+ t.Fatal("expected listed progress to be finished")
+ }
},
},
}