fix bug/webinfo-add custom template

This commit is contained in:
Aynakeya
2022-07-19 18:09:44 -07:00
parent f6b58a3e9d
commit 05c44079e2
9 changed files with 100 additions and 27 deletions

View File

@@ -8,7 +8,7 @@ import (
const ( const (
ProgramName = "卡西米尔唱片机" ProgramName = "卡西米尔唱片机"
Version = "alpha 0.8.6" Version = "beta 0.9.0"
) )
const ( const (

View File

@@ -90,14 +90,17 @@ func newImageFromPlayerPicture(picture player.Picture) (*canvas.Image, error) {
return img, nil return img, nil
} else { } else {
uri, err := storage.ParseURI(picture.Url) uri, err := storage.ParseURI(picture.Url)
if err != nil || uri == nil { if err != nil {
return nil, err return nil, err
} }
if uri == nil {
return nil, errors.New("fail to fail url")
}
img := canvas.NewImageFromURI(uri) img := canvas.NewImageFromURI(uri)
if img == nil { if img == nil {
// bug fix, return a new error to indicate fail to read an image // bug fix, return a new error to indicate fail to read an image
return nil, errors.New("fail to read image") return nil, errors.New("fail to read image")
} }
return img, err return img, nil
} }
} }

View File

@@ -202,21 +202,6 @@ func registerPlayControllerHandler() {
PlayController.Cover.Resource = picture.Resource PlayController.Cover.Resource = picture.Resource
PlayController.Cover.Refresh() PlayController.Cover.Refresh()
}() }()
//uri, err := storage.ParseURI(media.Cover)
//if err != nil || uri == nil {
// l().Warn("fail to load parse cover url", media.Cover)
//}
//// async update
//go func() {
// img := canvas.NewImageFromURI(uri)
// if img == nil {
// l().Warn("fail to load parse cover url", media.Cover)
// PlayController.SetDefaultCover()
// return
// }
// PlayController.Cover.Resource = img.Resource
// PlayController.Cover.Refresh()
//}()
} }
}) })
return return

View File

