Skip to content

Commit 389da8d

Browse files
committed
feat: update workspace path handling and improve workspace name generation
1 parent 9dcc079 commit 389da8d

8 files changed

Lines changed: 64 additions & 84 deletions

File tree

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ VITE_CONTEXT_WINDOW=160000
3838
# PLATFORM MODE (advanced — most users leave these commented out)
3939
# =============================================================================
4040
# VITE_IS_PLATFORM=false
41-
# WORKSPACES_ROOT=/home/user/projects
41+
# WORKSPACES_ROOT=/home/user/vibelab
4242

4343
# =============================================================================
4444
# INTEGRATIONS (optional)

server/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2274,6 +2274,9 @@ async function startServer() {
22742274
console.log(`${c.tip('[TIP]')} Run "vibelab status" for full configuration details`);
22752275
console.log('');
22762276

2277+
// Ensure the workspaces root directory exists
2278+
await fsPromises.mkdir(WORKSPACES_ROOT, { recursive: true });
2279+
22772280
// Start watching the projects folder for changes
22782281
await setupProjectsWatcher();
22792282
});

server/routes/projects.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function sanitizeGitError(message, token) {
1313
}
1414

1515
// Configure allowed workspace root (defaults to user's home directory)
16-
export const WORKSPACES_ROOT = process.env.WORKSPACES_ROOT || os.homedir();
16+
export const WORKSPACES_ROOT = process.env.WORKSPACES_ROOT || path.join(os.homedir(), 'vibelab');
1717

1818
// System-critical paths that should never be used as workspace directories
1919
export const FORBIDDEN_PATHS = [

src/components/ProjectCreationWizard.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ const ProjectCreationWizard = ({ onClose, onProjectCreated }) => {
7979
setWorkspacePath((currentPath) => (currentPath.trim() ? currentPath : suggestedPath));
8080
} catch (error) {
8181
console.error('Error auto-filling workspace path:', error);
82-
const fallbackPath = `~/${suggestedName}`;
82+
const fallbackPath = `~/vibelab/${suggestedName}`;
8383
setWorkspacePath((currentPath) => (currentPath.trim() ? currentPath : fallbackPath));
8484
}
8585
};

src/components/app/AppContent.tsx

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect } from 'react';
1+
import { useCallback, useEffect, useRef, useState } from 'react';
22
import { useLocation, useNavigate, useParams } from 'react-router-dom';
33
import { useTranslation } from 'react-i18next';
44

@@ -108,11 +108,60 @@ export default function AppContent() {
108108
};
109109
}, [isConnected, sendMessage]);
110110

