Fix bottom nav full-width layout + add backend URL autofill
- Remove max-width/gap/padding from bottom nav so buttons fill full screen width - Add NS_BACKEND_URL to config.js entrypoint and autofill backend-url field on setup screen Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
b6edfcf14b
commit
a5461ff92c
6 files changed
+17
-17
No files matched your search
+2
-1
@@ -1,7 +1,8 @@
|
|||||||
# Copy to .env and fill in your values
|
# Copy to .env and fill in your values
|
||||||
|
|
||||||
# Pre-fills the server URL on the setup screen
|
# Pre-fills the URLs on the setup screen
|
||||||
NAVIDROME_URL=https://music.yourdomain.com
|
NAVIDROME_URL=https://music.yourdomain.com
|
||||||
|
BACKEND_URL=https://novasonic-api.yourdomain.com
|
||||||
|
|
||||||
# Path to your Navidrome music library on the host
|
# Path to your Navidrome music library on the host
|
||||||
MUSIC_PATH=/path/to/your/navidrome/music
|
MUSIC_PATH=/path/to/your/navidrome/music
|
||||||
|
|||||||
@@ -110,11 +110,9 @@ function disconnect(){
|
|||||||
window.addEventListener('load',()=>{
|
window.addEventListener('load',()=>{
|
||||||
const saved=localStorage.getItem('ns_cfg');
|
const saved=localStorage.getItem('ns_cfg');
|
||||||
if(saved){cfg=JSON.parse(saved);startApp()}
|
if(saved){cfg=JSON.parse(saved);startApp()}
|
||||||
// Autofill server URL from Docker env (set via config.js)
|
// Autofill URLs from Docker env (set via config.js)
|
||||||
if(window.NS_SERVER_URL){
|
if(window.NS_SERVER_URL){const el=document.getElementById('srv-url');if(el&&!el.value)el.value=window.NS_SERVER_URL;}
|
||||||
const el=document.getElementById('srv-url');
|
if(window.NS_BACKEND_URL){const el=document.getElementById('backend-url');if(el&&!el.value)el.value=window.NS_BACKEND_URL;}
|
||||||
if(el&&!el.value)el.value=window.NS_SERVER_URL;
|
|
||||||
}
|
|
||||||
document.getElementById('srv-pass').addEventListener('keydown',e=>{if(e.key==='Enter')doConnect()});
|
document.getElementById('srv-pass').addEventListener('keydown',e=>{if(e.key==='Enter')doConnect()});
|
||||||
audio.addEventListener('timeupdate',updateProgress);
|
audio.addEventListener('timeupdate',updateProgress);
|
||||||
audio.addEventListener('ended',onEnded);
|
audio.addEventListener('ended',onEnded);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ services:
|
|||||||
- "8080:80" # route this port through your reverse proxy
|
- "8080:80" # route this port through your reverse proxy
|
||||||
environment:
|
environment:
|
||||||
- NAVIDROME_URL=${NAVIDROME_URL} # pre-filled on the setup screen
|
- NAVIDROME_URL=${NAVIDROME_URL} # pre-filled on the setup screen
|
||||||
|
- BACKEND_URL=${BACKEND_URL} # pre-filled on the setup screen
|
||||||
|
|
||||||
# ── Backend (yt-dlp download server) ─────────────────────────────────────────
|
# ── Backend (yt-dlp download server) ─────────────────────────────────────────
|
||||||
novasonic-backend:
|
novasonic-backend:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Generate runtime config from env vars so the frontend knows the Navidrome URL
|
# Generate runtime config from env vars so the frontend knows the Navidrome URL
|
||||||
cat > /usr/share/nginx/html/config.js <<EOF
|
cat > /usr/share/nginx/html/config.js <<EOF
|
||||||
window.NS_SERVER_URL = "${NAVIDROME_URL:-}";
|
window.NS_SERVER_URL = "${NAVIDROME_URL:-}";
|
||||||
|
window.NS_BACKEND_URL = "${BACKEND_URL:-}";
|
||||||
EOF
|
EOF
|
||||||
exec nginx -g "daemon off;"
|
exec nginx -g "daemon off;"
|
||||||
+8
-9
@@ -362,18 +362,17 @@ nav{flex:1;overflow-y:auto;padding:4px 10px}
|
|||||||
backdrop-filter:blur(28px);
|
backdrop-filter:blur(28px);
|
||||||
border-top:1px solid var(--border2);
|
border-top:1px solid var(--border2);
|
||||||
z-index:200;
|
z-index:200;
|
||||||
padding:0 4px;
|
|
||||||
padding-bottom:env(safe-area-inset-bottom);
|
padding-bottom:env(safe-area-inset-bottom);
|
||||||
}
|
}
|
||||||
.bottom-nav-inner{
|
.bottom-nav-inner{
|
||||||
display:flex;flex-direction:column;align-items:stretch;
|
display:flex;flex-direction:column;align-items:stretch;
|
||||||
height:100%;max-width:500px;margin:0 auto;
|
height:100%;width:100%;
|
||||||
}
|
}
|
||||||
.bnav-item{
|
.bnav-item{
|
||||||
display:flex;flex-direction:column;align-items:center;gap:4px;
|
display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
|
||||||
padding:8px 12px;border-radius:12px;cursor:pointer;
|
padding:6px 4px;border-radius:10px;cursor:pointer;
|
||||||
font-size:10px;font-weight:600;color:var(--text3);
|
font-size:10px;font-weight:600;color:var(--text3);
|
||||||
letter-spacing:.3px;min-width:52px;text-align:center;
|
letter-spacing:.3px;text-align:center;
|
||||||
transition:color .15s,background .15s;
|
transition:color .15s,background .15s;
|
||||||
border:none;background:none;font-family:var(--font);
|
border:none;background:none;font-family:var(--font);
|
||||||
-webkit-tap-highlight-color:transparent;
|
-webkit-tap-highlight-color:transparent;
|
||||||
@@ -384,10 +383,10 @@ nav{flex:1;overflow-y:auto;padding:4px 10px}
|
|||||||
.bnav-item svg{flex-shrink:0;transition:transform .15s}
|
.bnav-item svg{flex-shrink:0;transition:transform .15s}
|
||||||
.bnav-item:active svg{transform:scale(.88)}
|
.bnav-item:active svg{transform:scale(.88)}
|
||||||
/* Tab strip */
|
/* Tab strip */
|
||||||
.bnav-tabs{display:flex;justify-content:center;gap:6px;padding:5px 16px 2px;flex-shrink:0}
|
.bnav-tabs{display:flex;width:100%;padding:4px 8px 2px;flex-shrink:0;gap:4px}
|
||||||
.bnav-tab{flex:1;padding:3px 0;border-radius:7px;border:none;font-family:var(--font);font-size:10px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--text3);cursor:pointer;background:none;transition:color .15s,background .15s;-webkit-tap-highlight-color:transparent}
|
.bnav-tab{flex:1;padding:3px 0;border-radius:7px;border:none;font-family:var(--font);font-size:10px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--text3);cursor:pointer;background:none;transition:color .15s,background .15s;-webkit-tap-highlight-color:transparent}
|
||||||
.bnav-tab.active{background:var(--surface2);color:var(--text)}
|
.bnav-tab.active{background:var(--surface2);color:var(--text)}
|
||||||
.bnav-pages{display:grid;grid-template-columns:repeat(4,1fr);align-items:center;width:100%;gap:6px;flex:1}
|
.bnav-pages{display:grid;grid-template-columns:repeat(4,1fr);align-items:stretch;width:100%;flex:1}
|
||||||
|
|
||||||
@media(max-width:768px){
|
@media(max-width:768px){
|
||||||
.bottom-nav{display:flex;flex-direction:column;justify-content:flex-start}
|
.bottom-nav{display:flex;flex-direction:column;justify-content:flex-start}
|
||||||
@@ -400,8 +399,8 @@ nav{flex:1;overflow-y:auto;padding:4px 10px}
|
|||||||
.preview-bar{bottom:calc(var(--player-h) + 80px)}
|
.preview-bar{bottom:calc(var(--player-h) + 80px)}
|
||||||
.toast-container{bottom:calc(var(--player-h) + 80px + 16px)}
|
.toast-container{bottom:calc(var(--player-h) + 80px + 16px)}
|
||||||
.jobs-panel{bottom:calc(var(--player-h) + 80px + 16px)}
|
.jobs-panel{bottom:calc(var(--player-h) + 80px + 16px)}
|
||||||
.bnav-pages{grid-template-columns:repeat(4,1fr);gap:6px}
|
.bnav-pages{grid-template-columns:repeat(4,1fr)}
|
||||||
.bnav-item{min-width:0;width:100%;padding:8px 0 6px;box-sizing:border-box}
|
.bnav-item{min-width:0;width:100%;padding:6px 2px;box-sizing:border-box}
|
||||||
#settings-modal{align-items:flex-start;padding-top:max(env(safe-area-inset-top),16px);padding-bottom:calc(var(--player-h) + 80px + env(safe-area-inset-bottom) + 8px)}
|
#settings-modal{align-items:flex-start;padding-top:max(env(safe-area-inset-top),16px);padding-bottom:calc(var(--player-h) + 80px + env(safe-area-inset-bottom) + 8px)}
|
||||||
#settings-modal .modal{max-height:100%!important;overflow:hidden}
|
#settings-modal .modal{max-height:100%!important;overflow:hidden}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const CACHE = 'ns-v12';
|
const CACHE = 'ns-v13';
|
||||||
const PRECACHE = ['/', 'index.html', 'styles.css', 'app.js', 'sw.js'];
|
const PRECACHE = ['/', 'index.html', 'styles.css', 'app.js', 'sw.js'];
|
||||||
const SKIP_URLS = ['/rest/stream', '/rest/download', '/config.js'];
|
const SKIP_URLS = ['/rest/stream', '/rest/download', '/config.js'];
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user