From e27d5719f037aa9e9dca27c4eff23d4622b5475d Mon Sep 17 00:00:00 2001 From: Philipp Heckel <pheckel@datto.com> 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 @@ -<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/></svg> \ 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 zcmV+`4%G39P)<h;3K|Lk000e1NJLTq003nG003491^@s6){<Dv00009a7bBm000UB z000UB0g=Tn*Z=?k8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H14Y)}} zK~#90?OknfRMi=N&ThgcAw&o+K}jM>XbFClKy8~u8T@K#2U}z9I9j!6Ye%LtbjEg| zb)4yFr&IrS28Ed_2&1i~sNj^^sc0=2#a6zyLqsA(qYy|!LNH;M{k;9LU+28%oV)k# zy$dASXC}G3d+vSDd*0`~?{m-H-Mc^$MHErQxC9$#cE<}0CkML~JVv%fh{V_;$w?4- zB2<sv=wm!VMS`JuY>IpW#uMP_>gu|3-n@AaF~%AhW3%(HHxUquMx)0^M@RovQ&aN~ zWP_hTmJIsm8W;c%0B<-Pej<@b3>ifTNF)-`Xf*m>XJ_X%0Hy*c2jBxx3ZNtvKhtEe zlPL@U8yy|Jsj{+i8-S{OSe-;L!r}0?va+%Vk<6F`fH>6IBfw*^0|tOaqtVAID=Xhb zkq|3jKA-RV@p$~u<BvaHjbxUT0PrHKy($g1lqn1Vi$o$1m6n!1=c3b-2Jv|OM16gI zOJ84K1V9YQjG<YRffZ6b{r&yd`u+ZcjIqgbCgnOpq0n0u6%}_QNlFx1QY2z>l`jT> z`ThQ_MM9jRyuAF@UAuO*B3s7Nf-jXZvp_QdY<PIMea4I#?-bDANrOlv(&h8{ZUGQM zGF#H6Ovsj!9Clb$Rn?kYosEQoc>TkJ=ouQo`Dg?H%h1gz|LGSPKO<Q3G1msZEweIW zWEOEoXdBB|<(=T3rjM166Z{A9H~TN+Tg}ueEUu}=!dY`*hAC5~G&eRjmi6@X@TDt} zGMFh}W|`sv;4uv26o8q!ow^53;^(hy#@X|sY#`Eu<pP%6a5S)Nz=Xl-Y)EY;HZ0p0 z`^srwH5Tre+ncV%%9a~+p#lH|0)dq+EiK!S&6X&Lwph`WX=Xe8e&==tA&?2-jWV(m z4GPzJ=8-T{d4dJY#6JJB%04ATWnXYyvd`PtajXl0ffMp^9Q=O&HAtQor!__5Kt~EM zKBc-2f{`$~2l}M}fdq^%O*CMP@%zani2+j(!OZM4-UDv7^9S+|i61GuqJ3fm!mc=U z`V`DiUS3{@R270K_8C}NJSwJ465&`31~a69k&44*gg#(&Rx?e&#I_t-#G5BX^JOt( zpK?y^Q$Hks8N!Jea=-_1(o2S|lrIZV2Ta%s#>9ZpG9aBCXv!j;th})E0i&5ActqP& zIs)1TwSDVgioc8zGg5N)!h~Q#B1D)5dFzNeVARcvr6YpR)_I{>BEWg3(9GZ+bwx+i zuITOC)DcGfNWCW7CpLKd`DKeLOER!}K{96_{NVWkficXjzFZwJGT4ivBb?uQ`%FAe zX`dvp12`llNwitO7=X1MKf-U9-G$oAW+=-G4VZ8+XHF%&1=kTU=`dAhFmYgxkZVN` zBo{Q=o+M%C+qjIlxoH8GG|b2A9|f@CgWVVj1+@Xots}He4%mg%5o+HlTq|Fh{~8?u zfD(@f-@AGdw%qqKJo1g3QBgVtbmj^HBO}z?*9S}p6eBi-^5sBB<m7e)N2JIzmCS0A z;%StXl;VerTJhpNkKm50Tj2G0xB)3fXhlaf0lRQIBA32=;XG3`I+A{3=IG3dO8jEU zx3TF5596lBW>U5^_IayxtwICFA0Y*k*x-i*G8Ro{@H*m_$OCSbFHOKwFXTks^lChD z>m69v@c<THQCAQh;eBzeBU=0JFypLzfjDZi9<hRE{}uSd@_X^SZ{CTkrq9fp%3DVm z_b|O5U%v9w5hf6!qRbhroPC+Y%5^Q9Xs@4#wz?+l{<Ir^+`Aj6#=gi;M^pjRlto5} zFw+r!24w8Jm@O`qFNKb9B>npJt=NB}*Pcnnu(V-5Hs1LletP{9Oq)`cZm_N+#5whQ zEZiWZHj6r9Ru=O>E>cWC$;W6(P+WgvVEAyb50CEnGk&?_FE}!2ercP+S5k_5uKPM( zxa%jl=en=K=PhxlBcd`0Z9+w~rz38Dgu!v9Xmx}H3}D#T_bFCx+l=45xgEVDL$>;v z<}1U)UtNNY9V>8a;{v`*n>s?;T+k8s=t#n~@+H-I+LqcH40z|0BY5cLjd=2{*Kl%l z#8y`|l~wrF4a+XDjxb?BS{+fGUgrZxLT{!c%77soFarku{mBu$_xUk=w|OD%Z)wBy zvI={>ld4%b9pUWj%A!kz0In_`)6d0J=LaMWmN7)*alHEB0o=FsSv<eL6Xzmfd)>=5 z#hH#Uy0<kQ$<7Ps)VNx{R5~Kp`BV!D*!gG_F9!aD`(Azy+YcYG)u(9Rp^k6|nCl2{ zUrJd=a4z)He`E&BGy$XaKHXO0@nGrPFXP6mzGSKAi>o8lz6F;p!kMNp20J>EJudrz z0bm{vZfR)7ibd_1Q#IXU-&yN4U>8S6++)T0iXM<sorw+51q=Y%>YMQ6#W$j{+MjR7 zLZ@Z{E3}TdwN`QAG7G7%7IkFd>^eMr{SsU=>q^^Q4hF}FeMOzmxZ{G3Xs(;-?K^{G zQtawT;|xC@Sk#844fAdHH5LhDOV?h!b|j$C5ph<#sw3Iq5&Oi3;7|T=p?q1>k^1S? zxWA<pw>4dDJI!N>INmsR7@Gona5fy``eGz7u%#oC4Q_vF=9}sWDT@x_O8F8KTb^}~ z-taBl-n<YVn`9V<ft@{vu{rQQP6x*nbw0JpQ%A&MIMflTjOP#MXJ45osecL`S=un) zHX-{@euiiFcjDNYK`CI?b%aj=(J{Am#J%;rOXbVbdc-0=I(-To_ID!Ce?plV_H=~v zk$<Ms5#~@wT;j#K(3=FzPIC00`vRK}?!lWqhrtKTd_9tN!WA7MhuYE+$>02ulN7@+ zw8E@(R1q*UoDGMtwQC<<J$wMsL|iB(f_)kbMZj*G+l*D$FU>V1+vxq`3|4pU(Cdgi zBOJlCvoES6nKlhVu_(57?ZeAmdl8Do$Z=$_w9c!DW(;2DL8-^<a6B?fy<ST?!dxQ9 zrNtxEI>KZZV~GU*dGruAAABEYLg$o&&8Z_9`>MAL3J1N8$Ys$9a+1Or(|&A~5n&W+ zDh(Kb_doB!`VV&D#OR1xG#%?mp<$*Y?hpdFx_HzF?0@~o@z+Cpad_~gB)l{;WF6t{ z>xH+_U-P%FBbP||0(3f(eEj6we-oPot;nS#)IM)s7T$tF@Ru*U@>ra}@rUu~BdsW> zQ=QwN35V--#Qq293I&mTscc<J<x8t0jO@p~W=BV$voAK{bZ`v&`ajosDIY>#(8xl6 zXe_6WTv97~GvVbw59Y3p(6;362L_Jgz`zNyln@P|>nGg}7i9agZ^AgG$(28xy&X&j zk$RGPiA21BIzok)FN^fLmSBUFMbSR7!H+H5ptkQ2E`4bz9TOEHHg!Z3Fws7-!Q0nl zqqXZ=#0KxNz?nRO=s2CAAm2~n8p+I0J&{sfF(6IAC=q)5P}?WjB3)>N_$1q=T90sk zxRfP;TVI8smq${s@dKhWmp?*kGt&`Gz{s=}N)A0+m)>I$8@V<`#_{&)<g&(0&O5ET zR=xnmV1-mC0n?O$f_*VmRTc>mj&vk-a9!nPvi}^;pFcl{9Jj)CrF<nfq`YVX1~MQ% z)7;k)DWpOWW&1RxAht;fDVE*3sa0s3RSz=^4-X$DFG<8W{4B9li$EQn3_3EiyaFxN zSK!`xUxCkSewBLt`t>^@XNs_O<#S(Z9RYl$C0IQBDzw%%ptZIE)#X#&=x*F19*_4w z^UO1Yknc?lZfp7G21+m{>qyPCDzw%%qOG<O3uo7&qyX=4j8}a8@y8pHB}7FG02rpE zw6(Q)ki3hV67kf#lFk0vXs>HRYi%PMW?b&v`w56xEH<!U!GaAC@8q2(#u6BSlH<pZ zx0&77Jrau<XF}&L$UWr8GZKkJbnV);-vKZez#IU60GA<oAN(m0@9M2BUkm`MtE*eh zm@D;qG2LtDi$0SQiJd!lu3WWh)e$5!B!=v*Z}~EY^w#tyY+kRorGU;(c*NuJu}zyc zbu3%9>}_Q4L#(>3x&Tv6@p`@U3gGL6hhZ4;p`oF_x3#rBcJ%1c5VB;@8$>I`UPVgg zjNIe#)VlAl5qH_<MTcP+kwhX9j6@>6-QC@<EMLC-)zps-q(z-4M0wY49%h=t7-QO- zMB8vU6buHt`}+FcSg~To3w!qL2|;mgK2AaXPY0R)UJ5N+v~&q}a;;NrtGHnpp>R0d zJ3KtR=c%Wj+VJ$#PxnJk(*zmBcnAI6t@Ie<+?FRpw?+YALP{VIm;-VFMd^)U#KPh5 zXG23nyI*?gr9Z7+z4}wg3nbN+AH;Zvjuh2j&fn$IlG4=Fv_#pvVHojvynke5<iGE} z`|g&Gj*bsVhpNZARcziryLX8~^@C^$@;JR8zZIY*#pm-a&h%s$XM(}t!QS59?d|RD zJI<axOJ{~^HmJxjz2-9kpvoBC&kJgyDo+f6XKZZjZUD2^tXZ>V-MV!V$iF8Am}dl? zA-TwysO0cl`dA4aDGbSlWts?{ko1DnOf$@gm}n(S1=YALk5yH^_y8uj*V8|~!brQS zegfv1F;U5&$ZMQtr^GbqjQdl~e!C=07Gi8ecgoAZFG~Lab<Hf2;1bN%A<{<!NPCfl x0wLGpkhZ5wmkLD^TtdzjyUD&q5{j5S_&-c>)XNhRb$I{)002ovPDHLkV1hiF+kOB5 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): - -<!-- #default-branch-switch --> - -```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: - -<!-- #default-branch-switch --> - -[](https://codesandbox.io/s/github/mui/material-ui/tree/master/examples/create-react-app) - -<!-- #default-branch-switch --> - -[](https://stackblitz.com/github/mui/material-ui/tree/master/examples/create-react-app) - -## The idea behind the example - -<!-- #default-branch-switch --> - -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? - -<!-- #default-branch-switch --> - -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*/ -}} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>ntfy.sh | Send push notifications to your phone via PUT/POST</title> - <link rel="stylesheet" href="static/css/app.css" type="text/css"> + <link rel="stylesheet" href="static/css/home.css" type="text/css"> <!-- Mobile view --> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"> @@ -37,9 +36,9 @@ <div id="name">ntfy</div> <ol> <li><a href="docs/">Getting started</a></li> + <li><a href="app">Web app</a></li> <li><a href="docs/subscribe/phone/">Android/iOS</a></li> <li><a href="docs/publish/">API</a></li> - <li><a href="docs/install/">Self-hosting</a></li> <li><a href="https://github.com/binwiederhier/ntfy">GitHub</a></li> </ol> </div> @@ -90,7 +89,7 @@ Here's what that looks like in the <a href="docs/subscribe/phone/">Android app</a>: </p> <figure> - <img src="static/img/priority-notification.png" style="max-height: 200px"/> + <img src="static/img/screenshot-phone-popover.png" style="max-height: 200px"/> <figcaption>Urgent notification with pop-over</figcaption> </figure> @@ -170,7 +169,6 @@ <center id="ironicCenterTagDontFreakOut"><i>Made with ❤️ by <a href="https://heckel.io">Philipp C. Heckel</a></i></center> </div> <div id="lightbox" class="lightbox"></div> -<script src="static/js/emoji.js"></script> -<script src="static/js/app.js"></script> +<script src="static/js/home.js"></script> </body> </html> 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 @@ <!-- Previews in Google, Slack, WhatsApp, etc. --> <meta property="og:type" content="website" /> <meta property="og:locale" content="en_US" /> - <meta property="og:site_name" content="ntfy.sh" /> - <meta property="og:title" content="ntfy.sh | Send push notifications to your phone or desktop via PUT/POST" /> - <meta property="og:description" content="ntfy is a simple HTTP-based pub-sub notification service. It allows you to send desktop notifications via scripts from any computer, entirely without signup or cost. Made with ❤ by Philipp C. Heckel, Apache License 2.0, source at https://heckel.io/ntfy." /> + <meta property="og:site_name" content="ntfy web" /> + <meta property="og:title" content="ntfy web | Web app to receive push notifications from scripts via PUT/POST" /> + <meta property="og:description" content="ntfy lets you send push notifications via scripts from any computer or phone, entirely without signup or cost. Made with ❤ by Philipp C. Heckel, Apache License 2.0, source at https://heckel.io/ntfy." /> <meta property="og:image" content="%PUBLIC_URL%/static/img/ntfy.png" /> <meta property="og:url" content="https://ntfy.sh" /> <!-- Never index --> <meta name="robots" content="noindex, nofollow" /> - <!-- Server configuration --> - <script src="%PUBLIC_URL%/config.js"></script> - <!-- FIXME Roboto --> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" /> </head> 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 ( <VerticallyCenteredContainer maxWidth="xs"> <Typography variant="h5" align="center" sx={{ paddingBottom: 1 }}> - <img src="static/img/ntfy-outline.svg" height="64" width="64" alt="No notifications"/><br /> + <img src="/static/img/ntfy-outline.svg" height="64" width="64" alt="No notifications"/><br /> You haven't received any notifications for this topic yet. </Typography> <Paragraph> 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"