Add chapter naming per clip in author videos tab
This commit is contained in:
parent
595b1603ee
commit
71021f5585
|
|
@ -95,6 +95,18 @@ func buildVideoClipsTab(state *appState) fyne.CanvasObject {
|
||||||
durationLabel.TextStyle = fyne.TextStyle{Italic: true}
|
durationLabel.TextStyle = fyne.TextStyle{Italic: true}
|
||||||
durationLabel.Alignment = fyne.TextAlignTrailing
|
durationLabel.Alignment = fyne.TextAlignTrailing
|
||||||
|
|
||||||
|
titleEntry := widget.NewEntry()
|
||||||
|
titleEntry.SetPlaceHolder(fmt.Sprintf("Chapter %d", idx+1))
|
||||||
|
titleEntry.SetText(clip.ChapterTitle)
|
||||||
|
titleEntry.OnChanged = func(val string) {
|
||||||
|
state.authorClips[idx].ChapterTitle = val
|
||||||
|
if state.authorTreatAsChapters {
|
||||||
|
state.authorChapters = chaptersFromClips(state.authorClips)
|
||||||
|
state.authorChapterSource = "clips"
|
||||||
|
state.updateAuthorSummary()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
removeBtn := widget.NewButton("Remove", func() {
|
removeBtn := widget.NewButton("Remove", func() {
|
||||||
state.authorClips = append(state.authorClips[:idx], state.authorClips[idx+1:]...)
|
state.authorClips = append(state.authorClips[:idx], state.authorClips[idx+1:]...)
|
||||||
rebuildList()
|
rebuildList()
|
||||||
|
|
@ -107,7 +119,7 @@ func buildVideoClipsTab(state *appState) fyne.CanvasObject {
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
container.NewVBox(durationLabel, removeBtn),
|
container.NewVBox(durationLabel, removeBtn),
|
||||||
container.NewVBox(nameLabel),
|
container.NewVBox(nameLabel, titleEntry),
|
||||||
)
|
)
|
||||||
cardBg := canvas.NewRectangle(utils.MustHex("#171C2A"))
|
cardBg := canvas.NewRectangle(utils.MustHex("#171C2A"))
|
||||||
cardBg.CornerRadius = 6
|
cardBg.CornerRadius = 6
|
||||||
|
|
@ -150,9 +162,11 @@ func buildVideoClipsTab(state *appState) fyne.CanvasObject {
|
||||||
chapterToggle := widget.NewCheck("Treat videos as chapters", func(checked bool) {
|
chapterToggle := widget.NewCheck("Treat videos as chapters", func(checked bool) {
|
||||||
state.authorTreatAsChapters = checked
|
state.authorTreatAsChapters = checked
|
||||||
if checked {
|
if checked {
|
||||||
|
state.authorChapters = chaptersFromClips(state.authorClips)
|
||||||
state.authorChapterSource = "clips"
|
state.authorChapterSource = "clips"
|
||||||
} else if state.authorChapterSource == "clips" {
|
} else if state.authorChapterSource == "clips" {
|
||||||
state.authorChapterSource = ""
|
state.authorChapterSource = ""
|
||||||
|
state.authorChapters = nil
|
||||||
}
|
}
|
||||||
state.updateAuthorSummary()
|
state.updateAuthorSummary()
|
||||||
})
|
})
|
||||||
|
|
@ -533,10 +547,11 @@ func (s *appState) addAuthorFiles(paths []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
clip := authorClip{
|
clip := authorClip{
|
||||||
Path: path,
|
Path: path,
|
||||||
DisplayName: filepath.Base(path),
|
DisplayName: filepath.Base(path),
|
||||||
Duration: src.Duration,
|
Duration: src.Duration,
|
||||||
Chapters: []authorChapter{},
|
Chapters: []authorChapter{},
|
||||||
|
ChapterTitle: strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)),
|
||||||
}
|
}
|
||||||
s.authorClips = append(s.authorClips, clip)
|
s.authorClips = append(s.authorClips, clip)
|
||||||
}
|
}
|
||||||
|
|
@ -595,12 +610,20 @@ func chaptersFromClips(clips []authorClip) []authorChapter {
|
||||||
}
|
}
|
||||||
var chapters []authorChapter
|
var chapters []authorChapter
|
||||||
var t float64
|
var t float64
|
||||||
chapters = append(chapters, authorChapter{Timestamp: 0, Title: "Chapter 1", Auto: true})
|
firstTitle := strings.TrimSpace(clips[0].ChapterTitle)
|
||||||
|
if firstTitle == "" {
|
||||||
|
firstTitle = "Chapter 1"
|
||||||
|
}
|
||||||
|
chapters = append(chapters, authorChapter{Timestamp: 0, Title: firstTitle, Auto: true})
|
||||||
for i := 1; i < len(clips); i++ {
|
for i := 1; i < len(clips); i++ {
|
||||||
t += clips[i-1].Duration
|
t += clips[i-1].Duration
|
||||||
|
title := strings.TrimSpace(clips[i].ChapterTitle)
|
||||||
|
if title == "" {
|
||||||
|
title = fmt.Sprintf("Chapter %d", i+1)
|
||||||
|
}
|
||||||
chapters = append(chapters, authorChapter{
|
chapters = append(chapters, authorChapter{
|
||||||
Timestamp: t,
|
Timestamp: t,
|
||||||
Title: fmt.Sprintf("Chapter %d", i+1),
|
Title: title,
|
||||||
Auto: true,
|
Auto: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
main.go
22
main.go
|
|
@ -933,10 +933,11 @@ type authorChapter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type authorClip struct {
|
type authorClip struct {
|
||||||
Path string // Video file path
|
Path string // Video file path
|
||||||
DisplayName string // Display name in UI
|
DisplayName string // Display name in UI
|
||||||
Duration float64 // Video duration
|
Duration float64 // Video duration
|
||||||
Chapters []authorChapter // Chapters for this clip
|
Chapters []authorChapter // Chapters for this clip
|
||||||
|
ChapterTitle string // Optional chapter title when treating clips as chapters
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *appState) persistConvertConfig() {
|
func (s *appState) persistConvertConfig() {
|
||||||
|
|
@ -13105,10 +13106,21 @@ func buildPlayerView(state *appState) fyne.CanvasObject {
|
||||||
fileLabel := widget.NewLabel("No file loaded")
|
fileLabel := widget.NewLabel("No file loaded")
|
||||||
fileLabel.TextStyle = fyne.TextStyle{Bold: true}
|
fileLabel.TextStyle = fyne.TextStyle{Bold: true}
|
||||||
|
|
||||||
|
// Determine video pane size based on screen resolution
|
||||||
|
screenSize := fyne.CurrentApp().Driver().AllWindows()[0].Canvas().Size()
|
||||||
|
var playerSize fyne.Size
|
||||||
|
if screenSize.Width < 1600 {
|
||||||
|
// Use smaller size for lower resolution displays
|
||||||
|
playerSize = fyne.NewSize(640, 360)
|
||||||
|
} else {
|
||||||
|
// Use larger size for higher resolution displays
|
||||||
|
playerSize = fyne.NewSize(1280, 720)
|
||||||
|
}
|
||||||
|
|
||||||
var videoContainer fyne.CanvasObject
|
var videoContainer fyne.CanvasObject
|
||||||
if state.playerFile != nil {
|
if state.playerFile != nil {
|
||||||
fileLabel.SetText(fmt.Sprintf("File: %s", filepath.Base(state.playerFile.Path)))
|
fileLabel.SetText(fmt.Sprintf("File: %s", filepath.Base(state.playerFile.Path)))
|
||||||
videoContainer = buildVideoPane(state, fyne.NewSize(1280, 720), state.playerFile, nil)
|
videoContainer = buildVideoPane(state, playerSize, state.playerFile, nil)
|
||||||
} else {
|
} else {
|
||||||
videoContainer = container.NewCenter(widget.NewLabel("No video loaded"))
|
videoContainer = container.NewCenter(widget.NewLabel("No video loaded"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user