diff --git a/res/include/md/about.md b/res/include/md/about.md index 847353c..77c8943 100644 --- a/res/include/md/about.md +++ b/res/include/md/about.md @@ -26,16 +26,12 @@ spare some coins. Possible methods for donating are: * Bitcoin: [1Ne7hGuvnfz9EFTRD3PLWVeaJTX9oA1QUr](bitcoin:1Ne7hGuvnfz9EFTRD3PLWVeaJTX9oA1QUr?label=Pixeldrain%20Donation) * BasicAttentionToken: Donate BAT by clicking the BAT icon in your address bar. - If you don't have Brave browser yet you can download it here: Install Brave. Installing and using Brave with this - referral link also counts as a 5$ donation. + Learn more about Brave browser. * Siacoin: 26117c19ca3975b315d663dcbbc19cf9c07274f441689d4392ed380b2337589ef1aacfbdc93f (this address points directly at the storage backend. Donations will be used for paying storage contracts with Sia hosts) - * PayPal: + * Donate with PayPal ## How does pixeldrain store files? diff --git a/res/include/md/brave.md b/res/include/md/brave.md new file mode 100644 index 0000000..269b619 --- /dev/null +++ b/res/include/md/brave.md @@ -0,0 +1,53 @@ +# About Brave and Pixeldrain + +## What is Brave? + +Brave is a web browser focused on privacy and speed. In some tests Brave is up +to 3 times faster than Chrome and Firefox. It does this by blocking +advertisements and tracking scripts before they even get a chance to load. +Beside the speed improvements this also saves a lot of power and data, very +useful for mobile phones. + +Websites look much cleaner without all those advertisements. I don't like +putting ads on pixeldrain either, but I need the money to keep the website +running. Brave tries to solve this by giving users the choice if they want to +see ads. If you opt in to seeing ads from Brave you will receive notifications +with promotional offers once in a while. Brave protects your privacy by putting +the logic for showing relevant ads directly in the browser itself. This way your +browser history never leaves your computer and Google can't follow you around +the web. The earnings from these ads are distributed between the websites which +you love most, a small cut goes to Brave itself for developing the browser, and +some of it goes to you. That's right, you get paid for viewing ads! + +## Basic attention tokens + + + +The money that you get from viewing ads (and receiving free token grants) goes +into a cryptocurrency wallet which is built right into the browser. Once you +have earned some rewards you have a few options. You can choose to automatically +distribute them between websites which you spend the most time on, you can tip +your favourite websites by pressing the tip button in the address bar or you can +convert the money to your own currency and deposit it to your bank account. + +Of course I would really appreciate it if you tipped some coins to pixeldrain +once in a while ;-) + +
+ +When you install the Brave browser and use it for 30 days they will make a +contribution of around 5$ to pixeldrain. This is currently the site's +biggest source of income. It allows me to get faster servers in more places and +spend more time working on the site. So, if you're ready: + +
+ + + Get started with Brave + +
+ +If you want to learn more about Brave and its goals I can recommend checking out +the [blog](https://brave.com/blog). If you want to get in touch there is also +the [community forum](https://community.brave.com) and a [reddit +forum](https://www.reddit.com/r/brave_browser). diff --git a/res/include/script/admin.js b/res/include/script/admin.js index 1ee1d1e..5d48209 100644 --- a/res/include/script/admin.js +++ b/res/include/script/admin.js @@ -187,6 +187,13 @@ function getStats(order) { resp.stats_watcher_listeners / resp.stats_watcher_threads ).toPrecision(3); + document.getElementById("cache_files").innerText = resp.cache_files; + document.getElementById("cache_size").innerText = formatDataVolume(resp.cache_size_total, 3); + document.getElementById("cache_max").innerText = formatDataVolume(resp.cache_size_max, 3); + document.getElementById("cache_reads").innerText = resp.cache_reads; + document.getElementById("disk_reads").innerText = resp.disk_reads; + document.getElementById("remote_reads").innerText = resp.remote_reads; + let c = document.getElementById("tconnstat_body") c.innerHTML = "" resp.db_connection_stats.forEach(v => { diff --git a/res/include/script/file_manager/DirectoryElement.js b/res/include/script/file_manager/DirectoryElement.js index 7c46c67..9efbe53 100644 --- a/res/include/script/file_manager/DirectoryElement.js +++ b/res/include/script/file_manager/DirectoryElement.js @@ -189,7 +189,7 @@ DirectoryElement.prototype.createFileButton = function(file, index) { let el = document.createElement("a") el.classList = "node" el.href = file.href - // el.target = "_blank" + el.target = "_blank" el.title = file.name el.setAttribute("fileindex", index) diff --git a/res/include/style/layout.css b/res/include/style/layout.css index 39f69b7..922ea36 100644 --- a/res/include/style/layout.css +++ b/res/include/style/layout.css @@ -56,7 +56,7 @@ body{ background-repeat: repeat; margin: 0; font-family: system-ui, sans-serif; - line-height: 1.5em; + line-height: 1.8em; color: #b2b2b2; /* Fallback */ color: var(--text_color); padding: 0; diff --git a/res/static/img/bat_full_color.svg b/res/static/img/bat_full_color.svg new file mode 100644 index 0000000..c226561 --- /dev/null +++ b/res/static/img/bat_full_color.svg @@ -0,0 +1,19 @@ + + + + bat/logo-full-color + Created with Sketch. + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/static/img/bat_wallet.png b/res/static/img/bat_wallet.png new file mode 100644 index 0000000..c511690 Binary files /dev/null and b/res/static/img/bat_wallet.png differ diff --git a/res/static/img/brave_lion.svg b/res/static/img/brave_lion.svg new file mode 100644 index 0000000..f80dbc3 --- /dev/null +++ b/res/static/img/brave_lion.svg @@ -0,0 +1,33 @@ + + + + build-icons/Stable Copy 3 + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/static/img/brave_lion_alt.png b/res/static/img/brave_lion_alt.png new file mode 100644 index 0000000..49acd7a Binary files /dev/null and b/res/static/img/brave_lion_alt.png differ diff --git a/res/static/img/mime/folder-remote.png b/res/static/img/mime/folder-remote.png new file mode 100644 index 0000000..805adfc Binary files /dev/null and b/res/static/img/mime/folder-remote.png differ diff --git a/res/static/img/mime/folder.png b/res/static/img/mime/folder.png new file mode 100644 index 0000000..ce5909e Binary files /dev/null and b/res/static/img/mime/folder.png differ diff --git a/res/static/img/misc/brave-728x90.png b/res/static/img/misc/brave-728x90.png new file mode 100644 index 0000000..3954c2c Binary files /dev/null and b/res/static/img/misc/brave-728x90.png differ diff --git a/res/template/admin.html b/res/template/admin.html index f3b684b..58895e5 100644 --- a/res/template/admin.html +++ b/res/template/admin.html @@ -81,6 +81,29 @@ +

Pixelstore stats

+ + + + + + + + + + + + + + + + + + + + + +
Cache filesCache sizeMax cache size
Cache readsDisk readsRemote reads

Websocket statistics

diff --git a/res/template/file_viewer.html b/res/template/file_viewer.html index 52af8cb..1406c99 100644 --- a/res/template/file_viewer.html +++ b/res/template/file_viewer.html @@ -166,6 +166,10 @@
{{ else if eq .Other.AdType 7}} + {{ else if eq .Other.AdType 8}} + + + {{end}} {{ else if not .Other.UserAdsEnabled }}
diff --git a/res/template/filesystem.html b/res/template/filesystem.html new file mode 100644 index 0000000..c1b324c --- /dev/null +++ b/res/template/filesystem.html @@ -0,0 +1,37 @@ +{{ define "filesystem" }} + + + {{template "meta_tags" .Title}} + {{template "user_style" .}} + + + + + + {{template "page_top" .}} + +

{{ .Title}}

+ +
+
+

+ Buckets + {{ range $node := .Other.Path }} + / {{ $node.Name }} + {{ end }} +

+ + {{ range $node := .Other.Children }} +
+ + {{ $node.Name }} +
+ {{ end }} +
+
+ + {{template "page_bottom" .}} + {{template "analytics"}} + + +{{ end }} diff --git a/res/template/home.html b/res/template/home.html index d3cde0f..661b2ef 100644 --- a/res/template/home.html +++ b/res/template/home.html @@ -28,6 +28,7 @@ .big_number { font-size: 24px; font-weight: bold; + line-height: 1em; text-align: center; display: block; box-sizing: border-box; @@ -107,7 +108,6 @@
-
1Select files to upload You can also drop files anywhere on this page from your file diff --git a/webcontroller/file_viewer.go b/webcontroller/file_viewer.go index a93b0af..a791420 100644 --- a/webcontroller/file_viewer.go +++ b/webcontroller/file_viewer.go @@ -44,6 +44,7 @@ func adType() (i int) { adMaven = 5 mediaNet = 6 revenueHits = 7 + brave = 8 ) switch i { @@ -53,11 +54,8 @@ func adType() (i int) { case 2: return adMaven - case 3: - return mediaNet - - case 4: - return revenueHits + case 3, 4: + return brave default: panic(fmt.Errorf( diff --git a/webcontroller/filesystem.go b/webcontroller/filesystem.go new file mode 100644 index 0000000..661a49c --- /dev/null +++ b/webcontroller/filesystem.go @@ -0,0 +1,116 @@ +package webcontroller + +import ( + "net/http" + "sort" + "strings" + + "fornaxian.tech/pixeldrain_server/api/restapi/apitype" + "github.com/Fornaxian/log" + "github.com/julienschmidt/httprouter" +) + +type filesystemPath struct { + Path []filesystemNode + Children []filesystemNode +} + +type filesystemNode struct { + HREF string + Icon string + Name string + Type string + FileSize int64 + FileType string +} + +func convFilesystemNode(bucketID string, v apitype.FilesystemNode) (node filesystemNode) { + node = filesystemNode{ + HREF: "/fs/" + bucketID + v.Path, + Type: v.Type, + Name: v.Name, + FileSize: v.FileSize, + FileType: v.FileType, + } + if node.Type == "dir" { + node.Icon = "/res/img/mime/folder.png" + } else { + node.Icon = "/res/img/mime/empty.png" + } + + return node +} + +func (wc *WebController) serveFilesystem(w http.ResponseWriter, r *http.Request, p httprouter.Params) { + var err error + var td = wc.newTemplateData(w, r) + var path = strings.TrimPrefix(p.ByName("path"), "/") + var fsPath filesystemPath + + if path == "" { + buckets, err := td.PixelAPI.GetFilesystemBuckets() + if err != nil { + if err.Error() == "not_found" { + wc.templates.Get().ExecuteTemplate(w, "404", td) + } else if err.Error() == "authentication_required" { + http.Redirect(w, r, "/login", http.StatusSeeOther) + } else { + log.Error("Failed to get buckets: %s", err) + wc.templates.Get().ExecuteTemplate(w, "500", td) + } + return + } + + for _, v := range buckets.Buckets { + fsPath.Children = append(fsPath.Children, filesystemNode{ + HREF: "/fs/" + v.ID, + Icon: "/res/img/mime/folder-remote.png", + Type: "dir", + Name: v.Name, + FileSize: 0, + FileType: "inode/directory", + }) + } + } else { + log.Info("getting path %s", path) + node, err := td.PixelAPI.GetFilesystemPath(path) + if err != nil { + if err.Error() == "not_found" || err.Error() == "path_not_found" { + wc.templates.Get().ExecuteTemplate(w, "404", td) + } else { + log.Error("Failed to get path: %s", err) + wc.templates.Get().ExecuteTemplate(w, "500", td) + } + return + } + + if node.Path[node.NodeIndex].Type == "file" { + http.Redirect(w, r, "/api/filesystem/"+path, http.StatusSeeOther) + return + } + + for _, v := range node.Path { + fsPath.Path = append(fsPath.Path, convFilesystemNode(node.Bucket.ID, v)) + } + for _, v := range node.Children { + fsPath.Children = append(fsPath.Children, convFilesystemNode(node.Bucket.ID, v)) + } + } + + sort.Slice(fsPath.Children, func(i, j int) (less bool) { + // Directories always come first. Make sure we're comparing apples with + // apples + if fsPath.Children[i].Type != fsPath.Children[j].Type { + return fsPath.Children[i].Type == "dir" + } + + return fsPath.Children[i].Name < fsPath.Children[j].Name + }) + + td.Title = "Filesystem" + td.Other = fsPath + err = wc.templates.Get().ExecuteTemplate(w, "filesystem", td) + if err != nil && !strings.Contains(err.Error(), "broken pipe") { + log.Error("Error executing template filesystem: %s", err) + } +} diff --git a/webcontroller/web_controller.go b/webcontroller/web_controller.go index 5afcae6..6e93442 100644 --- a/webcontroller/web_controller.go +++ b/webcontroller/web_controller.go @@ -116,6 +116,7 @@ func New( {GET, "about" /* */, wc.serveMarkdown("about.md", false)}, {GET, "appearance" /* */, wc.serveTemplate("appearance", false)}, {GET, "hosting" /* */, wc.serveMarkdown("hosting.md", false)}, + {GET, "brave" /* */, wc.serveMarkdown("brave.md", false)}, // User account pages {GET, "register" /* */, wc.serveForm(wc.registerForm, false)}, @@ -138,6 +139,9 @@ func New( {GET, "user/password_reset_confirm" /**/, wc.serveForm(wc.passwordResetConfirmForm, false)}, {PST, "user/password_reset_confirm" /**/, wc.serveForm(wc.passwordResetConfirmForm, false)}, + // Filesystem + {GET, "fs/*path", wc.serveFilesystem}, + {GET, "patreon_activate" /* */, wc.serveForm(wc.patreonLinkForm, true)}, {PST, "patreon_activate" /* */, wc.serveForm(wc.patreonLinkForm, true)},