diff --git a/build/web/bundleWeb.sh b/build/web/bundleWeb.sh index 9c5e3b3fe..d1e07d97a 100755 --- a/build/web/bundleWeb.sh +++ b/build/web/bundleWeb.sh @@ -17,7 +17,7 @@ echo "Building owncast web..." rm -rf .next (node_modules/.bin/next build && node_modules/.bin/next export) | grep info -echo "Copying admin to project directory..." +echo "Copying web project to dist directory..." # Remove the old one rm -rf ../static/web diff --git a/controllers/config.go b/controllers/config.go index ef9567671..b2a9997f1 100644 --- a/controllers/config.go +++ b/controllers/config.go @@ -61,6 +61,14 @@ func GetWebConfig(w http.ResponseWriter, r *http.Request) { middleware.DisableCache(w) w.Header().Set("Content-Type", "application/json") + configuration := getConfigResponse() + + if err := json.NewEncoder(w).Encode(configuration); err != nil { + BadRequestHandler(w, err) + } +} + +func getConfigResponse() webConfigResponse { pageContent := utils.RenderPageContentMarkdown(data.GetExtraPageBodyContent()) socialHandles := data.GetSocialHandles() for i, handle := range socialHandles { @@ -106,7 +114,7 @@ func GetWebConfig(w http.ResponseWriter, r *http.Request) { IndieAuthEnabled: data.GetServerURL() != "", } - configuration := webConfigResponse{ + return webConfigResponse{ Name: data.GetServerName(), Summary: serverSummary, OfflineMessage: data.GetCustomOfflineMessage(), @@ -126,10 +134,6 @@ func GetWebConfig(w http.ResponseWriter, r *http.Request) { Notifications: notificationsResponse, Authentication: authenticationResponse, } - - if err := json.NewEncoder(w).Encode(configuration); err != nil { - BadRequestHandler(w, err) - } } // GetAllSocialPlatforms will return a list of all social platform types. diff --git a/controllers/index.go b/controllers/index.go index ba0958d73..0dba20e92 100644 --- a/controllers/index.go +++ b/controllers/index.go @@ -1,10 +1,14 @@ package controllers import ( + "encoding/json" "net/http" "path/filepath" + "strings" + "github.com/owncast/owncast/core/data" "github.com/owncast/owncast/router/middleware" + "github.com/owncast/owncast/static" "github.com/owncast/owncast/utils" ) @@ -19,6 +23,11 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) { return } + if isIndexRequest { + renderIndexHtml(w) + return + } + // Set a cache control max-age header middleware.SetCachingHeaders(w, r) @@ -27,3 +36,53 @@ func IndexHandler(w http.ResponseWriter, r *http.Request) { serveWeb(w, r) } + +func renderIndexHtml(w http.ResponseWriter) { + type serverSideContent struct { + Name string + Summary string + RequestedURL string + TagsString string + ThumbnailURL string + Thumbnail string + Image string + StatusJSON string + ServerConfigJSON string + } + + status := getStatusResponse() + sb, err := json.Marshal(status) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + config := getConfigResponse() + cb, err := json.Marshal(config) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + content := serverSideContent{ + Name: data.GetServerName(), + Summary: data.GetServerSummary(), + RequestedURL: data.GetServerURL(), + TagsString: strings.Join(data.GetServerMetadataTags(), ","), + ThumbnailURL: "/thumbnail", + Thumbnail: "/thumbnail", + Image: "/logo/external", + StatusJSON: string(sb), + ServerConfigJSON: string(cb), + } + + index, err := static.GetWebIndexTemplate() + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + if err := index.Execute(w, content); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} diff --git a/controllers/status.go b/controllers/status.go index 4c316bbf0..531044394 100644 --- a/controllers/status.go +++ b/controllers/status.go @@ -13,6 +13,17 @@ import ( // GetStatus gets the status of the server. func GetStatus(w http.ResponseWriter, r *http.Request) { + response := getStatusResponse() + + w.Header().Set("Content-Type", "application/json") + middleware.DisableCache(w) + + if err := json.NewEncoder(w).Encode(response); err != nil { + InternalErrorHandler(w, err) + } +} + +func getStatusResponse() webStatusResponse { status := core.GetStatus() response := webStatusResponse{ Online: status.Online, @@ -22,17 +33,10 @@ func GetStatus(w http.ResponseWriter, r *http.Request) { VersionNumber: status.VersionNumber, StreamTitle: status.StreamTitle, } - if !data.GetHideViewerCount() { response.ViewerCount = status.ViewerCount } - - w.Header().Set("Content-Type", "application/json") - middleware.DisableCache(w) - - if err := json.NewEncoder(w).Encode(response); err != nil { - InternalErrorHandler(w, err) - } + return response } type webStatusResponse struct { diff --git a/web/components/layouts/Main.tsx b/web/components/layouts/Main.tsx index 8d7d068b6..579f5f3b7 100644 --- a/web/components/layouts/Main.tsx +++ b/web/components/layouts/Main.tsx @@ -1,3 +1,5 @@ +/* eslint-disable react/no-danger */ +/* eslint-disable react/no-unescaped-entities */ import { Layout } from 'antd'; import { useRecoilValue } from 'recoil'; import Head from 'next/head'; @@ -27,6 +29,11 @@ export const Main: FC = () => { setupNoLinkReferrer(layoutRef.current); }, []); + const hydrationScript = ` + window.statusHydration = {{.StatusJSON}}; + window.configHydration = {{.ServerConfigJSON}}; + `; + return ( <> @@ -86,6 +93,7 @@ export const Main: FC = () => { +