From e27d5719f037aa9e9dca27c4eff23d4622b5475d Mon Sep 17 00:00:00 2001 From: Philipp Heckel Date: Sat, 5 Mar 2022 20:24:10 -0500 Subject: [PATCH] Embed new web UI into server --- .gitignore | 1 + Makefile | 29 +++++++++- server/server.go | 53 ++++++++---------- server/static/img/close.svg | 1 - server/static/img/favicon.png | Bin 4701 -> 0 bytes server/static/img/ntfy.png | Bin 3627 -> 0 bytes web/README.md | 44 --------------- web/public/config.js | 3 - web/public/favicon.ico | Bin 3870 -> 0 bytes server/index.gohtml => web/public/home.html | 10 ++-- web/public/index.html | 9 +-- web/public/manifest.json | 15 ----- .../app.css => web/public/static/css/home.css | 0 .../static/font/roboto-v29-latin-300.woff | Bin .../static/font/roboto-v29-latin-300.woff2 | Bin .../static/font/roboto-v29-latin-500.woff | Bin .../static/font/roboto-v29-latin-500.woff2 | Bin .../static/font/roboto-v29-latin-regular.woff | Bin .../font/roboto-v29-latin-regular.woff2 | Bin .../static/img/android-video-overview.mp4 | Bin .../img/android-video-subscribe-api.mp4 | Bin .../public}/static/img/badge-appstore.png | Bin .../public}/static/img/badge-fdroid.png | Bin .../public}/static/img/badge-googleplay.png | Bin .../public}/static/img/basic-notification.png | Bin .../public}/static/img/screenshot-curl.png | Bin .../public}/static/img/screenshot-docs.png | Bin .../static/img/screenshot-phone-add.jpg | Bin .../static/img/screenshot-phone-detail.jpg | Bin .../static/img/screenshot-phone-main.jpg | Bin .../img/screenshot-phone-notification.jpg | Bin .../static/img/screenshot-phone-popover.png | Bin .../static/img/screenshot-web-detail.png | Bin .../js/app.js => web/public/static/js/home.js | 0 web/src/app/config.js | 5 +- web/src/components/App.js | 1 - web/src/components/Notifications.js | 2 +- web/src/components/SubscribeDialog.js | 1 + 38 files changed, 64 insertions(+), 110 deletions(-) delete mode 100644 server/static/img/close.svg delete mode 100644 server/static/img/favicon.png delete mode 100644 server/static/img/ntfy.png delete mode 100644 web/README.md delete mode 100644 web/public/config.js delete mode 100644 web/public/favicon.ico rename server/index.gohtml => web/public/home.html (96%) delete mode 100644 web/public/manifest.json rename server/static/css/app.css => web/public/static/css/home.css (100%) rename {server => web/public}/static/font/roboto-v29-latin-300.woff (100%) rename {server => web/public}/static/font/roboto-v29-latin-300.woff2 (100%) rename {server => web/public}/static/font/roboto-v29-latin-500.woff (100%) rename {server => web/public}/static/font/roboto-v29-latin-500.woff2 (100%) rename {server => web/public}/static/font/roboto-v29-latin-regular.woff (100%) rename {server => web/public}/static/font/roboto-v29-latin-regular.woff2 (100%) rename {server => web/public}/static/img/android-video-overview.mp4 (100%) rename {server => web/public}/static/img/android-video-subscribe-api.mp4 (100%) rename {server => web/public}/static/img/badge-appstore.png (100%) rename {server => web/public}/static/img/badge-fdroid.png (100%) rename {server => web/public}/static/img/badge-googleplay.png (100%) rename {server => web/public}/static/img/basic-notification.png (100%) rename {server => web/public}/static/img/screenshot-curl.png (100%) rename {server => web/public}/static/img/screenshot-docs.png (100%) rename {server => web/public}/static/img/screenshot-phone-add.jpg (100%) rename {server => web/public}/static/img/screenshot-phone-detail.jpg (100%) rename {server => web/public}/static/img/screenshot-phone-main.jpg (100%) rename {server => web/public}/static/img/screenshot-phone-notification.jpg (100%) rename server/static/img/priority-notification.png => web/public/static/img/screenshot-phone-popover.png (100%) rename {server => web/public}/static/img/screenshot-web-detail.png (100%) rename server/static/js/app.js => web/public/static/js/home.js (100%) diff --git a/.gitignore b/.gitignore index 932e0fcd..9f514857 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ dist/ build/ .idea/ server/docs/ +server/site/ tools/fbsend/fbsend playground/ *.iml diff --git a/Makefile b/Makefile index a9a9a201..06b4c745 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,28 @@ docs-deps: .PHONY docs: docs-deps mkdocs build + +# Web app + +web-deps: + cd web && npm install + +web-build: + cd web \ + && npm run build \ + && mv build/index.html build/app.html \ + && rm -rf ../server/site \ + && mv build ../server/site \ + && rm \ + ../server/site/precache* \ + ../server/site/service-worker.js \ + ../server/site/asset-manifest.json \ + ../server/site/static/js/*.js.map \ + ../server/site/static/js/*.js.LICENSE.txt + +web: web-deps web-build + + # Test/check targets check: test fmt-check vet lint staticcheck @@ -94,7 +116,7 @@ staticcheck: .PHONY # Building targets -build-deps: docs +build-deps: docs web which arm-linux-gnueabi-gcc || { echo "ERROR: ARMv6/v7 cross compiler not installed. On Ubuntu, run: apt install gcc-arm-linux-gnueabi"; exit 1; } which aarch64-linux-gnu-gcc || { echo "ERROR: ARM64 cross compiler not installed. On Ubuntu, run: apt install gcc-aarch64-linux-gnu"; exit 1; } @@ -105,8 +127,9 @@ build-snapshot: build-deps goreleaser build --snapshot --rm-dist --debug build-simple: clean - mkdir -p dist/ntfy_linux_amd64 server/docs - touch server/docs/dummy + mkdir -p dist/ntfy_linux_amd64 server/docs server/site + touch server/docs/index.html + touch server/site/app.html export CGO_ENABLED=1 go build \ -o dist/ntfy_linux_amd64/ntfy \ diff --git a/server/server.go b/server/server.go index 7e4c551a..9edcc86c 100644 --- a/server/server.go +++ b/server/server.go @@ -13,7 +13,6 @@ import ( "golang.org/x/sync/errgroup" "heckel.io/ntfy/auth" "heckel.io/ntfy/util" - "html/template" "io" "log" "net" @@ -61,35 +60,31 @@ type handleFunc func(http.ResponseWriter, *http.Request, *visitor) error var ( // If changed, don't forget to update Android App and auth_sqlite.go - topicRegex = regexp.MustCompile(`^[-_A-Za-z0-9]{1,64}$`) // No /! - topicPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}$`) // Regex must match JS & Android app! - jsonPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/json$`) - ssePathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/sse$`) - rawPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/raw$`) - wsPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/ws$`) - authPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/auth$`) - publishPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/(publish|send|trigger)$`) + topicRegex = regexp.MustCompile(`^[-_A-Za-z0-9]{1,64}$`) // No /! + topicPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}$`) // Regex must match JS & Android app! + extTopicPathRegex = regexp.MustCompile(`^/[^/]+\.[^/]+/[-_A-Za-z0-9]{1,64}$`) // Extended topic path, for web-app, e.g. /example.com/mytopic + jsonPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/json$`) + ssePathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/sse$`) + rawPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/raw$`) + wsPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/ws$`) + authPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/auth$`) + publishPathRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}(,[-_A-Za-z0-9]{1,64})*/(publish|send|trigger)$`) staticRegex = regexp.MustCompile(`^/static/.+`) docsRegex = regexp.MustCompile(`^/docs(|/.*)$`) fileRegex = regexp.MustCompile(`^/file/([-_A-Za-z0-9]{1,64})(?:\.[A-Za-z0-9]{1,16})?$`) - disallowedTopics = []string{"docs", "static", "file"} // If updated, also update in Android app + disallowedTopics = []string{"docs", "static", "file", "app", "settings"} // If updated, also update in Android app attachURLRegex = regexp.MustCompile(`^https?://`) - templateFnMap = template.FuncMap{ - "durationToHuman": util.DurationToHuman, - } - - //go:embed "index.gohtml" - indexSource string - indexTemplate = template.Must(template.New("index").Funcs(templateFnMap).Parse(indexSource)) - //go:embed "example.html" exampleSource string - //go:embed static - webStaticFs embed.FS - webStaticFsCached = &util.CachingEmbedFS{ModTime: time.Now(), FS: webStaticFs} + //go:embed site + webFs embed.FS + webFsCached = &util.CachingEmbedFS{ModTime: time.Now(), FS: webFs} + webSiteDir = "/site" + webHomeIndex = "/home.html" // Landing page, only if "web-index: home" + webAppIndex = "/app.html" // React app //go:embed docs docsStaticFs embed.FS @@ -284,8 +279,6 @@ func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request, v *visit return s.limitRequests(s.handleFile)(w, r, v) } else if r.Method == http.MethodOptions { return s.handleOptions(w, r) - } else if r.Method == http.MethodGet && topicPathRegex.MatchString(r.URL.Path) { - return s.handleTopic(w, r) } else if (r.Method == http.MethodPut || r.Method == http.MethodPost) && topicPathRegex.MatchString(r.URL.Path) { return s.limitRequests(s.authWrite(s.handlePublish))(w, r, v) } else if r.Method == http.MethodGet && publishPathRegex.MatchString(r.URL.Path) { @@ -300,15 +293,15 @@ func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request, v *visit return s.limitRequests(s.authRead(s.handleSubscribeWS))(w, r, v) } else if r.Method == http.MethodGet && authPathRegex.MatchString(r.URL.Path) { return s.limitRequests(s.authRead(s.handleTopicAuth))(w, r, v) + } else if r.Method == http.MethodGet && (topicPathRegex.MatchString(r.URL.Path) || extTopicPathRegex.MatchString(r.URL.Path)) { + return s.handleTopic(w, r) } return errHTTPNotFound } func (s *Server) handleHome(w http.ResponseWriter, r *http.Request) error { - return indexTemplate.Execute(w, &indexPage{ - Topic: r.URL.Path[1:], - CacheDuration: s.config.CacheDuration, - }) + r.URL.Path = webHomeIndex + return s.handleStatic(w, r) } func (s *Server) handleTopic(w http.ResponseWriter, r *http.Request) error { @@ -319,7 +312,8 @@ func (s *Server) handleTopic(w http.ResponseWriter, r *http.Request) error { _, err := io.WriteString(w, `{"unifiedpush":{"version":1}}`+"\n") return err } - return s.handleHome(w, r) + r.URL.Path = webAppIndex + return s.handleStatic(w, r) } func (s *Server) handleEmpty(_ http.ResponseWriter, _ *http.Request, _ *visitor) error { @@ -339,7 +333,8 @@ func (s *Server) handleExample(w http.ResponseWriter, _ *http.Request) error { } func (s *Server) handleStatic(w http.ResponseWriter, r *http.Request) error { - http.FileServer(http.FS(webStaticFsCached)).ServeHTTP(w, r) + r.URL.Path = webSiteDir + r.URL.Path + http.FileServer(http.FS(webFsCached)).ServeHTTP(w, r) return nil } diff --git a/server/static/img/close.svg b/server/static/img/close.svg deleted file mode 100644 index 5f1267d7..00000000 --- a/server/static/img/close.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/server/static/img/favicon.png b/server/static/img/favicon.png deleted file mode 100644 index 92312feac6a3c9effe8323e76a6d30f2ce88d724..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4701 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 Zdu`HC4VjGyX*2{dxMQmGUfU`5e*gp9@R9%k diff --git a/server/static/img/ntfy.png b/server/static/img/ntfy.png deleted file mode 100644 index 6b969a846efc6c3dac70510793c72253e04389c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3627 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 diff --git a/web/README.md b/web/README.md deleted file mode 100644 index 953f65b2..00000000 --- a/web/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# Create React App example - -## How to use - -Download the example [or clone the repo](https://github.com/mui/material-ui): - - - -```sh -curl https://codeload.github.com/mui/material-ui/tar.gz/master | tar -xz --strip=2 material-ui-master/examples/create-react-app -cd create-react-app -``` - -Install it and run: - -```sh -npm install -npm start -``` - -or: - - - -[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/mui/material-ui/tree/master/examples/create-react-app) - - - -[![Edit on StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/mui/material-ui/tree/master/examples/create-react-app) - -## The idea behind the example - - - -This example demonstrates how you can use [Create React App](https://github.com/facebookincubator/create-react-app). -It includes `@mui/material` and its peer dependencies, including `emotion`, the default style engine in MUI v5. -If you prefer, you can [use styled-components instead](https://mui.com/guides/interoperability/#styled-components). - -## What's next? - - - -You now have a working example project. -You can head back to the documentation, continuing browsing it from the [templates](https://mui.com/getting-started/templates/) section. diff --git a/web/public/config.js b/web/public/config.js deleted file mode 100644 index 3283db2e..00000000 --- a/web/public/config.js +++ /dev/null @@ -1,3 +0,0 @@ -var config = { - defaultBaseUrl: 'https://ntfy.sh' -}; diff --git a/web/public/favicon.ico b/web/public/favicon.ico deleted file mode 100644 index a11777cc471a4344702741ab1c8a588998b1311a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ diff --git a/server/index.gohtml b/web/public/home.html similarity index 96% rename from server/index.gohtml rename to web/public/home.html index 9fec14cf..f054f83a 100644 --- a/server/index.gohtml +++ b/web/public/home.html @@ -1,11 +1,10 @@ -{{- /*gotype: heckel.io/ntfy/server.indexPage*/ -}} ntfy.sh | Send push notifications to your phone via PUT/POST - + @@ -37,9 +36,9 @@
ntfy
  1. Getting started
  2. +
  3. Web app
  4. Android/iOS
  5. API
  6. -
  7. Self-hosting
  8. GitHub
