Skip to content

Commit 51bef50

Browse files
committed
feat: 动态加载歌曲
1 parent 7ae6641 commit 51bef50

File tree

4 files changed

+104
-48
lines changed

4 files changed

+104
-48
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
## TODO
1515

1616
- [x] 扫码登录(不登录无法获取超过一页的歌曲)
17-
- [ ] 支持动态添加更多音乐
17+
- [x] 支持动态添加更多音乐
1818
- [ ] 支持广场动态
1919
- [ ] 支持更多的Topic
20-
- [ ] 优化UI
20+
- [x] 优化UI
2121
- [ ] 支持除网易云音乐以外的更多歌曲
2222

2323
---

fm.go

Lines changed: 68 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,20 @@ import (
77
"github.com/faiface/beep"
88
"github.com/faiface/beep/speaker"
99
"github.com/gdamore/tcell"
10+
"strconv"
1011
"strings"
1112
"time"
1213
"unicode"
1314
)
1415

15-
var topics = map[string]string{
16-
"55483ddee4b03ccbae843925": "晚安电台",
17-
"5a1ccf936e6e7c0011037480": "即友在听什么歌",
16+
type Topic struct {
17+
id string
18+
name string
19+
}
20+
21+
var topics = []Topic{
22+
{id: "55483ddee4b03ccbae843925", name: "晚安电台"},
23+
{id: "5a1ccf936e6e7c0011037480", name: "即友在听什么歌"},
1824
}
1925

2026
var CurrentSession *jike.Session
@@ -29,26 +35,50 @@ type JikeFm struct {
2935
playlist []jike.Message
3036
player *Player
3137
currentMusic Music
32-
currentTopic string
38+
currentTopicIndex int
3339
nextMusicIndex int
3440
skip string
41+
more chan bool
3542
}
3643

3744
func newFm() *JikeFm {
3845
p := &JikeFm{
39-
currentTopic:"55483ddee4b03ccbae843925",
46+
currentTopicIndex: 0,
47+
more: make(chan bool, 1),
4048
}
4149
p.player = newPlayer(p.iter)
4250
p.nextMusicIndex = 0
51+
go p.fetchMore()
4352
return p
4453
}
4554

46-
func (p *JikeFm) feed() {
47-
res, next, _ := jike.FetchMoreSelectedFM(CurrentSession, p.currentTopic, p.skip)
48-
for _, msg := range res {
49-
p.playlist = append(p.playlist, msg)
55+
func (p *JikeFm) fetchMore() {
56+
for {
57+
<- p.more
58+
msgs := p.feed()
59+
60+
UI.app.QueueUpdateDraw(func() {
61+
currentLen := len(p.playlist)
62+
p.addToPlaylist(msgs)
63+
updateTotalSong(len(p.playlist))
64+
if p.nextMusicIndex == 0 {
65+
p.nextMusicIndex = currentLen
66+
}
67+
})
5068
}
69+
}
70+
71+
func (p *JikeFm) feed() []jike.Message {
72+
res, next, _ := jike.FetchMoreSelectedFM(CurrentSession, topics[p.currentTopicIndex].id, p.skip)
5173
p.skip = next
74+
return res
75+
}
76+
77+
func (p *JikeFm) addToPlaylist(messages []jike.Message) {
78+
for _, msg := range messages {
79+
p.playlist = append(p.playlist, msg)
80+
UI.side.AddItem(normalText(len(p.playlist), msg.GetTitle()), "", 0, nil)
81+
}
5282
}
5383

5484
func (p *JikeFm) play() {
@@ -82,6 +112,9 @@ func (p *JikeFm) onSelectChange(index int, _ string, _ string, _ rune) {
82112
if index >= len(p.playlist) {
83113
i = index - len(p.playlist)
84114
}
115+
if index == len(p.playlist) - 1 {
116+
p.queueMore()
117+
}
85118
msg := p.playlist[i]
86119
UI.main.SetText(msg.Content)
87120
UI.mainAuthor.SetText("[green]@" + msg.User.ScreenName)
@@ -104,24 +137,34 @@ func (p *JikeFm) changeSong(from int, target int) {
104137
if from >= 0 {
105138
UI.side.SetItemText(
106139
from,
107-
normalText(from, p.playlist[from].GetTitle()),
140+
normalText(from + 1, p.playlist[from].GetTitle()),
108141
"",
109142
)
110143
}
111144
UI.side.SetItemText(
112145
target,
113-
playingText(target, p.playlist[target].GetTitle()),
146+
playingText(target + 1, p.playlist[target].GetTitle()),
114147
"",
115148
)
116149
}
117150

151+
func (p *JikeFm) queueMore() {
152+
select {
153+
case p.more <- true:
154+
default:
155+
}
156+
}
157+
118158
func (p *JikeFm) iter() beep.Streamer {
119159
if len(p.playlist) == 0 {
120160
return nil
121161
}
122162
stream := p.playIndex(p.nextMusicIndex)
123-
var next int
124-
if next = p.nextMusicIndex + 1; next >= len(p.playlist) {
163+
next := p.nextMusicIndex + 1
164+
if next > len(p.playlist) - 1 {
165+
p.queueMore()
166+
}
167+
if next >= len(p.playlist) {
125168
next = 0
126169
}
127170
p.nextMusicIndex = next
@@ -133,10 +176,17 @@ func (p *JikeFm) handle(event *tcell.EventKey) *tcell.EventKey {
133176
switch event.Key() {
134177
case tcell.KeyESC:
135178
UI.app.Stop()
179+
case tcell.KeyCtrlN:
180+
return nil
181+
case tcell.KeyCtrlP:
182+
return nil
183+
case tcell.KeyTab:
184+
return nil
136185
case tcell.KeyRune:
137186
switch unicode.ToLower(event.Rune()) {
138187
case ' ':
139188
p.player.togglePlay()
189+
return nil
140190
}
141191
}
142192
return event
@@ -148,30 +198,23 @@ func main() {
148198

149199
defer fm.player.close()
150200

151-
for {
152-
fm.feed()
153-
if len(fm.playlist) > 20 {
154-
break
155-
}
156-
}
201+
fm.addToPlaylist(fm.feed())
202+
updateTotalSong(len(fm.playlist))
157203

158204
fm.onSelectChange(0, "", "", 0)
159205

160-
for index, msg := range fm.playlist {
161-
UI.side.AddItem(normalText(index, msg.GetTitle()), "", 0, nil)
162-
}
163-
164206
UI.side.
165207
SetChangedFunc(fm.onSelectChange).
166208
SetSelectedFunc(fm.onEnterPlay).
167209
ShowSecondaryText(false)
168210
UI.app.SetInputCapture(fm.handle)
169211

170212
var s []string
171-
for id, topicName := range topics {
172-
s = append(s, fmt.Sprintf(`["%s"]%s[""]`, id, topicName))
213+
for index, topic := range topics {
214+
s = append(s, fmt.Sprintf(`["%d"]%s[""]`, index, topic.name))
173215
}
174216
UI.footerTopic.SetText("| " + strings.Join(s, " | ") + " |")
217+
UI.footerTopic.Highlight(strconv.Itoa(fm.currentTopicIndex))
175218

176219
fm.play()
177220

ui.go

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"github.com/rivo/tview"
77
)
88

9-
var UI = struct {
9+
type Components struct {
1010
app *tview.Application
1111
root *tview.Flex
1212
header *tview.TextView
@@ -15,19 +15,10 @@ var UI = struct {
1515
mainAuthor *tview.TextView
1616
footerTopic *tview.TextView
1717
footerHelp *tview.TextView
18-
}{
19-
app: tview.NewApplication(),
20-
root: tview.NewFlex().SetDirection(tview.FlexRow),
21-
header: tview.NewTextView().SetDynamicColors(true),
22-
main: tview.NewTextView().SetDynamicColors(true),
23-
mainAuthor: tview.NewTextView().SetDynamicColors(true).SetTextAlign(tview.AlignRight),
24-
side: tview.NewList(),
25-
footerTopic: tview.NewTextView().
26-
SetDynamicColors(true).SetRegions(true).SetWrap(false).SetTextAlign(tview.AlignCenter),
27-
footerHelp: tview.NewTextView().
28-
SetDynamicColors(true).SetRegions(true).SetWrap(false).SetTextAlign(tview.AlignRight),
2918
}
3019

20+
var UI Components
21+
3122
var headerTpl = `
3223
[red]♫ ♪ ♫ ♪ [yellow]%s
3324
@@ -40,37 +31,56 @@ var normalTpl = "[yellow]% 3d) \t[-:-:-]%s"
4031
var playingTpl = "[purple]% 3d) \t->[::b] %s"
4132

4233
func init() {
34+
UI = Components{
35+
app: tview.NewApplication(),
36+
root: tview.NewFlex().SetDirection(tview.FlexRow),
37+
header: tview.NewTextView().SetDynamicColors(true),
38+
main: tview.NewTextView().SetDynamicColors(true),
39+
mainAuthor: tview.NewTextView().SetDynamicColors(true).SetTextAlign(tview.AlignRight),
40+
side: tview.NewList().SetSelectedBackgroundColor(tcell.ColorDimGray),
41+
footerTopic: tview.NewTextView().
42+
SetDynamicColors(true).SetRegions(true).SetWrap(false).SetTextAlign(tview.AlignCenter),
43+
footerHelp: tview.NewTextView().
44+
SetDynamicColors(true).SetRegions(true).SetWrap(false).SetTextAlign(tview.AlignRight).
45+
SetText(footerTpl),
46+
}
4347
UI.root.SetRect(0, 0, 100, 40)
44-
UI.header.SetBorder(true).SetTitle("JIKE FM")
48+
UI.header.SetBorder(true).SetTitle("即刻电台 " + version)
4549
UI.side.SetBorder(true).SetBorderPadding(1, 0, 0, 1)
4650

4751
mainContainer := tview.NewFlex().SetDirection(tview.FlexRow).
4852
AddItem(UI.main, 0, 1, false).
4953
AddItem(UI.mainAuthor, 2, 1, false)
5054
mainContainer.SetBorder(true).SetBorderPadding(1, 0, 2, 2)
51-
footer := tview.NewFlex().SetDirection(tview.FlexColumn)
52-
footer.SetBackgroundColor(tcell.ColorGrey)
53-
UI.footerHelp.SetText(footerTpl).SetBackgroundColor(tcell.ColorGrey)
54-
UI.footerTopic.SetBackgroundColor(tcell.ColorGrey)
55-
footer.
55+
56+
footerContainer := tview.NewFlex().SetDirection(tview.FlexColumn).
5657
AddItem(UI.footerTopic, 40, 1, false).
5758
AddItem(UI.footerHelp, 0, 1, false)
59+
60+
footerContainer.SetBackgroundColor(tcell.ColorGrey)
61+
UI.footerHelp.SetBackgroundColor(tcell.ColorGrey)
62+
UI.footerTopic.SetBackgroundColor(tcell.ColorGrey)
63+
5864
UI.root.
5965
AddItem(UI.header, 7, 1, false).
6066
AddItem(tview.NewFlex().SetDirection(tview.FlexColumn).
6167
AddItem(UI.side, 40, 1, true).
6268
AddItem(mainContainer, 0, 1, false),
6369
0, 1, false).
64-
AddItem(footer, 1, 1, false)
70+
AddItem(footerContainer, 1, 1, false)
6571
UI.app.SetRoot(UI.root, false).SetFocus(UI.side)
6672
}
6773

6874
func normalText(index int, title string) string {
69-
return fmt.Sprintf(normalTpl, index + 1, title)
75+
return fmt.Sprintf(normalTpl, index, title)
7076
}
7177

7278
func playingText(index int, title string) string {
73-
return fmt.Sprintf(playingTpl, index + 1, title)
79+
return fmt.Sprintf(playingTpl, index, title)
80+
}
81+
82+
func updateTotalSong(count int) {
83+
UI.side.SetTitle(fmt.Sprintf(" 歌曲数: %d", count))
7484
}
7585

7686
func run() error {

version.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package main
2+
3+
var version = "v0.1.0"

0 commit comments

Comments
 (0)