refactor lyric.go

This commit is contained in:
tramhao 2021-03-26 00:48:01 +08:00
parent 112bb338a4
commit 01b4c3f692
7 changed files with 95 additions and 99 deletions

View File

@ -19,32 +19,9 @@ type SongTag struct {
LyricID string LyricID string
} }
// GetLyric return the actual function based on lang type GetLyrics interface {
func GetLyric(lang string, songTag *SongTag) (string, error) { GetLyric(songTag *SongTag) (string, error)
GetLyricOptions(search string) ([]*SongTag, error)
switch lang {
case "en":
return getLyricEn(songTag)
case "zh-CN":
return getLyricCn(songTag)
default:
return getLyricEn(songTag)
}
}
// GetLyricOptions return the actual function based on lang
func GetLyricOptions(lang string, search string) ([]*SongTag, error) {
switch lang {
case "en":
return getLyricOptionsEn(search)
case "zh-CN":
return getLyricOptionsCn(search)
default:
return getLyricOptionsEn(search)
}
} }
// cleanHTML parses html text to valid utf-8 text // cleanHTML parses html text to valid utf-8 text

View File

@ -42,8 +42,10 @@ type tagLyric struct {
Tlyric string `json:"tlyric"` Tlyric string `json:"tlyric"`
} }
// getLyricOptionsCn queries available song lyrics. It returns slice of SongTag type GetLyricCn struct{}
func getLyricOptionsCn(search string) ([]*SongTag, error) {
// GetLyricOptions queries available song lyrics. It returns slice of SongTag
func (cn GetLyricCn) GetLyricOptions(search string) ([]*SongTag, error) {
serviceProvider := "netease" serviceProvider := "netease"
results, err := getLyricOptionsCnByProvider(search, serviceProvider) results, err := getLyricOptionsCnByProvider(search, serviceProvider)
@ -61,9 +63,9 @@ func getLyricOptionsCn(search string) ([]*SongTag, error) {
return results, err return results, err
} }
// getLyricCn should receive songTag that was returned from getLyricOptionsCn // GetLyric should receive songTag that was returned from getLyricOptions
// and returns lyric of the queried song. // and returns lyric of the queried song.
func getLyricCn(songTag *SongTag) (lyricString string, err error) { func (cn GetLyricCn) GetLyric(songTag *SongTag) (lyricString string, err error) {
urlSearch := "http://api.sunyj.xyz" urlSearch := "http://api.sunyj.xyz"

View File

@ -8,9 +8,11 @@ import (
"github.com/gocolly/colly" "github.com/gocolly/colly"
) )
// getLyricEn should receive SongTag that was returned from GetLyricOptions, and type GetLyricEn struct{}
// GetLyric should receive SongTag that was returned from GetLyricOptions, and
// returns lyric of the queried song. // returns lyric of the queried song.
func getLyricEn(songTag *SongTag) (string, error) { func (en GetLyricEn) GetLyric(songTag *SongTag) (string, error) {
var lyric string var lyric string
c := colly.NewCollector() c := colly.NewCollector()
@ -37,8 +39,8 @@ func getLyricEn(songTag *SongTag) (string, error) {
return "", fmt.Errorf("lyric not compatible") return "", fmt.Errorf("lyric not compatible")
} }
// getLyricOptionsEn queries available song lyrics. It returns slice of SongTag // GetLyricOptions queries available song lyrics. It returns slice of SongTag
func getLyricOptionsEn(search string) ([]*SongTag, error) { func (en GetLyricEn) GetLyricOptions(search string) ([]*SongTag, error) {
var songTags []*SongTag var songTags []*SongTag

View File

@ -23,7 +23,8 @@ func TestCleanHTML(t *testing.T) {
assert.Equal(t, string(clean), got) assert.Equal(t, string(clean), got)
_, err = NewFromLRC(got) var lyric Lyric
err = lyric.NewFromLRC(got)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

View File

@ -850,7 +850,15 @@ func ytSearchPopup() {
func lyricPopup(lang string, audioFile *AudioFile, wg *sync.WaitGroup) error { func lyricPopup(lang string, audioFile *AudioFile, wg *sync.WaitGroup) error {
var titles []string var titles []string
results, err := lyric.GetLyricOptions(lang, audioFile.name) var getLyric lyric.GetLyrics
if lang == "zh-CN" {
getLyric = lyric.GetLyricCn{}
} else if lang == "en" {
getLyric = lyric.GetLyricEn{}
} else {
getLyric = lyric.GetLyricEn{}
}
results, err := getLyric.GetLyricOptions(audioFile.name)
if err != nil { if err != nil {
return tracerr.Wrap(err) return tracerr.Wrap(err)
} }
@ -873,7 +881,7 @@ func lyricPopup(lang string, audioFile *AudioFile, wg *sync.WaitGroup) error {
break break
} }
} }
lyricContent, err := lyric.GetLyric(results[selectedIndex].LangExt, results[selectedIndex]) lyricContent, err := getLyric.GetLyric(results[selectedIndex])
if err != nil { if err != nil {
errorPopup(err) errorPopup(err)
gomu.app.Draw() gomu.app.Draw()

View File

@ -17,10 +17,11 @@ import (
"github.com/issadarkthing/gomu/lyric" "github.com/issadarkthing/gomu/lyric"
) )
// myFlex extend the flex control to modify the Focus item // lyricFlex extend the flex control to modify the Focus item
type myFlex struct { type lyricFlex struct {
*tview.Flex *tview.Flex
FocusedItem tview.Primitive FocusedItem tview.Primitive
inputs []tview.Primitive
} }
var box *tview.Box = tview.NewBox() var box *tview.Box = tview.NewBox()
@ -29,7 +30,7 @@ var box *tview.Box = tview.NewBox()
func tagPopup(node *AudioFile) (err error) { func tagPopup(node *AudioFile) (err error) {
popupID := "tag-editor-input-popup" popupID := "tag-editor-input-popup"
tag, popupLyricMap, options, err := loadTagMap(node) tag, popupLyricMap, options, err := node.loadTagMap()
if err != nil { if err != nil {
return tracerr.Wrap(err) return tracerr.Wrap(err)
} }
@ -67,51 +68,53 @@ func tagPopup(node *AudioFile) (err error) {
getTagButton.SetSelectedFunc(func() { getTagButton.SetSelectedFunc(func() {
var titles []string var titles []string
audioFile := node audioFile := node
lang := "zh-CN"
results, err := lyric.GetLyricOptions(lang, audioFile.name)
if err != nil {
errorPopup(err)
return
}
for _, v := range results {
titles = append(titles, v.TitleForPopup)
}
go func() { go func() {
searchPopup(" Song Tags ", titles, func(selected string) { var getLyric lyric.GetLyricCn
if selected == "" { results, err := getLyric.GetLyricOptions(audioFile.name)
return if err != nil {
} errorPopup(err)
return
}
for _, v := range results {
titles = append(titles, v.TitleForPopup)
}
var selectedIndex int go func() {
for i, v := range results { searchPopup(" Song Tags ", titles, func(selected string) {
if v.TitleForPopup == selected { if selected == "" {
selectedIndex = i return
break
} }
}
newTag := results[selectedIndex] var selectedIndex int
artistInputField.SetText(newTag.Artist) for i, v := range results {
titleInputField.SetText(newTag.Title) if v.TitleForPopup == selected {
albumInputField.SetText(newTag.Album) selectedIndex = i
break
}
}
tag, err = id3v2.Open(node.path, id3v2.Options{Parse: true}) newTag := results[selectedIndex]
if err != nil { artistInputField.SetText(newTag.Artist)
errorPopup(err) titleInputField.SetText(newTag.Title)
return albumInputField.SetText(newTag.Album)
}
defer tag.Close() tag, err = id3v2.Open(node.path, id3v2.Options{Parse: true})
tag.SetArtist(newTag.Artist) if err != nil {
tag.SetTitle(newTag.Title) errorPopup(err)
tag.SetAlbum(newTag.Album) return
err = tag.Save() }
if err != nil { defer tag.Close()
errorPopup(err) tag.SetArtist(newTag.Artist)
return tag.SetTitle(newTag.Title)
} tag.SetAlbum(newTag.Album)
defaultTimedPopup(" Success ", "Tag update successfully") err = tag.Save()
}) if err != nil {
errorPopup(err)
return
}
defaultTimedPopup(" Success ", "Tag update successfully")
})
}()
}() }()
}). }).
SetBackgroundColorActivated(gomu.colors.popup). SetBackgroundColorActivated(gomu.colors.popup).
@ -247,7 +250,7 @@ func tagPopup(node *AudioFile) (err error) {
go func() { go func() {
// This is to ensure that the above go routine finish. // This is to ensure that the above go routine finish.
wg.Wait() wg.Wait()
_, popupLyricMap, newOptions, err := loadTagMap(audioFile) _, popupLyricMap, newOptions, err := audioFile.loadTagMap()
if err != nil { if err != nil {
errorPopup(err) errorPopup(err)
gomu.app.Draw() gomu.app.Draw()
@ -328,18 +331,19 @@ func tagPopup(node *AudioFile) (err error) {
rightFlex.SetDirection(tview.FlexColumn). rightFlex.SetDirection(tview.FlexColumn).
AddItem(lyricTextView, 0, 1, true) AddItem(lyricTextView, 0, 1, true)
lyricFlex := &myFlex{ lyricFlex := &lyricFlex{
tview.NewFlex().SetDirection(tview.FlexColumn). tview.NewFlex().SetDirection(tview.FlexColumn).
AddItem(leftGrid, 0, 2, true). AddItem(leftGrid, 0, 2, true).
AddItem(rightFlex, 0, 3, true), AddItem(rightFlex, 0, 3, true),
nil, nil,
nil,
} }
lyricFlex. lyricFlex.
SetTitle(node.name). SetTitle(node.name).
SetBorderPadding(1, 1, 2, 2) SetBorderPadding(1, 1, 2, 2)
inputs := []tview.Primitive{ lyricFlex.inputs = []tview.Primitive{
getTagButton, getTagButton,
artistInputField, artistInputField,
titleInputField, titleInputField,
@ -363,13 +367,13 @@ func tagPopup(node *AudioFile) (err error) {
gomu.pages.RemovePage(popupID) gomu.pages.RemovePage(popupID)
gomu.popups.pop() gomu.popups.pop()
case tcell.KeyTab: case tcell.KeyTab:
lyricFlex.cycleFocus(gomu.app, inputs, false) lyricFlex.cycleFocus(gomu.app, false)
case tcell.KeyBacktab: case tcell.KeyBacktab:
lyricFlex.cycleFocus(gomu.app, inputs, true) lyricFlex.cycleFocus(gomu.app, true)
case tcell.KeyRight: case tcell.KeyRight:
lyricFlex.cycleFocus(gomu.app, inputs, false) lyricFlex.cycleFocus(gomu.app, false)
case tcell.KeyLeft: case tcell.KeyLeft:
lyricFlex.cycleFocus(gomu.app, inputs, true) lyricFlex.cycleFocus(gomu.app, true)
} }
switch e.Rune() { switch e.Rune() {
@ -387,8 +391,8 @@ func tagPopup(node *AudioFile) (err error) {
} }
// This is a hack to cycle Focus in a flex // This is a hack to cycle Focus in a flex
func (f *myFlex) cycleFocus(app *tview.Application, elements []tview.Primitive, reverse bool) { func (f *lyricFlex) cycleFocus(app *tview.Application, reverse bool) {
for i, el := range elements { for i, el := range f.inputs {
if !el.HasFocus() { if !el.HasFocus() {
continue continue
} }
@ -396,22 +400,23 @@ func (f *myFlex) cycleFocus(app *tview.Application, elements []tview.Primitive,
if reverse { if reverse {
i = i - 1 i = i - 1
if i < 0 { if i < 0 {
i = len(elements) - 1 i = len(f.inputs) - 1
} }
} else { } else {
i = i + 1 i = i + 1
i = i % len(elements) i = i % len(f.inputs)
} }
app.SetFocus(elements[i]) app.SetFocus(f.inputs[i])
f.FocusedItem = elements[i] f.FocusedItem = f.inputs[i]
if elements[9].HasFocus() { // below code is setting the border highlight of left and right flex
elements[9].(*tview.TextView).SetBorderColor(gomu.colors.accent). if f.inputs[9].HasFocus() {
f.inputs[9].(*tview.TextView).SetBorderColor(gomu.colors.accent).
SetTitleColor(gomu.colors.accent) SetTitleColor(gomu.colors.accent)
box.SetBorderColor(gomu.colors.background). box.SetBorderColor(gomu.colors.background).
SetTitleColor(gomu.colors.background) SetTitleColor(gomu.colors.background)
} else { } else {
elements[9].(*tview.TextView).SetBorderColor(gomu.colors.background). f.inputs[9].(*tview.TextView).SetBorderColor(gomu.colors.background).
SetTitleColor(gomu.colors.background) SetTitleColor(gomu.colors.background)
box.SetBorderColor(gomu.colors.accent). box.SetBorderColor(gomu.colors.accent).
SetTitleColor(gomu.colors.accent) SetTitleColor(gomu.colors.accent)
@ -423,7 +428,7 @@ func (f *myFlex) cycleFocus(app *tview.Application, elements []tview.Primitive,
// Focus is an override of Focus function in tview.flex. // Focus is an override of Focus function in tview.flex.
// This is to ensure that the focus of flex remain unchanged // This is to ensure that the focus of flex remain unchanged
// when returning from popups or search lists // when returning from popups or search lists
func (f *myFlex) Focus(delegate func(p tview.Primitive)) { func (f *lyricFlex) Focus(delegate func(p tview.Primitive)) {
if f.FocusedItem != nil { if f.FocusedItem != nil {
gomu.app.SetFocus(f.FocusedItem) gomu.app.SetFocus(f.FocusedItem)
} else { } else {
@ -432,7 +437,7 @@ func (f *myFlex) Focus(delegate func(p tview.Primitive)) {
} }
// loadTagMap will load from tag and return a map of langExt to lyrics // loadTagMap will load from tag and return a map of langExt to lyrics
func loadTagMap(node *AudioFile) (tag *id3v2.Tag, popupLyricMap map[string]string, options []string, err error) { func (node *AudioFile) loadTagMap() (tag *id3v2.Tag, popupLyricMap map[string]string, options []string, err error) {
popupLyricMap = make(map[string]string) popupLyricMap = make(map[string]string)

View File

@ -127,7 +127,8 @@ func TestEmbedLyric(t *testing.T) {
t.Error(err) t.Error(err)
} }
}() }()
lyric, err := lyric.NewFromLRC(lyricString) var lyric lyric.Lyric
err = lyric.NewFromLRC(lyricString)
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }