diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 5f54aebb8fb..7d9c9d89f99 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -153,7 +153,8 @@ void getIndexPage(resp_https_t response, req_https_t request) { std::string header = read_file(WEB_DIR "header.html"); std::string content = read_file(WEB_DIR "index.html"); - response->write(header + content); + std::string footer = read_file(WEB_DIR "footer.html"); + response->write(header + content + footer); } void getPinPage(resp_https_t response, req_https_t request) { @@ -163,7 +164,8 @@ void getPinPage(resp_https_t response, req_https_t request) { std::string header = read_file(WEB_DIR "header.html"); std::string content = read_file(WEB_DIR "pin.html"); - response->write(header + content); + std::string footer = read_file(WEB_DIR "footer.html"); + response->write(header + content + footer); } void getAppsPage(resp_https_t response, req_https_t request) { @@ -176,7 +178,8 @@ void getAppsPage(resp_https_t response, req_https_t request) { std::string header = read_file(WEB_DIR "header.html"); std::string content = read_file(WEB_DIR "apps.html"); - response->write(header + content, headers); + std::string footer = read_file(WEB_DIR "footer.html"); + response->write(header + content + footer, headers); } void getClientsPage(resp_https_t response, req_https_t request) { @@ -186,7 +189,8 @@ void getClientsPage(resp_https_t response, req_https_t request) { std::string header = read_file(WEB_DIR "header.html"); std::string content = read_file(WEB_DIR "clients.html"); - response->write(header + content); + std::string footer = read_file(WEB_DIR "footer.html"); + response->write(header + content + footer); } void getConfigPage(resp_https_t response, req_https_t request) { @@ -196,7 +200,8 @@ void getConfigPage(resp_https_t response, req_https_t request) { std::string header = read_file(WEB_DIR "header.html"); std::string content = read_file(WEB_DIR "config.html"); - response->write(header + content); + std::string footer = read_file(WEB_DIR "footer.html"); + response->write(header + content + footer + footer); } void getPasswordPage(resp_https_t response, req_https_t request) { @@ -206,7 +211,8 @@ void getPasswordPage(resp_https_t response, req_https_t request) { std::string header = read_file(WEB_DIR "header.html"); std::string content = read_file(WEB_DIR "password.html"); - response->write(header + content); + std::string footer = read_file(WEB_DIR "footer.html"); + response->write(header + content + footer); } void getWelcomePage(resp_https_t response, req_https_t request) { @@ -217,7 +223,8 @@ void getWelcomePage(resp_https_t response, req_https_t request) { } std::string header = read_file(WEB_DIR "header-no-nav.html"); std::string content = read_file(WEB_DIR "welcome.html"); - response->write(header + content); + std::string footer = read_file(WEB_DIR "footer.html"); + response->write(header + content + footer); } void getTroubleshootingPage(resp_https_t response, req_https_t request) { @@ -227,7 +234,8 @@ void getTroubleshootingPage(resp_https_t response, req_https_t request) { std::string header = read_file(WEB_DIR "header.html"); std::string content = read_file(WEB_DIR "troubleshooting.html"); - response->write(header + content); + std::string footer = read_file(WEB_DIR "footer.html"); + response->write(header + content + footer); } void getFaviconImage(resp_https_t response, req_https_t request) { @@ -257,24 +265,23 @@ bool isChildPath(fs::path const &base, fs::path const &query) { return *(relPath.begin()) != fs::path(".."); } -void getNodeModules(resp_https_t response, req_https_t request) { +void getWebAsset(resp_https_t response, req_https_t request) { print_req(request); - fs::path webDirPath(WEB_DIR); - fs::path nodeModulesPath(webDirPath / "node_modules"); + fs::path assetsDirPath(SUNSHINE_ASSETS_DIR); // .relative_path is needed to shed any leading slash that might exist in the request path - auto filePath = fs::weakly_canonical(webDirPath / fs::path(request->path).relative_path()); + auto filePath = fs::weakly_canonical(assetsDirPath / fs::path(request->path).relative_path()); - // Don't do anything if file does not exist or is outside the node_modules directory - if(!isChildPath(filePath, nodeModulesPath)) { - BOOST_LOG(warning) << "Someone requested a path " << filePath << " that is outside the node_modules folder"; + // Don't do anything if file does not exist or is outside the assets directory + if(!isChildPath(filePath, assetsDirPath)) { + BOOST_LOG(warning) << "Someone requested a path " << filePath << " that is outside the assets directory"; response->write(SimpleWeb::StatusCode::client_error_bad_request, "Bad Request"); } else if(!fs::exists(filePath)) { response->write(SimpleWeb::StatusCode::client_error_not_found); } else { - auto relPath = fs::relative(filePath, webDirPath); + auto relPath = fs::relative(filePath, assetsDirPath); // get the mime type from the file extension mime_types map // remove the leading period from the extension auto mimeType = mime_types.find(relPath.extension().string().substr(1)); @@ -729,7 +736,7 @@ void start() { server.resource["^/api/covers/upload$"]["POST"] = uploadCover; server.resource["^/images/favicon.ico$"]["GET"] = getFaviconImage; server.resource["^/images/logo-sunshine-45.png$"]["GET"] = getSunshineLogoImage; - server.resource["^/node_modules\\/.+$"]["GET"] = getNodeModules; + server.resource["^/(web)\\/.+$"]["GET"] = getWebAsset; server.config.reuse_address = true; server.config.address = "0.0.0.0"s; server.config.port = port_https; diff --git a/src_assets/common/assets/web/css/main.css b/src_assets/common/assets/web/css/main.css new file mode 100644 index 00000000000..86b12e0e0c5 --- /dev/null +++ b/src_assets/common/assets/web/css/main.css @@ -0,0 +1,24 @@ +:root, [data-bs-theme=light]{ + --bs-primary-rgb: 255, 196, 0; +} +[data-bs-theme=dark]{ + --bs-primary-rgb: 25, 27, 30; +} + +#toggleTheme{ + margin-left:auto; + margin-right:10px; +} +#toggleTheme span:not(.active){ + display:none; +} +@media(min-width:992px){ + #toggleTheme{ + position:absolute; + right:0; + } +} + +html[data-bs-theme="dark"] #toggleTheme i{ + color:#fff; +} diff --git a/src_assets/common/assets/web/footer.html b/src_assets/common/assets/web/footer.html new file mode 100644 index 00000000000..8a50e4922de --- /dev/null +++ b/src_assets/common/assets/web/footer.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src_assets/common/assets/web/header-no-nav.html b/src_assets/common/assets/web/header-no-nav.html index 28ef76defe5..cbda6b37b14 100644 --- a/src_assets/common/assets/web/header-no-nav.html +++ b/src_assets/common/assets/web/header-no-nav.html @@ -5,10 +5,8 @@ Sunshine - - - + + + - - - + diff --git a/src_assets/common/assets/web/header.html b/src_assets/common/assets/web/header.html index 800414779e4..b26c6132e0f 100644 --- a/src_assets/common/assets/web/header.html +++ b/src_assets/common/assets/web/header.html @@ -6,21 +6,23 @@ Sunshine - - - - + + + + -