Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
3e31f8822e
|
|||
|
6cff4247a8
|
|||
|
90ff1382a8
|
|||
|
1450357b91
|
|||
|
7a31c36c10
|
|||
|
5271c12525
|
26
.drone.yml
26
.drone.yml
@@ -2,9 +2,6 @@ kind: pipeline
|
|||||||
type: docker
|
type: docker
|
||||||
name: default
|
name: default
|
||||||
|
|
||||||
clone:
|
|
||||||
depth: 1
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: frontend-web
|
- name: frontend-web
|
||||||
image: node:19
|
image: node:19
|
||||||
@@ -13,22 +10,9 @@ steps:
|
|||||||
- npm install
|
- npm install
|
||||||
- npm run build
|
- npm run build
|
||||||
|
|
||||||
- name: backend
|
- name: release
|
||||||
image: golang:1.19
|
image: plugins/gitea-release
|
||||||
commands:
|
|
||||||
- go build -v .
|
|
||||||
environment:
|
|
||||||
CGO_ENABLED: 0
|
|
||||||
GOPROXY: goproxy.cn
|
|
||||||
|
|
||||||
- name: upload
|
|
||||||
image: plugins/s3-sync
|
|
||||||
settings:
|
settings:
|
||||||
bucket: msw-artifacts-public
|
api_key: da966507c259aa32ccc2d434e930af4a580de785
|
||||||
region: ap-southeast-1
|
base_url: https://yongyuancv.cn/git/
|
||||||
access_key:
|
files: build/*
|
||||||
from_secret: access_key
|
|
||||||
secret_key:
|
|
||||||
from_secret: secret_key
|
|
||||||
source: msw-open-music
|
|
||||||
target: /msw-open-music/${DRONE_COMMIT}/
|
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -4,7 +4,7 @@ web:
|
|||||||
cd web && npm run build
|
cd web && npm run build
|
||||||
|
|
||||||
linux:
|
linux:
|
||||||
CGO_ENABLED=0 go build -v -ldflags '-extldflags=-static'
|
go build -v -ldflags '-linkmode=external -extldflags=-static' -tags sqlite_omit_load_extension,netgo
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
CC=x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build -v
|
CC=x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build -v
|
||||||
|
|||||||
14
main.go
14
main.go
@@ -1,10 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"io/fs"
|
|
||||||
"log"
|
"log"
|
||||||
"msw-open-music/pkg/api"
|
"msw-open-music/pkg/api"
|
||||||
"msw-open-music/pkg/commonconfig"
|
"msw-open-music/pkg/commonconfig"
|
||||||
@@ -17,21 +15,11 @@ func init() {
|
|||||||
flag.StringVar(&ConfigFilePath, "config", "config.json", "backend config file path")
|
flag.StringVar(&ConfigFilePath, "config", "config.json", "backend config file path")
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed web/build
|
|
||||||
var WEBFILES embed.FS
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var err error
|
var err error
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
WEBFS, err := fs.Sub(WEBFILES, "web/build")
|
config := commonconfig.Config{}
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
config := commonconfig.Config{
|
|
||||||
WEBFS: WEBFS,
|
|
||||||
}
|
|
||||||
configFile, err := os.Open(ConfigFilePath)
|
configFile, err := os.Open(ConfigFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/gorilla/sessions"
|
||||||
"msw-open-music/pkg/commonconfig"
|
"msw-open-music/pkg/commonconfig"
|
||||||
"msw-open-music/pkg/database"
|
"msw-open-music/pkg/database"
|
||||||
"msw-open-music/pkg/tmpfs"
|
"msw-open-music/pkg/tmpfs"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gorilla/sessions"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
@@ -104,7 +103,7 @@ func NewAPI(config commonconfig.Config) (*API, error) {
|
|||||||
apiMux.HandleFunc("/reset", api.HandleReset)
|
apiMux.HandleFunc("/reset", api.HandleReset)
|
||||||
|
|
||||||
mux.Handle("/api/v1/", http.StripPrefix("/api/v1", api.PermissionMiddleware(apiMux)))
|
mux.Handle("/api/v1/", http.StripPrefix("/api/v1", api.PermissionMiddleware(apiMux)))
|
||||||
mux.Handle("/", http.StripPrefix("/", http.FileServer(http.FS(config.WEBFS))))
|
mux.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir("web/build"))))
|
||||||
|
|
||||||
return api, nil
|
return api, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
package commonconfig
|
package commonconfig
|
||||||
|
|
||||||
import "io/fs"
|
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
APIConfig APIConfig `json:"api"`
|
APIConfig APIConfig `json:"api"`
|
||||||
TmpfsConfig TmpfsConfig `json:"tmpfs"`
|
TmpfsConfig TmpfsConfig `json:"tmpfs"`
|
||||||
WEBFS fs.FS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type APIConfig struct {
|
type APIConfig struct {
|
||||||
|
|||||||
20
web/build.js
20
web/build.js
@@ -1,20 +0,0 @@
|
|||||||
const fs = require("fs");
|
|
||||||
const esbuild = require("esbuild");
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
fs.rmSync("build", { recursive: true, force: true });
|
|
||||||
fs.cpSync("public", "build", { recursive: true });
|
|
||||||
|
|
||||||
const result = await esbuild.build({
|
|
||||||
entryPoints: ["src/index.jsx"],
|
|
||||||
bundle: true,
|
|
||||||
outfile: "build/msw-open-music.js",
|
|
||||||
sourcemap: true,
|
|
||||||
minify: true,
|
|
||||||
metafile: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const text = await esbuild.analyzeMetafile(result.metafile);
|
|
||||||
console.log(text);
|
|
||||||
console.log("Build done, output files udner ./build directory");
|
|
||||||
})();
|
|
||||||
6
web/build.sh
Executable file
6
web/build.sh
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
rm -rf build
|
||||||
|
cp -raf public build
|
||||||
|
./node_modules/.bin/esbuild src/index.jsx --bundle --outfile=build/msw-open-music.js --alias:react=preact/compat --alias:react-dom=preact/compat --minify --analyze
|
||||||
|
cat public/index.html | sed "s/%PUBLIC_URL%/$PUBLIC_URL/" > build/index.html
|
||||||
|
|
||||||
|
echo "Build done, output files under ./build directory"
|
||||||
@@ -9,6 +9,6 @@
|
|||||||
"water.css": "^2.1.1"
|
"water.css": "^2.1.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node build.js"
|
"build": "bash ./build.sh"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,18 +2,18 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="./favicon.png" />
|
<link rel="icon" href="%PUBLIC_URL%/favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="description" content="Personal music streaming platform" />
|
<meta name="description" content="Personal music streaming platform" />
|
||||||
<link rel="apple-touch-icon" href="./favicon.png" />
|
<link rel="apple-touch-icon" href="%PUBLIC_URL%/favicon.png" />
|
||||||
<link rel="manifest" href="./manifest.json" />
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
<link rel="stylesheet" href="./msw-open-music.css" />
|
<link rel="stylesheet" href="%PUBLIC_URL%/msw-open-music.css" />
|
||||||
<meta name="mobile-web-app-capable" content="yes" />
|
<meta name="mobile-web-app-capable" content="yes" />
|
||||||
<title>MSW Open Music</title>
|
<title>MSW Open Music</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<script type="module" src="./msw-open-music.js"></script>
|
<script type="module" src="%PUBLIC_URL%/msw-open-music.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
|
html {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: auto;
|
||||||
|
padding-top: 1rem;
|
||||||
|
max-width: unset;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
#root {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
.base {
|
.base {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-row-gap: 1em;
|
grid-row-gap: 1em;
|
||||||
@@ -35,10 +48,54 @@
|
|||||||
color: rgb(229, 232, 245);
|
color: rgb(229, 232, 245);
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
|
a.unset {
|
||||||
|
color: unset;
|
||||||
|
text-decoration: unset;
|
||||||
|
}
|
||||||
|
a.active {
|
||||||
|
color: deeppink;
|
||||||
|
background-color: lightgray;
|
||||||
|
border-radius: 0.39em 0.39em 0 0;
|
||||||
|
}
|
||||||
.audio-player {
|
.audio-player {
|
||||||
height: 39px;
|
height: 39px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
td.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
div.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
div.page {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
div.search_toolbar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: flex-end;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
div.feedback {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
button.refresh {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
td,
|
||||||
|
th {
|
||||||
|
padding-bottom: 0.5em;
|
||||||
|
padding-top: 0.5em;
|
||||||
|
}
|
||||||
|
dialog {
|
||||||
|
border: solid;
|
||||||
|
}
|
||||||
.player-options {
|
.player-options {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,66 +1,13 @@
|
|||||||
#root {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
html {
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
body {
|
body {
|
||||||
margin: auto;
|
margin: 0;
|
||||||
padding-top: 1rem;
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
max-width: none;
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||||
min-height: 100vh;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
|
|
||||||
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
|
||||||
sans-serif;
|
sans-serif;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
|
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||||
monospace;
|
monospace;
|
||||||
}
|
}
|
||||||
a.unset {
|
|
||||||
color: unset;
|
|
||||||
text-decoration: unset;
|
|
||||||
}
|
|
||||||
a.active {
|
|
||||||
color: deeppink;
|
|
||||||
background-color: lightgray;
|
|
||||||
border-radius: 0.39em 0.39em 0 0;
|
|
||||||
}
|
|
||||||
td.clickable {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
div.clickable {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
div.page {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
div.search_toolbar {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: flex-end;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
div.feedback {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
button.refresh {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
td,
|
|
||||||
th {
|
|
||||||
padding-bottom: 0.5em;
|
|
||||||
padding-top: 0.5em;
|
|
||||||
}
|
|
||||||
dialog {
|
|
||||||
border: solid;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import 'water.css';
|
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
import 'water.css';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
|
|||||||
Reference in New Issue
Block a user