111+
const SIDEBAR_MIN = 220;
112+
const SIDEBAR_MAX = 480;
113+
const SIDEBAR_DEFAULT = 288; // w-72
114+
const STORAGE_KEY = 'vibelab-sidebar-width';
115+
116+
const [sidebarWidth, setSidebarWidth] = useState(() => {
117+
const saved = localStorage.getItem(STORAGE_KEY);
118+
const parsed = saved ? Number(saved) : NaN;
119+
return Number.isFinite(parsed) && parsed >= SIDEBAR_MIN && parsed <= SIDEBAR_MAX
120+
? parsed
121+
: SIDEBAR_DEFAULT;
122+
});
123+
124+
const isResizing = useRef(false);
125+
126+
const handleResizeStart = useCallback((e: React.MouseEvent) => {
127+
e.preventDefault();
128+
isResizing.current = true;
129+
document.body.style.cursor = 'col-resize';
130+
document.body.style.userSelect = 'none';
131+
132+
const onMouseMove = (ev: MouseEvent) => {
133+
if (!isResizing.current) return;
134+
const newWidth = Math.min(SIDEBAR_MAX, Math.max(SIDEBAR_MIN, ev.clientX));
135+
setSidebarWidth(newWidth);
136+
};
137+
138+
const onMouseUp = () => {
139+
isResizing.current = false;
140+
document.body.style.cursor = '';
141+
document.body.style.userSelect = '';
142+
document.removeEventListener('mousemove', onMouseMove);
143+
document.removeEventListener('mouseup', onMouseUp);
144+
setSidebarWidth((w) => {
145+
localStorage.setItem(STORAGE_KEY, String(w));
146+
return w;
147+
});
148+
};
149+
150+
document.addEventListener('mousemove', onMouseMove);
151+
document.addEventListener('mouseup', onMouseUp);
152+
}, []);
153+
111154
return (
112155
<div className="fixed inset-0 flex bg-background">
113156
{!isMobile ? (
114-
<div className="h-full flex-shrink-0 border-r border-border/50">
115-
<Sidebar {...sidebarSharedProps} />
157+
<div className="h-full flex-shrink-0 relative" style={{ width: sidebarWidth }}>
158+
<div className="h-full border-r border-border/50">
159+
<Sidebar {...sidebarSharedProps} />
160+
</div>
161+
<div
162+
className="absolute top-0 right-0 w-1 h-full cursor-col-resize hover:bg-primary/20 active:bg-primary/30 z-10"
163+
onMouseDown={handleResizeStart}
164+
/>
116165
</div>
117166
) : (
118167
<div

src/components/sidebar/view/Sidebar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ function Sidebar({
137137
try {
138138
const fsResponse = await (api as any).browseFilesystem('~');
139139
const fsData = await fsResponse.json();
140-
const homePath = fsData.path || '~';
140+
const homePath = fsData.path || '~/vibelab';
141141
const name = generateWorkspaceName();
142142
const workspacePath = `${homePath}/${name}`;
143143

src/components/sidebar/view/subcomponents/SidebarContent.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export default function SidebarContent({
4949
}: SidebarContentProps) {
5050
return (
5151
<div
52-
className="h-full flex flex-col bg-background/80 backdrop-blur-sm md:select-none md:w-72"
52+
className="h-full flex flex-col bg-background/80 backdrop-blur-sm md:select-none w-full"
5353
style={{}}
5454
>
5555
<SidebarHeader
Lines changed: 4 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,20 @@
1-
const WORD_LIST = [
2-
'amber',
3-
'aurora',
4-
'breeze',
5-
'bronze',
6-
'canyon',
7-
'cascade',
8-
'cedar',
9-
'cinder',
10-
'clover',
11-
'comet',
12-
'coral',
13-
'cosmos',
14-
'crystal',
15-
'dawn',
16-
'drift',
17-
'echo',
18-
'eclipse',
19-
'ember',
20-
'fern',
21-
'frost',
22-
'galaxy',
23-
'glacier',
24-
'grove',
25-
'harbor',
26-
'horizon',
27-
'indigo',
28-
'iris',
29-
'island',
30-
'jade',
31-
'juniper',
32-
'lagoon',
33-
'lotus',
34-
'marble',
35-
'meadow',
36-
'mist',
37-
'moonbeam',
38-
'nebula',
39-
'nova',
40-
'oasis',
41-
'obsidian',
42-
'orchid',
43-
'pearl',
44-
'pine',
45-
'quartz',
46-
'rainfall',
47-
'reef',
48-
'river',
49-
'saffron',
50-
'sandstone',
51-
'solstice',
52-
'spruce',
53-
'starlight',
54-
'summit',
55-
'sunrise',
56-
'tempest',
57-
'thicket',
58-
'tidal',
59-
'valley',
60-
'violet',
61-
'waterfall',
62-
'willow',
63-
'zenith',
64-
'zephyr'
65-
];
66-
671
const formatDate = (date) => {
682
const year = date.getFullYear();
693
const month = String(date.getMonth() + 1).padStart(2, '0');
704
const day = String(date.getDate()).padStart(2, '0');
71-
return `${year}${month}${day}`;
5+
return `${year}-${month}-${day}`;
726
};
737

748
const formatTime = (date) => {
759
const hours = String(date.getHours()).padStart(2, '0');
7610
const minutes = String(date.getMinutes()).padStart(2, '0');
77-
return `${hours}${minutes}`;
11+
const seconds = String(date.getSeconds()).padStart(2, '0');
12+
return `${hours}-${minutes}-${seconds}`;
7813
};
7914

80-
const pickRandomWord = () => WORD_LIST[Math.floor(Math.random() * WORD_LIST.length)];
81-
8215
export const generateWorkspaceName = () => {
8316
const now = new Date();
84-
return `${pickRandomWord()}-${formatDate(now)}`;
85-
};
86-
87-
export const generateWorkspaceNameWithTime = () => {
88-
const now = new Date();
89-
return `${pickRandomWord()}-${formatDate(now)}-${formatTime(now)}`;
17+
return `proj-${formatDate(now)}-${formatTime(now)}`;
9018
};
9119

9220
export default generateWorkspaceName;

0 commit comments

Comments
 (0)