@@ -90,7 +89,7 @@ Here's what that looks like in the Android app:

- +
Urgent notification with pop-over
@@ -170,7 +169,6 @@
Made with ❤️ by Philipp C. Heckel
- - + diff --git a/web/public/index.html b/web/public/index.html index 3512b548..19e14506 100644 --- a/web/public/index.html +++ b/web/public/index.html @@ -20,18 +20,15 @@ - - - + + + - - - diff --git a/web/public/manifest.json b/web/public/manifest.json deleted file mode 100644 index f99717a5..00000000 --- a/web/public/manifest.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "short_name": "Your Orders", - "name": "Your Orders", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" -} diff --git a/server/static/css/app.css b/web/public/static/css/home.css similarity index 100% rename from server/static/css/app.css rename to web/public/static/css/home.css diff --git a/server/static/font/roboto-v29-latin-300.woff b/web/public/static/font/roboto-v29-latin-300.woff similarity index 100% rename from server/static/font/roboto-v29-latin-300.woff rename to web/public/static/font/roboto-v29-latin-300.woff diff --git a/server/static/font/roboto-v29-latin-300.woff2 b/web/public/static/font/roboto-v29-latin-300.woff2 similarity index 100% rename from server/static/font/roboto-v29-latin-300.woff2 rename to web/public/static/font/roboto-v29-latin-300.woff2 diff --git a/server/static/font/roboto-v29-latin-500.woff b/web/public/static/font/roboto-v29-latin-500.woff similarity index 100% rename from server/static/font/roboto-v29-latin-500.woff rename to web/public/static/font/roboto-v29-latin-500.woff diff --git a/server/static/font/roboto-v29-latin-500.woff2 b/web/public/static/font/roboto-v29-latin-500.woff2 similarity index 100% rename from server/static/font/roboto-v29-latin-500.woff2 rename to web/public/static/font/roboto-v29-latin-500.woff2 diff --git a/server/static/font/roboto-v29-latin-regular.woff b/web/public/static/font/roboto-v29-latin-regular.woff similarity index 100% rename from server/static/font/roboto-v29-latin-regular.woff rename to web/public/static/font/roboto-v29-latin-regular.woff diff --git a/server/static/font/roboto-v29-latin-regular.woff2 b/web/public/static/font/roboto-v29-latin-regular.woff2 similarity index 100% rename from server/static/font/roboto-v29-latin-regular.woff2 rename to web/public/static/font/roboto-v29-latin-regular.woff2 diff --git a/server/static/img/android-video-overview.mp4 b/web/public/static/img/android-video-overview.mp4 similarity index 100% rename from server/static/img/android-video-overview.mp4 rename to web/public/static/img/android-video-overview.mp4 diff --git a/server/static/img/android-video-subscribe-api.mp4 b/web/public/static/img/android-video-subscribe-api.mp4 similarity index 100% rename from server/static/img/android-video-subscribe-api.mp4 rename to web/public/static/img/android-video-subscribe-api.mp4 diff --git a/server/static/img/badge-appstore.png b/web/public/static/img/badge-appstore.png similarity index 100% rename from server/static/img/badge-appstore.png rename to web/public/static/img/badge-appstore.png diff --git a/server/static/img/badge-fdroid.png b/web/public/static/img/badge-fdroid.png similarity index 100% rename from server/static/img/badge-fdroid.png rename to web/public/static/img/badge-fdroid.png diff --git a/server/static/img/badge-googleplay.png b/web/public/static/img/badge-googleplay.png similarity index 100% rename from server/static/img/badge-googleplay.png rename to web/public/static/img/badge-googleplay.png diff --git a/server/static/img/basic-notification.png b/web/public/static/img/basic-notification.png similarity index 100% rename from server/static/img/basic-notification.png rename to web/public/static/img/basic-notification.png diff --git a/server/static/img/screenshot-curl.png b/web/public/static/img/screenshot-curl.png similarity index 100% rename from server/static/img/screenshot-curl.png rename to web/public/static/img/screenshot-curl.png diff --git a/server/static/img/screenshot-docs.png b/web/public/static/img/screenshot-docs.png similarity index 100% rename from server/static/img/screenshot-docs.png rename to web/public/static/img/screenshot-docs.png diff --git a/server/static/img/screenshot-phone-add.jpg b/web/public/static/img/screenshot-phone-add.jpg similarity index 100% rename from server/static/img/screenshot-phone-add.jpg rename to web/public/static/img/screenshot-phone-add.jpg diff --git a/server/static/img/screenshot-phone-detail.jpg b/web/public/static/img/screenshot-phone-detail.jpg similarity index 100% rename from server/static/img/screenshot-phone-detail.jpg rename to web/public/static/img/screenshot-phone-detail.jpg diff --git a/server/static/img/screenshot-phone-main.jpg b/web/public/static/img/screenshot-phone-main.jpg similarity index 100% rename from server/static/img/screenshot-phone-main.jpg rename to web/public/static/img/screenshot-phone-main.jpg diff --git a/server/static/img/screenshot-phone-notification.jpg b/web/public/static/img/screenshot-phone-notification.jpg similarity index 100% rename from server/static/img/screenshot-phone-notification.jpg rename to web/public/static/img/screenshot-phone-notification.jpg diff --git a/server/static/img/priority-notification.png b/web/public/static/img/screenshot-phone-popover.png similarity index 100% rename from server/static/img/priority-notification.png rename to web/public/static/img/screenshot-phone-popover.png diff --git a/server/static/img/screenshot-web-detail.png b/web/public/static/img/screenshot-web-detail.png similarity index 100% rename from server/static/img/screenshot-web-detail.png rename to web/public/static/img/screenshot-web-detail.png diff --git a/server/static/js/app.js b/web/public/static/js/home.js similarity index 100% rename from server/static/js/app.js rename to web/public/static/js/home.js diff --git a/web/src/app/config.js b/web/src/app/config.js index 71a9ece3..1976d79e 100644 --- a/web/src/app/config.js +++ b/web/src/app/config.js @@ -1,2 +1,5 @@ -const config = window.config; +//const config = window.config; +const config = { + defaultBaseUrl: "https://ntfy.sh" +}; export default config; diff --git a/web/src/components/App.js b/web/src/components/App.js index c39fd412..7834de47 100644 --- a/web/src/components/App.js +++ b/web/src/components/App.js @@ -21,7 +21,6 @@ import {BrowserRouter, Route, Routes, useLocation, useNavigate} from "react-rout import {subscriptionRoute} from "../app/utils"; // TODO support unsubscribed routes -// TODO embed into ntfy server // TODO googlefonts // TODO new notification indicator // TODO sound diff --git a/web/src/components/Notifications.js b/web/src/components/Notifications.js index d64ef0a6..38e8c9c4 100644 --- a/web/src/components/Notifications.js +++ b/web/src/components/Notifications.js @@ -251,7 +251,7 @@ const NothingHereYet = (props) => { return ( - No notifications
+ No notifications
You haven't received any notifications for this topic yet.
diff --git a/web/src/components/SubscribeDialog.js b/web/src/components/SubscribeDialog.js index c3a362d5..aa2de679 100644 --- a/web/src/components/SubscribeDialog.js +++ b/web/src/components/SubscribeDialog.js @@ -109,6 +109,7 @@ const SubscribePage = (props) => { margin="dense" id="topic" placeholder="Topic name, e.g. phil_alerts" + inputProps={{ maxLength: 64 }} value={props.topic} onChange={ev => props.setTopic(ev.target.value)} type="text"