Add watch progress feature to video model and UI
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Build / build (push) Successful in 2m29s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Build / build (push) Successful in 2m29s
				
			This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,6 +1,7 @@
 | 
				
			|||||||
.idea
 | 
					.idea
 | 
				
			||||||
*.iml
 | 
					*.iml
 | 
				
			||||||
*.db3
 | 
					*.db3
 | 
				
			||||||
 | 
					*.db3.*
 | 
				
			||||||
*.db3-*
 | 
					*.db3-*
 | 
				
			||||||
*.bak*
 | 
					*.bak*
 | 
				
			||||||
/downloads/
 | 
					/downloads/
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								migrations/6_add_watch_progress.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								migrations/6_add_watch_progress.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					ALTER TABLE videos ADD COLUMN watch_progress REAL;
 | 
				
			||||||
@@ -93,6 +93,25 @@
 | 
				
			|||||||
			opacity: 1;
 | 
								opacity: 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.progress-bar-container {
 | 
				
			||||||
 | 
								position: absolute;
 | 
				
			||||||
 | 
								bottom: 0;
 | 
				
			||||||
 | 
								left: 0;
 | 
				
			||||||
 | 
								width: 100%;
 | 
				
			||||||
 | 
								height: 5px; /* Or adjust as needed */
 | 
				
			||||||
 | 
								background-color: rgba(0, 0, 0, 0.5);
 | 
				
			||||||
 | 
								border-bottom-left-radius: 8px;
 | 
				
			||||||
 | 
								border-bottom-right-radius: 8px;
 | 
				
			||||||
 | 
								overflow: hidden;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							.progress-bar {
 | 
				
			||||||
 | 
								height: 100%;
 | 
				
			||||||
 | 
								background-color: #3498db; /* A nice blue */
 | 
				
			||||||
 | 
								width: 0; /* Initially no progress */
 | 
				
			||||||
 | 
								transition: width 0.2s ease-in-out;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		.play-button {
 | 
							.play-button {
 | 
				
			||||||
			position: absolute;
 | 
								position: absolute;
 | 
				
			||||||
			top: 50%;
 | 
								top: 50%;
 | 
				
			||||||
@@ -339,7 +358,13 @@
 | 
				
			|||||||
			let container = $(`<div class="video-thumbnail" tabindex="0" role="button" aria-label="${data.title}"></div>`);
 | 
								let container = $(`<div class="video-thumbnail" tabindex="0" role="button" aria-label="${data.title}"></div>`);
 | 
				
			||||||
			let thumbnailImg = $(`<img src="${data.thumbnail}" alt="" style="width: 100%; height: 100%; object-fit: cover;">`);
 | 
								let thumbnailImg = $(`<img src="${data.thumbnail}" alt="" style="width: 100%; height: 100%; object-fit: cover;">`);
 | 
				
			||||||
			let title = $(`<div class="video-title">${data.title}</div>`);
 | 
								let title = $(`<div class="video-title">${data.title}</div>`);
 | 
				
			||||||
			container.append(thumbnailImg).append(title);
 | 
								let progressBarContainer = $(`<div class="progress-bar-container"><div class="progress-bar"></div></div>`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								container.append(thumbnailImg).append(title).append(progressBarContainer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (data.watchProgress > 0) {
 | 
				
			||||||
 | 
									progressBarContainer.find(".progress-bar").css("width", (data.watchProgress * 100) + "%");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			let index;
 | 
								let index;
 | 
				
			||||||
			if (append) {
 | 
								if (append) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										17
									
								
								webview.go
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								webview.go
									
									
									
									
									
								
							@@ -52,10 +52,11 @@ func serveWebview(db *mysqlite.Db) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type VideoModel struct {
 | 
					type VideoModel struct {
 | 
				
			||||||
	ID        int    `json:"id"`
 | 
						ID            int     `json:"id"`
 | 
				
			||||||
	Thumbnail string `json:"thumbnail"`
 | 
						Thumbnail     string  `json:"thumbnail"`
 | 
				
			||||||
	URL       string `json:"url"`
 | 
						URL           string  `json:"url"`
 | 
				
			||||||
	Title     string `json:"title"`
 | 
						Title         string  `json:"title"`
 | 
				
			||||||
 | 
						WatchProgress float64 `json:"watchProgress"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type HomePageModel struct {
 | 
					type HomePageModel struct {
 | 
				
			||||||
@@ -66,13 +67,13 @@ type HomePageModel struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (a *App) homePage(c *gin.Context) {
 | 
					func (a *App) homePage(c *gin.Context) {
 | 
				
			||||||
	model := HomePageModel{}
 | 
						model := HomePageModel{}
 | 
				
			||||||
	errCurrent := a.db.Query("SELECT id, thumbnail, title FROM videos WHERE (watch_state IS NULL OR watch_state != 'watched') ORDER BY upload_date, episode LIMIT 1").
 | 
						errCurrent := a.db.Query("SELECT id, thumbnail, title, watch_progress FROM videos WHERE (watch_state IS NULL OR watch_state != 'watched') ORDER BY upload_date, episode LIMIT 1").
 | 
				
			||||||
		ScanSingle(&model.Current.ID, &model.Current.Thumbnail, &model.Current.Title)
 | 
							ScanSingle(&model.Current.ID, &model.Current.Thumbnail, &model.Current.Title, &model.Current.WatchProgress)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var errNext, errPrevious error
 | 
						var errNext, errPrevious error
 | 
				
			||||||
	for row := range a.db.Query("SELECT id, thumbnail, title FROM videos WHERE (watch_state IS NULL OR watch_state != 'watched') ORDER BY upload_date, episode LIMIT 3 OFFSET 1").Range(&errNext) {
 | 
						for row := range a.db.Query("SELECT id, thumbnail, title, watch_progress FROM videos WHERE (watch_state IS NULL OR watch_state != 'watched') ORDER BY upload_date, episode LIMIT 3 OFFSET 1").Range(&errNext) {
 | 
				
			||||||
		video := VideoModel{}
 | 
							video := VideoModel{}
 | 
				
			||||||
		err := row.Scan(&video.ID, &video.Thumbnail, &video.Title)
 | 
							err := row.Scan(&video.ID, &video.Thumbnail, &video.Title, &video.WatchProgress)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.Printf("Failed to scan next video: %v", err)
 | 
								log.Printf("Failed to scan next video: %v", err)
 | 
				
			||||||
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve next videos"})
 | 
								c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve next videos"})
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user