mirror of
https://github.com/pldubouilh/gossa.git
synced 2026-08-30 22:06:46 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c517f7b7e1 | ||
|
|
3ff1c03d5f |
@@ -6,6 +6,7 @@ build:
|
|||||||
embed:
|
embed:
|
||||||
echo "embedding css and js into binary"
|
echo "embedding css and js into binary"
|
||||||
cp src/main.go gossa.go
|
cp src/main.go gossa.go
|
||||||
|
perl -pe 's/template_will_be_here/`cat src\/page.tmpl`/ge' -i gossa.go
|
||||||
perl -pe 's/css_will_be_here/`cat src\/style.css`/ge' -i gossa.go
|
perl -pe 's/css_will_be_here/`cat src\/style.css`/ge' -i gossa.go
|
||||||
perl -pe 's/js_will_be_here/`cat src\/script.js`/ge' -i gossa.go
|
perl -pe 's/js_will_be_here/`cat src\/script.js`/ge' -i gossa.go
|
||||||
perl -pe 's/favicon_will_be_here/`base64 -w0 src\/favicon.png`/ge' -i gossa.go
|
perl -pe 's/favicon_will_be_here/`base64 -w0 src\/favicon.png`/ge' -i gossa.go
|
||||||
@@ -20,7 +21,7 @@ ci:
|
|||||||
cd src && sleep 5 && go test
|
cd src && sleep 5 && go test
|
||||||
|
|
||||||
ci-watch:
|
ci-watch:
|
||||||
ls src/* | entr -rc make ci
|
ls src/* | entr -rc make ci
|
||||||
|
|
||||||
watch:
|
watch:
|
||||||
ls src/* | entr -rc make run
|
ls src/* | entr -rc make run
|
||||||
|
|||||||
+38
-61
@@ -6,6 +6,7 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html"
|
"html"
|
||||||
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
@@ -21,14 +22,23 @@ var host = flag.String("h", "127.0.0.1", "host to listen to")
|
|||||||
var port = flag.String("p", "8001", "port to listen to")
|
var port = flag.String("p", "8001", "port to listen to")
|
||||||
var verb = flag.Bool("verb", true, "verbosity")
|
var verb = flag.Bool("verb", true, "verbosity")
|
||||||
var skipHidden = flag.Bool("k", true, "skip hidden files")
|
var skipHidden = flag.Bool("k", true, "skip hidden files")
|
||||||
|
|
||||||
var initPath = ""
|
var initPath = ""
|
||||||
var css = `css_will_be_here` // js will be embedded here
|
|
||||||
var js = `js_will_be_here` // id. css
|
|
||||||
var favicon = "data:image/png;base64,favicon_will_be_here" // id. b64 favicon
|
|
||||||
var units = [8]string{"k", "M", "G", "T", "P", "E", "Z", "Y"}
|
|
||||||
|
|
||||||
var fs http.Handler
|
var fs http.Handler
|
||||||
|
var page, _ = template.New("pageTemplate").Parse(`template_will_be_here`)
|
||||||
|
|
||||||
|
type rowTemplate struct {
|
||||||
|
Name string
|
||||||
|
Href template.HTML
|
||||||
|
Size string
|
||||||
|
Ext string
|
||||||
|
}
|
||||||
|
|
||||||
|
type pageTemplate struct {
|
||||||
|
Title template.HTML
|
||||||
|
RowsFiles []rowTemplate
|
||||||
|
RowsFolders []rowTemplate
|
||||||
|
}
|
||||||
|
|
||||||
type rpcCall struct {
|
type rpcCall struct {
|
||||||
Call string `json:"call"`
|
Call string `json:"call"`
|
||||||
@@ -47,84 +57,52 @@ func logVerb(s ...interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sizeToString(bytes float64) string {
|
func sizeToString(bytes int64) string {
|
||||||
if bytes == 0 {
|
units := [9]string{"B", "k", "M", "G", "T", "P", "E", "Z", "Y"}
|
||||||
return "0"
|
b := float64(bytes)
|
||||||
}
|
u := 0
|
||||||
var u = -1
|
|
||||||
for {
|
for {
|
||||||
bytes = bytes / 1024
|
if b < 1024 {
|
||||||
u++
|
return strconv.FormatFloat(b, 'f', 1, 64) + units[u]
|
||||||
if bytes < 1024 {
|
|
||||||
return strconv.FormatFloat(bytes, 'f', 1, 64) + units[u]
|
|
||||||
}
|
}
|
||||||
|
b = b / 1024
|
||||||
|
u++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func row(name string, href string, size float64, ext string) string {
|
|
||||||
if strings.HasPrefix(href, "/") {
|
|
||||||
href = strings.Replace(href, "/", "", 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return `<tr>
|
|
||||||
<td><i ondblclick="return rm(event)" onclick="return rename(event)" class="btn icon icon-` + strings.ToLower(ext) + ` icon-blank"></i></td>
|
|
||||||
<td class="file-size"><code>` + sizeToString(size) + `</code></td>
|
|
||||||
<td class="arrow"><i class="arrow-icon"></i></td>
|
|
||||||
<td class="display-name"><a class="list-links" onclick="return onClickLink(event)" href="` + url.PathEscape(href) + `">` + name + `</a></td>
|
|
||||||
</tr>`
|
|
||||||
}
|
|
||||||
|
|
||||||
func replyList(w http.ResponseWriter, path string) {
|
func replyList(w http.ResponseWriter, path string) {
|
||||||
if !strings.HasSuffix(path, "/") {
|
if !strings.HasSuffix(path, "/") {
|
||||||
path += "/"
|
path += "/"
|
||||||
}
|
}
|
||||||
|
|
||||||
var head = `<!doctype html><html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width">
|
|
||||||
<title>` + html.EscapeString(path) + `</title>
|
|
||||||
<link href="` + favicon + `" rel="icon" type="image/png"/>
|
|
||||||
<script>window.onload = function(){` + js + `}</script>
|
|
||||||
<style type="text/css">` + css + `</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="drop-grid"> Drop here to upload </div>
|
|
||||||
<h1>.` + html.EscapeString(path) + `</h1>
|
|
||||||
<div class="icHolder"><div style="display:none;" class="ic icon-large-images" onclick="window.picsToggle()"></div>
|
|
||||||
<div class="ic icon-large-folder" onclick="window.mkdirBtn()"></div></div>
|
|
||||||
<div id="pics" style="display:none;"> <div onclick="window.picsToggle()" id="picsToggleCinema"></div> <img onclick="window.picsNav()" id="picsHolder"/> <span id="picsLabel"></span> </div>
|
|
||||||
<table>`
|
|
||||||
|
|
||||||
_files, err := ioutil.ReadDir(initPath + path)
|
_files, err := ioutil.ReadDir(initPath + path)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
|
p := pageTemplate{}
|
||||||
if path != "/" {
|
if path != "/" {
|
||||||
head += row("../", "../", 0, "folder")
|
p.RowsFolders = append(p.RowsFolders, rowTemplate{"../", "../", "", "folder"})
|
||||||
}
|
}
|
||||||
|
|
||||||
var dirs = ""
|
|
||||||
var files = ""
|
|
||||||
|
|
||||||
for _, el := range _files {
|
for _, el := range _files {
|
||||||
var name = el.Name()
|
name := el.Name()
|
||||||
|
href := url.PathEscape(name)
|
||||||
if *skipHidden && strings.HasPrefix(name, ".") {
|
if *skipHidden && strings.HasPrefix(name, ".") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if el.IsDir() && strings.HasPrefix(href, "/") {
|
||||||
|
href = strings.Replace(href, "/", "", 1)
|
||||||
|
}
|
||||||
if el.IsDir() {
|
if el.IsDir() {
|
||||||
dirs += row(name+"/", name, 0, "folder")
|
p.RowsFolders = append(p.RowsFolders, rowTemplate{name + "/", template.HTML(href), "", "folder"})
|
||||||
} else {
|
} else {
|
||||||
var sl = strings.Split(name, ".")
|
sl := strings.Split(name, ".")
|
||||||
var ext = sl[len(sl)-1]
|
ext := strings.ToLower(sl[len(sl)-1])
|
||||||
files += row(name, name, float64(el.Size()), ext)
|
p.RowsFiles = append(p.RowsFiles, rowTemplate{name, template.HTML(href), sizeToString(el.Size()), ext})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Write([]byte(head + dirs + files + `</table>
|
p.Title = template.HTML(html.EscapeString(path))
|
||||||
<br><address><a href="https://github.com/pldubouilh/gossa">Gossa 🎶</a></address>
|
page.Execute(w, p)
|
||||||
<div id="progress" style="display:none;"><span id="dlBarName"></span><div id="dlBarPc">1%</div></div>
|
|
||||||
</body></html>`))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func doContent(w http.ResponseWriter, r *http.Request) {
|
func doContent(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -206,7 +184,6 @@ func checkPath(p string) (string, error) {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if len(flag.Args()) == 0 {
|
if len(flag.Args()) == 0 {
|
||||||
initPath = "."
|
initPath = "."
|
||||||
} else {
|
} else {
|
||||||
@@ -217,11 +194,11 @@ func main() {
|
|||||||
initPath, err = filepath.Abs(initPath)
|
initPath, err = filepath.Abs(initPath)
|
||||||
check(err)
|
check(err)
|
||||||
|
|
||||||
var hostString = *host + ":" + *port
|
hostString := *host + ":" + *port
|
||||||
fmt.Println("Gossa startig on directory " + initPath)
|
fmt.Println("Gossa startig on directory " + initPath)
|
||||||
fmt.Println("Listening on http://" + hostString)
|
fmt.Println("Listening on http://" + hostString)
|
||||||
|
|
||||||
var root = http.Dir(initPath)
|
root := http.Dir(initPath)
|
||||||
fs = http.StripPrefix("/", http.FileServer(root))
|
fs = http.StripPrefix("/", http.FileServer(root))
|
||||||
|
|
||||||
http.HandleFunc("/rpc", rpc)
|
http.HandleFunc("/rpc", rpc)
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
<title>{{.Title}}</title>
|
||||||
|
<link href="data:image/png;base64,favicon_will_be_here" rel="icon" type="image/png" />
|
||||||
|
<script>window.onload = function () { js_will_be_here }</script>
|
||||||
|
<style type="text/css">css_will_be_here</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="drop-grid"> Drop here to upload </div>
|
||||||
|
|
||||||
|
<h1>.{{.Title}}</h1>
|
||||||
|
|
||||||
|
<div class="icHolder">
|
||||||
|
<div style="display:none;" class="ic icon-large-images" onclick="window.picsToggle()"></div>
|
||||||
|
<div class="ic icon-large-folder" onclick="window.mkdirBtn()"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="pics" style="display:none;">
|
||||||
|
<div onclick="window.picsToggle()" id="picsToggleCinema"></div> <img onclick="window.picsNav()" id="picsHolder" />
|
||||||
|
<span id="picsLabel"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
{{range .RowsFolders}}
|
||||||
|
<tr>
|
||||||
|
<td><i ondblclick="return rm(event)" onclick="return rename(event)" class="btn icon icon-{{.Ext}} icon-blank"></i></td>
|
||||||
|
<td class="file-size"><code>{{.Size}}</code></td>
|
||||||
|
<td class="arrow"><i class="arrow-icon"></i></td>
|
||||||
|
<td class="display-name"><a class="list-links" onclick="return onClickLink(event)" href="{{.Href}}">{{.Name}}</a></td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
{{range .RowsFiles}}
|
||||||
|
<tr>
|
||||||
|
<td><i ondblclick="return rm(event)" onclick="return rename(event)" class="btn icon icon-{{.Ext}} icon-blank"></i></td>
|
||||||
|
<td class="file-size"><code>{{.Size}}</code></td>
|
||||||
|
<td class="arrow"><i class="arrow-icon"></i></td>
|
||||||
|
<td class="display-name"><a class="list-links" onclick="return onClickLink(event)" href="{{.Href}}">{{.Name}}</a></td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div id="progress" style="display:none;">
|
||||||
|
<span id="dlBarName"></span>
|
||||||
|
<div id="dlBarPc">1%</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
+20
-5
@@ -163,6 +163,11 @@ const setBackgroundLinks = t => { t.style.backgroundColor = 'rgba(123, 123, 123,
|
|||||||
|
|
||||||
const getLink = e => e.target.parentElement.querySelectorAll('a.list-links')[0]
|
const getLink = e => e.target.parentElement.querySelectorAll('a.list-links')[0]
|
||||||
|
|
||||||
|
upGrid.ondragleave = e => {
|
||||||
|
cancelDefault(e)
|
||||||
|
upGrid.style.display = 'none'
|
||||||
|
}
|
||||||
|
|
||||||
document.ondragenter = e => {
|
document.ondragenter = e => {
|
||||||
if (isPicMode()) { return }
|
if (isPicMode()) { return }
|
||||||
cancelDefault(e)
|
cancelDefault(e)
|
||||||
@@ -181,10 +186,7 @@ document.ondragenter = e => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
upGrid.ondragleave = e => {
|
document.ondragend = e => resetBackgroundLinks()
|
||||||
cancelDefault(e)
|
|
||||||
upGrid.style.display = 'none'
|
|
||||||
}
|
|
||||||
|
|
||||||
document.ondragover = e => {
|
document.ondragover = e => {
|
||||||
cancelDefault(e)
|
cancelDefault(e)
|
||||||
@@ -365,6 +367,16 @@ function onPaste () {
|
|||||||
mvCall(root, dest + filename, onPaste)
|
mvCall(root, dest + filename, onPaste)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dark mode
|
||||||
|
const darkMode = 'html, a { background-color: #2d3436; color: #dfe6e9; } .arrow, .icon-large-images { filter: invert(100%) !important; }'
|
||||||
|
const extraCss = document.createElement('style')
|
||||||
|
document.body.appendChild(extraCss);
|
||||||
|
|
||||||
|
const currentMode = () => localStorage.getItem('colorMode')
|
||||||
|
const setMode = () => { extraCss.innerHTML = currentMode() === 'dark' ? darkMode : '' }
|
||||||
|
const toggleBWMode = () => localStorage.setItem('colorMode', currentMode() === 'dark' ? 'white' : 'dark') || setMode()
|
||||||
|
setMode()
|
||||||
|
|
||||||
// Kb handler
|
// Kb handler
|
||||||
let typedPath = ''
|
let typedPath = ''
|
||||||
let typedToken = null
|
let typedToken = null
|
||||||
@@ -402,7 +414,7 @@ document.body.addEventListener('keydown', e => {
|
|||||||
return prevent(e) || picsNav(false) || prevPage()
|
return prevent(e) || picsNav(false) || prevPage()
|
||||||
|
|
||||||
case 'Escape':
|
case 'Escape':
|
||||||
return prevent(e) || picsOff()
|
return prevent(e) || resetBackgroundLinks() || picsOff()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ctrl keys
|
// Ctrl keys
|
||||||
@@ -426,6 +438,9 @@ document.body.addEventListener('keydown', e => {
|
|||||||
|
|
||||||
case 'KeyD':
|
case 'KeyD':
|
||||||
return prevent(e) || isPicMode() || window.mkdirBtn()
|
return prevent(e) || isPicMode() || window.mkdirBtn()
|
||||||
|
|
||||||
|
case 'KeyB':
|
||||||
|
return prevent(e) || toggleBWMode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-4
@@ -1,3 +1,9 @@
|
|||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: transparent !important;
|
||||||
|
/* border-bottom: .01em solid #dfe6e9; */
|
||||||
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
display: block;
|
display: block;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
@@ -75,7 +81,6 @@ h1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#progress {
|
#progress {
|
||||||
background-color: white;
|
|
||||||
width: 99%;
|
width: 99%;
|
||||||
left: 0.5%;
|
left: 0.5%;
|
||||||
right: 0.5%;
|
right: 0.5%;
|
||||||
@@ -83,7 +88,6 @@ h1 {
|
|||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
max-height: 50%;
|
max-height: 50%;
|
||||||
overflow-y: scroll;
|
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,10 +122,9 @@ h1 {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 4em;
|
font-size: 4em;
|
||||||
font-family: Helvetica;
|
font-family: Helvetica;
|
||||||
background-color: white;
|
|
||||||
color: green;
|
color: green;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
backdrop-filter: grayscale(100%);
|
background-color: rgba(123, 123, 123, 0.2)
|
||||||
}
|
}
|
||||||
|
|
||||||
#pics {
|
#pics {
|
||||||
|
|||||||
Reference in New Issue
Block a user