@@ -14,6 +14,11 @@ var Logger *logrus.Logger
func init() { func init() {
Logger = logrus.New() Logger = logrus.New()
Logger.SetLevel(config.Log.Level) Logger.SetLevel(config.Log.Level)
Logger.SetFormatter(&nested.Formatter{
FieldsOrder: []string{"Module"},
HideKeys: true,
NoColors: true,
})
file, err := os.OpenFile(config.Log.Path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) file, err := os.OpenFile(config.Log.Path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if config.Log.RedirectStderr { if config.Log.RedirectStderr {
Logger.Info("panic/stderr redirect to log file") Logger.Info("panic/stderr redirect to log file")
@@ -26,9 +31,4 @@ func init() {
} else { } else {
Logger.Info("Failed to log to file, using default stdout") Logger.Info("Failed to log to file, using default stdout")
} }
Logger.SetFormatter(&nested.Formatter{
FieldsOrder: []string{"Module"},
HideKeys: true,
NoColors: true,
})
} }

View File

@@ -25,6 +25,7 @@ type WebInfoServer struct {
Server *http.Server Server *http.Server
Clients map[*Client]int Clients map[*Client]int
Running bool Running bool
Store *TemplateStore
lock sync.Mutex lock sync.Mutex
} }
@@ -36,18 +37,86 @@ type Client struct {
func NewWebInfoServer(port int) *WebInfoServer { func NewWebInfoServer(port int) *WebInfoServer {
server := &WebInfoServer{ server := &WebInfoServer{
Store: newTemplateStore(WebTemplateStorePath),
Port: port, Port: port,
Info: OutInfo{Playlist: make([]MediaInfo, 0)},
Clients: map[*Client]int{}, Clients: map[*Client]int{},
} }
mux := http.NewServeMux() mux := http.NewServeMux()
mux.Handle("/", http.FileServer(http.Dir(config.GetAssetPath("webinfo")))) mux.Handle("/", http.FileServer(http.Dir(config.GetAssetPath("webinfo"))))
mux.HandleFunc("/ws/info", server.handleInfo) mux.HandleFunc("/ws/info", server.handleInfo)
mux.HandleFunc("/api/info", server.getInfo) mux.HandleFunc("/api/info", server.getInfo)
mux.HandleFunc("/api/template/list", server.tmplList)
mux.HandleFunc("/api/template/get", server.tmplGet)
mux.HandleFunc("/api/template/save", server.tmplSave)
server.ServerMux = mux server.ServerMux = mux
return server return server
} }
func (s *WebInfoServer) tmplList(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
//w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
d, _ := json.Marshal(s.Store.List())
_, err := w.Write(d)
if err != nil {
lg.Warnf("/api/template/list error: %s", err)
return
}
}
func (s *WebInfoServer) tmplGet(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
name := r.URL.Query().Get("name")
if name == "" {
name = "default"
}
d, _ := json.Marshal(s.Store.Get(name))
_, err := w.Write(d)
if err != nil {
lg.Warnf("/api/template/get error: %s", err)
return
}
}
func (s *WebInfoServer) tmplSave(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Method", "*")
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Access-Control-Expose-Headers", "*")
w.Header().Set("Access-Control-Allow-Headers", "*")
lg.Info(r.Method)
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
if r.Method != "POST" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
if err := r.ParseMultipartForm(1 << 16); err != nil {
lg.Warnf("ParseForm() err: %v", err)
return
}
name := r.FormValue("name")
tmpl := r.FormValue("template")
if name == "" {
name = "default"
}
lg.Infof("change template %s", name)
s.Store.Modify(name, tmpl)
d, _ := json.Marshal(s.Store.Get(name))
_, err := w.Write(d)
if err != nil {
lg.Warnf("/api/template/save error: %s", err)
return
}
s.Store.Save(WebTemplateStorePath)
}
func (s *WebInfoServer) getInfo(w http.ResponseWriter, r *http.Request) { func (s *WebInfoServer) getInfo(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Origin", "*")

View File

@@ -19,13 +19,14 @@ type TemplateStore struct {
func newTemplateStore(filename string) *TemplateStore { func newTemplateStore(filename string) *TemplateStore {
s := &TemplateStore{Templates: map[string]*WebTemplate{}} s := &TemplateStore{Templates: map[string]*WebTemplate{}}
var templates []WebTemplate var templates []*WebTemplate
file, err := ioutil.ReadFile(filename) file, err := ioutil.ReadFile(filename)
if err == nil { if err == nil {
_ = json.Unmarshal(file, &templates) _ = json.Unmarshal(file, &templates)
} }
for _, tmpl := range templates { for _, tmpl := range templates {
s.Templates[tmpl.Name] = &tmpl s.Templates[tmpl.Name] = tmpl
} }
return s return s
} }

View File

@@ -9,12 +9,13 @@ func TestTemplateStore_Create(t *testing.T) {
s := newTemplateStore(WebTemplateStorePath) s := newTemplateStore(WebTemplateStorePath)
s.Get("A") s.Get("A")
s.Get("B") s.Get("B")
s.Modify("A", "123123") s.Modify("A", "33333")
s.Save(WebTemplateStorePath) s.Save(WebTemplateStorePath)
} }
func TestTemplateStore_Load(t *testing.T) { func TestTemplateStore_Load(t *testing.T) {
s := newTemplateStore(WebTemplateStorePath) s := newTemplateStore(WebTemplateStorePath)
fmt.Println(s.List())
for name, tmpl := range s.Templates { for name, tmpl := range s.Templates {
fmt.Println(name, tmpl.Template) fmt.Println(name, tmpl.Template)
} }

View File

@@ -7,7 +7,6 @@
- web输出 (前端) - web输出 (前端)
- 进入beta版本
beta beta
- web 重连 - web 重连
@@ -17,6 +16,7 @@ beta
---- ----
Finished Finished
- 2022.7.18@0.9.0: Fix bug/网页第二版跟新,加入自定义模板/修复图片加载不出来导致的闪退bug
- 2022.7.18 : Fix bug - 2022.7.18 : Fix bug
- 2022.7.16@0.8.6: 网页输出第一版更新/修复历史列表部分歌曲放不出来的bug/修复部分歌词不更新 - 2022.7.16@0.8.6: 网页输出第一版更新/修复历史列表部分歌曲放不出来的bug/修复部分歌词不更新
- 2022.7.15: 更新stderr重定向/添加logo/ - 2022.7.15: 更新stderr重定向/添加logo/

14
webtemplates.json Normal file
View File

@@ -0,0 +1,14 @@
[
{
"Name": "时间例子",
"Template": "<p><media-title /></p>\r\n\r\n<p>秒显示:<current-time />/<total-time /></p>\r\n\r\n<p>\r\n分秒显示: \r\n<current-time format=\"m:s\"/>\r\n/\r\n<total-time format=\"m:s\"/>\r\n</p>\r\n"
},
{
"Name": "播放列表例子",
"Template": "<p>默认</p>\r\n<playlist-container></playlist-container>\r\n<p>自定义格式</p>\r\n<playlist-container>\r\n <template v-slot=\"v\">\r\n <p>序号: <playlist-index :index=\"v.index\"></playlist-index></p>\r\n <p>\r\n 歌名: <playlist-title :index=\"v.index\"></playlist-title>\r\n </p>\r\n <p>\r\n 歌手: <playlist-artist :index=\"v.index\"></playlist-artist>\r\n </p>\r\n <p>\r\n 专辑名: <playlist-album :index=\"v.index\"></playlist-album>\r\n </p>\r\n <p>\r\n 点歌用户: <playlist-username :index=\"v.index\"></playlist-username>\r\n </p>\r\n </template>\r\n </playlist-container>"
},
{
"Name": "default",
"Template": " <div>\r\n <div class=\"current-playing\">\r\n <media-title></media-title>\r\n ---\r\n <media-artist></media-artist>\r\n ---\r\n <media-username></media-username>\r\n </div>"
}
]