feat: add default theme option and fix toast z-index, add error styling to start screen inputs
This commit is contained in:
@@ -1 +1 @@
|
|||||||
NEXT_PUBLIC_COMMIT_SHA=4721c05
|
NEXT_PUBLIC_COMMIT_SHA=88c31c5
|
||||||
|
|||||||
12
.github/workflows/release.yml
vendored
12
.github/workflows/release.yml
vendored
@@ -82,9 +82,9 @@ jobs:
|
|||||||
type=gha,mode=max,scope=deps-only
|
type=gha,mode=max,scope=deps-only
|
||||||
|
|
||||||
|
|
||||||
# - name: Docker Hub Description
|
- name: Docker Hub Description
|
||||||
# uses: peter-evans/dockerhub-description@v4
|
uses: peter-evans/dockerhub-description@v4
|
||||||
# with:
|
with:
|
||||||
# username: ${{ vars.DOCKERHUB_USERNAME }}
|
username: sillyangel
|
||||||
# password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
# repository: sillyangel/mice
|
repository: sillyangel/mice
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export function LoginForm({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [isTesting, setIsTesting] = useState(false);
|
const [isTesting, setIsTesting] = useState(false);
|
||||||
|
const [hasError, setHasError] = useState(false);
|
||||||
|
|
||||||
// Settings for step 2
|
// Settings for step 2
|
||||||
const [scrobblingEnabled, setScrobblingEnabled] = useState(() => {
|
const [scrobblingEnabled, setScrobblingEnabled] = useState(() => {
|
||||||
@@ -45,21 +46,7 @@ export function LoginForm({
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sidebar shortcuts setting - default to 'playlists'
|
// New settings - removed sidebar and standalone lastfm options
|
||||||
const [sidebarShortcuts, setSidebarShortcuts] = useState(() => {
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
const saved = localStorage.getItem('sidebar-layout-settings');
|
|
||||||
if (saved) {
|
|
||||||
try {
|
|
||||||
const parsed = JSON.parse(saved);
|
|
||||||
return parsed.shortcuts || 'playlists';
|
|
||||||
} catch (e) {
|
|
||||||
return 'playlists';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 'playlists';
|
|
||||||
});
|
|
||||||
|
|
||||||
// Check if Navidrome is configured via environment variables
|
// Check if Navidrome is configured via environment variables
|
||||||
const hasEnvConfig = React.useMemo(() => {
|
const hasEnvConfig = React.useMemo(() => {
|
||||||
@@ -133,6 +120,7 @@ export function LoginForm({
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (!formData.serverUrl || !formData.username || !formData.password) {
|
if (!formData.serverUrl || !formData.username || !formData.password) {
|
||||||
|
setHasError(true);
|
||||||
toast({
|
toast({
|
||||||
title: "Missing Information",
|
title: "Missing Information",
|
||||||
description: "Please fill in all fields before proceeding.",
|
description: "Please fill in all fields before proceeding.",
|
||||||
@@ -142,6 +130,7 @@ export function LoginForm({
|
|||||||
}
|
}
|
||||||
|
|
||||||
setIsTesting(true);
|
setIsTesting(true);
|
||||||
|
setHasError(false);
|
||||||
try {
|
try {
|
||||||
// Strip trailing slash from server URL before testing
|
// Strip trailing slash from server URL before testing
|
||||||
const cleanServerUrl = formData.serverUrl.replace(/\/+$/, '');
|
const cleanServerUrl = formData.serverUrl.replace(/\/+$/, '');
|
||||||
@@ -168,6 +157,7 @@ export function LoginForm({
|
|||||||
// Move to settings step
|
// Move to settings step
|
||||||
setStep('settings');
|
setStep('settings');
|
||||||
} else {
|
} else {
|
||||||
|
setHasError(true);
|
||||||
toast({
|
toast({
|
||||||
title: "Connection Failed",
|
title: "Connection Failed",
|
||||||
description: "Could not connect to the server. Please check your settings.",
|
description: "Could not connect to the server. Please check your settings.",
|
||||||
@@ -175,6 +165,7 @@ export function LoginForm({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
setHasError(true);
|
||||||
toast({
|
toast({
|
||||||
title: "Connection Error",
|
title: "Connection Error",
|
||||||
description: "An error occurred while testing the connection.",
|
description: "An error occurred while testing the connection.",
|
||||||
@@ -189,23 +180,6 @@ export function LoginForm({
|
|||||||
// Save all settings
|
// Save all settings
|
||||||
localStorage.setItem('lastfm-scrobbling-enabled', scrobblingEnabled.toString());
|
localStorage.setItem('lastfm-scrobbling-enabled', scrobblingEnabled.toString());
|
||||||
|
|
||||||
// Save sidebar settings with default items
|
|
||||||
const defaultItems = [
|
|
||||||
{"id":"home","label":"Home","visible":true,"icon":"home","href":"/"},
|
|
||||||
{"id":"queue","label":"Queue","visible":true,"icon":"queue","href":"/queue"},
|
|
||||||
{"id":"artists","label":"Artists","visible":true,"icon":"artists","href":"/library/artists"},
|
|
||||||
{"id":"albums","label":"Albums","visible":true,"icon":"albums","href":"/library/albums"},
|
|
||||||
{"id":"playlists","label":"Playlists","visible":true,"icon":"playlists","href":"/library/playlists"},
|
|
||||||
{"id":"favorites","label":"Favorites","visible":true,"icon":"favorites","href":"/favorites"},
|
|
||||||
{"id":"settings","label":"Settings","visible":true,"icon":"settings","href":"/settings"}
|
|
||||||
];
|
|
||||||
|
|
||||||
localStorage.setItem('sidebar-layout-settings', JSON.stringify({
|
|
||||||
items: defaultItems,
|
|
||||||
shortcuts: sidebarShortcuts,
|
|
||||||
showIcons: true
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Mark onboarding as complete
|
// Mark onboarding as complete
|
||||||
localStorage.setItem('onboarding-completed', '1.1.0');
|
localStorage.setItem('onboarding-completed', '1.1.0');
|
||||||
|
|
||||||
@@ -286,11 +260,12 @@ export function LoginForm({
|
|||||||
<span>
|
<span>
|
||||||
<Label htmlFor="theme">Theme</Label>
|
<Label htmlFor="theme">Theme</Label>
|
||||||
</span>
|
</span>
|
||||||
<Select value={theme || "blue"} onValueChange={setTheme}>
|
<Select value={theme} onValueChange={setTheme}>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder="Select a theme" />
|
<SelectValue placeholder="Select a theme" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
|
<SelectItem value="default">Default</SelectItem>
|
||||||
<SelectItem value="blue">Blue</SelectItem>
|
<SelectItem value="blue">Blue</SelectItem>
|
||||||
<SelectItem value="violet">Violet</SelectItem>
|
<SelectItem value="violet">Violet</SelectItem>
|
||||||
<SelectItem value="red">Red</SelectItem>
|
<SelectItem value="red">Red</SelectItem>
|
||||||
@@ -327,28 +302,6 @@ export function LoginForm({
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Sidebar Shortcuts Selection */}
|
|
||||||
<div className="grid gap-3">
|
|
||||||
<Label htmlFor="sidebar-shortcuts">Sidebar Shortcuts</Label>
|
|
||||||
<Select value={sidebarShortcuts} onValueChange={setSidebarShortcuts}>
|
|
||||||
<SelectTrigger>
|
|
||||||
<SelectValue />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value="playlists">Playlists Only</SelectItem>
|
|
||||||
<SelectItem value="both">Playlists + Artists</SelectItem>
|
|
||||||
<SelectItem value="none">None</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
{sidebarShortcuts === 'playlists'
|
|
||||||
? "Show only playlist shortcuts in the sidebar"
|
|
||||||
: sidebarShortcuts === 'both'
|
|
||||||
? "Show both playlist and artist shortcuts in the sidebar"
|
|
||||||
: "Hide all shortcuts from the sidebar"}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col gap-3">
|
<div className="flex flex-col gap-3">
|
||||||
<Button onClick={handleFinishSetup} className="w-full">
|
<Button onClick={handleFinishSetup} className="w-full">
|
||||||
<FaCheck className="w-4 h-4 mr-2" />
|
<FaCheck className="w-4 h-4 mr-2" />
|
||||||
@@ -402,6 +355,7 @@ export function LoginForm({
|
|||||||
placeholder="https://your-navidrome-server.com"
|
placeholder="https://your-navidrome-server.com"
|
||||||
value={formData.serverUrl}
|
value={formData.serverUrl}
|
||||||
onChange={(e) => handleInputChange('serverUrl', e.target.value)}
|
onChange={(e) => handleInputChange('serverUrl', e.target.value)}
|
||||||
|
className={hasError ? "border-destructive focus-visible:ring-destructive" : ""}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -416,6 +370,7 @@ export function LoginForm({
|
|||||||
placeholder="your-username"
|
placeholder="your-username"
|
||||||
value={formData.username}
|
value={formData.username}
|
||||||
onChange={(e) => handleInputChange('username', e.target.value)}
|
onChange={(e) => handleInputChange('username', e.target.value)}
|
||||||
|
className={hasError ? "border-destructive focus-visible:ring-destructive" : ""}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -429,6 +384,7 @@ export function LoginForm({
|
|||||||
type="password"
|
type="password"
|
||||||
value={formData.password}
|
value={formData.password}
|
||||||
onChange={(e) => handleInputChange('password', e.target.value)}
|
onChange={(e) => handleInputChange('password', e.target.value)}
|
||||||
|
className={hasError ? "border-destructive focus-visible:ring-destructive" : ""}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user