Skip to content

Commit 0ee95c9

Browse files
authored
Merge pull request #118 from nebulabroadcast/custom-login-background
Customizable login background
2 parents a747828 + 857f897 commit 0ee95c9

File tree

4 files changed

+62
-3
lines changed

4 files changed

+62
-3
lines changed

backend/api/init/init_request.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import functools
2+
import os
13
from typing import Annotated, get_args
24

35
import fastapi
@@ -16,6 +18,12 @@
1618
from .client_settings import ClientSettingsModel, get_client_settings
1719

1820

21+
@functools.cache
22+
def is_login_background_enabled() -> bool:
23+
img_path = f"/mnt/{nebula.config.site_name}_01/.nx/login-background.jpg"
24+
return os.path.isfile(img_path)
25+
26+
1927
class InitResponseModel(ResponseModel):
2028
installed: Annotated[
2129
bool | None,
@@ -33,6 +41,15 @@ class InitResponseModel(ResponseModel):
3341
),
3442
] = None
3543

44+
background: Annotated[
45+
bool,
46+
Field(
47+
title="Background",
48+
description="Is the login background image enabled?",
49+
default_factory=is_login_background_enabled,
50+
),
51+
]
52+
3653
user: Annotated[
3754
UserModel | None,
3855
Field(

backend/server/server.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,14 @@ async def ws_endpoint(websocket: WebSocket) -> None:
174174
# API endpoints and the frontend
175175
#
176176

177+
@app.get("/api/login-background.jpg")
178+
def login_background() -> FileResponse:
179+
"""Serve the login background image."""
180+
img_path = f"/mnt/{nebula.config.site_name}_01/.nx/login-background.jpg"
181+
if os.path.exists(img_path):
182+
return FileResponse(img_path, media_type="image/jpeg")
183+
return JSONResponse(status_code=404, content={"detail": "File not found"})
184+
177185

178186
def install_frontend_plugins(app: FastAPI) -> None:
179187
for plugin in get_frontend_plugins():

frontend/src/app.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const App = () => {
4040
nebula.experimental = response.data.experimental || false;
4141
nebula.plugins = response.data.frontend_plugins || [];
4242
nebula.scopedEndpoints = response.data.scoped_endpoints || [];
43+
nebula.loginBackground = response.data.background || false;
4344
nebula.user = response.data.user || {};
4445
axios.interceptors.response.use(
4546
(response) => {

frontend/src/pages/LoginPage.jsx

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import NebulaLogo from '/src/svg/logo-wide.svg';
77

88
import styled from 'styled-components';
99

10+
import nebula from '/src/nebula';
11+
1012
import LoadingPage from './LoadingPage';
1113

1214
const LoginContainer = styled.div`
@@ -21,6 +23,10 @@ const LoginContainer = styled.div`
2123
justify-content: center;
2224
gap: 12px;
2325
26+
background-position: center;
27+
background-repeat: no-repeat;
28+
background-size: cover;
29+
2430
small {
2531
font-size: 0.8em;
2632
font-style: italic;
@@ -29,7 +35,7 @@ const LoginContainer = styled.div`
2935
`;
3036

3137
const LoginForm = styled.form`
32-
padding: 30px;
38+
padding: 40px;
3339
background-color: var(--color-surface-02);
3440
border-radius: 12px;
3541
display: flex;
@@ -41,6 +47,23 @@ const LoginForm = styled.form`
4147
max-height: 85%;
4248
position: relative;
4349
50+
&.glass {
51+
background-color: rgba(0, 0, 0, 0.4);
52+
backdrop-filter: blur(10px);
53+
54+
input,
55+
button,
56+
a {
57+
background-color: rgba(255, 255, 255, 0.1) !important;
58+
color: #eee !important;
59+
60+
&::placeholder {
61+
color: #ccc;
62+
opacity: 1; /* Firefox */
63+
}
64+
}
65+
}
66+
4467
hr {
4568
border: none;
4669
border-top: 1px solid var(--color-surface-04);
@@ -144,10 +167,20 @@ const LoginPage = ({ motd, onLogin, ssoOptions }) => {
144167
return <LoadingPage />;
145168
}
146169

170+
const pageStyle = {};
171+
let formClass = null;
172+
if (nebula.loginBackground) {
173+
pageStyle.backgroundImage = `url(/api/login-background.jpg)`;
174+
pageStyle.backgroundPosition = 'center';
175+
pageStyle.backgroundRepeat = 'no-repeat';
176+
pageStyle.backgroundSize = 'cover';
177+
formClass = 'glass';
178+
}
179+
147180
return (
148-
<main>
181+
<main style={pageStyle}>
149182
<LoginContainer>
150-
<LoginForm onSubmit={onSubmit}>
183+
<LoginForm onSubmit={onSubmit} className={formClass}>
151184
<div className="logo-container">
152185
<img src={NebulaLogo} alt="Nebula" />
153186
</div>

0 commit comments

Comments
 (0)