Skip to content

Commit b6b523b

Browse files
authored
Merge pull request #114 from nookat-io/sidebar_config
[feat]: Sidebar config
2 parents a09b9da + 762cffd commit b6b523b

File tree

13 files changed

+101
-89
lines changed

13 files changed

+101
-89
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
name: ready-for-review
22
color: "0E8A16"
3-
description: "PR is ready for platform testing and review"
3+
description: "PR is ready for review"

.github/labels/ready-to-merge.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
name: ready-to-merge
2+
color: "1D76DB"
3+
description: "PR is ready for merging to main"

.github/workflows/ci-builds.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ jobs:
4040
exit 0
4141
fi
4242
43-
# Check if PR has ready-for-review label
44-
if [[ "$PR_LABELS" =~ "ready-for-review" ]]; then
43+
# Check if PR has ready-to-merge label
44+
if [[ "$PR_LABELS" =~ "ready-to-merge" ]]; then
4545
echo "should_build=true" >> $GITHUB_OUTPUT
46-
echo "reason=PR has ready-for-review label" >> $GITHUB_OUTPUT
46+
echo "reason=PR has ready-to-merge label" >> $GITHUB_OUTPUT
4747
exit 0
4848
fi
4949

package-lock.json

Lines changed: 0 additions & 79 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,12 @@
2323
"@radix-ui/react-progress": "^1.1.7",
2424
"@radix-ui/react-select": "^2.2.6",
2525
"@radix-ui/react-separator": "^1.1.0",
26-
"@radix-ui/react-slider": "^1.3.6",
2726
"@radix-ui/react-slot": "^1.1.0",
2827
"@radix-ui/react-switch": "^1.2.6",
2928
"@radix-ui/react-tabs": "^1.1.13",
30-
"@radix-ui/react-toast": "^1.2.15",
3129
"@sentry/react": "^10.5.0",
3230
"@tauri-apps/api": "^2",
3331
"@tauri-apps/plugin-autostart": "^2.5.0",
34-
"@tauri-apps/plugin-opener": "^2",
3532
"@tauri-apps/plugin-updater": "^2.9.0",
3633
"class-variance-authority": "^0.7.0",
3734
"clsx": "^2.1.0",

src-tauri/src/entities/config/v2.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub struct AppConfigV2 {
1313
pub language: Language,
1414
pub telemetry: TelemetrySettings,
1515
pub startup: StartupSettings,
16+
pub sidebar_collapsed: bool,
1617
}
1718

1819
impl From<AppConfigV1> for AppConfigV2 {
@@ -22,6 +23,7 @@ impl From<AppConfigV1> for AppConfigV2 {
2223
language: v1.language,
2324
telemetry: v1.telemetry,
2425
startup: v1.startup,
26+
sidebar_collapsed: false,
2527
}
2628
}
2729
}
@@ -77,6 +79,7 @@ mod tests {
7779
language: Language::English,
7880
telemetry: TelemetrySettings::default(),
7981
startup: StartupSettings::default(),
82+
sidebar_collapsed: false,
8083
};
8184

8285
// Serialize to JSON
@@ -94,6 +97,7 @@ mod tests {
9497
language: Language::English,
9598
telemetry: TelemetrySettings::default(),
9699
startup: StartupSettings::default(),
100+
sidebar_collapsed: false,
97101
};
98102

99103
let versioned_config = VersionedAppConfig::V2(v2_config);

src-tauri/src/handlers/config.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,15 @@ pub async fn update_last_update_check() -> Result<(), String> {
8282
UpdaterService::update_last_update_check()
8383
.map_err(|e| format!("Failed to update last update check: {}", e))
8484
}
85+
86+
/// Update sidebar collapsed state
87+
#[tauri::command]
88+
#[instrument(skip_all, err)]
89+
pub async fn update_sidebar_collapsed(sidebar_collapsed: bool) -> Result<(), String> {
90+
debug!("Updating sidebar collapsed state to: {}", sidebar_collapsed);
91+
92+
let mut config = get_config().await?;
93+
config.sidebar_collapsed = sidebar_collapsed;
94+
95+
ConfigService::save_config(&config)
96+
}

src-tauri/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::handlers::{
1414
open_terminal, open_url, pause_container, prune_containers, prune_images, prune_volumes,
1515
remove_container, remove_network, remove_volume, restart_container, start_colima_vm_command,
1616
start_container, stop_container, unpause_container, update_language, update_last_update_check,
17-
update_startup_settings, update_telemetry_settings, update_theme,
17+
update_sidebar_collapsed, update_startup_settings, update_telemetry_settings, update_theme,
1818
};
1919
use crate::sentry::flush_sentry;
2020
use crate::services::ConfigService;
@@ -101,6 +101,7 @@ pub fn run() {
101101
update_language,
102102
update_telemetry_settings,
103103
update_startup_settings,
104+
update_sidebar_collapsed,
104105
update_last_update_check,
105106
// Containers
106107
list_containers,

src-tauri/src/services/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ impl ConfigService {
9595
let config_path = ConfigService::get_config_path()?;
9696

9797
let versioned_config = VersionedAppConfig::from(config.clone());
98+
9899
let content = serde_json::to_string_pretty(&versioned_config)
99100
.map_err(|e| format!("Failed to serialize config: {}", e))?;
100101

src/components/layout/sidebar.tsx

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import { useState } from 'react';
3+
import { useState, useEffect } from 'react';
44
import { Link, useLocation } from 'react-router-dom';
55
import {
66
Container,
@@ -13,6 +13,7 @@ import {
1313
} from 'lucide-react';
1414
import { cn } from '../../lib/utils';
1515
import { Button } from '../ui/button';
16+
import { useConfig } from '../../hooks/use-config';
1617

1718
const navigation = [
1819
{ name: 'Containers', href: '/', icon: Container },
@@ -23,9 +24,39 @@ const navigation = [
2324
];
2425

2526
export function Sidebar() {
27+
const { config, updateSidebarCollapsed } = useConfig();
2628
const [collapsed, setCollapsed] = useState(false);
29+
const [isSaving, setIsSaving] = useState(false);
2730
const location = useLocation();
2831

32+
// Initialize from config whenever config changes
33+
useEffect(() => {
34+
if (config) {
35+
setCollapsed(config.sidebar_collapsed);
36+
}
37+
}, [config]);
38+
39+
const handleToggleCollapsed = async () => {
40+
// Prevent rapid clicks while saving is in progress
41+
if (isSaving) {
42+
return;
43+
}
44+
45+
setIsSaving(true);
46+
47+
try {
48+
// Use functional update to get the latest state value
49+
await updateSidebarCollapsed(!collapsed);
50+
// Update local state only after save succeeds
51+
setCollapsed(prevCollapsed => !prevCollapsed);
52+
} catch (error) {
53+
console.error('Failed to persist sidebar state:', error);
54+
// Keep current state on error - don't update local state
55+
} finally {
56+
setIsSaving(false);
57+
}
58+
};
59+
2960
return (
3061
<div
3162
className={cn(
@@ -50,7 +81,12 @@ export function Sidebar() {
5081
<Button
5182
variant="ghost"
5283
size="sm"
53-
onClick={() => setCollapsed(!collapsed)}
84+
onClick={handleToggleCollapsed}
85+
disabled={isSaving}
86+
aria-busy={isSaving}
87+
aria-pressed={!collapsed}
88+
aria-expanded={!collapsed}
89+
aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
5490
draggable="false"
5591
>
5692
{collapsed ? (

0 commit comments

Comments
 (0)