Skip to content

Commit 86b4b98

Browse files
committed
fix: macOS compatibility - title bar padding, cross-platform vault paths, version display
- Add left padding on macOS for window buttons in title bar - Use dynamic version from package.json in Settings About page - Cross-platform vault paths (~/Documents/BluePDM on macOS, C:\BluePDM on Windows) - Expand ~ to home directory in Electron main process - Fix path separators for rename operations on macOS - Add Supabase secrets to GitHub Actions workflow
1 parent 73afaab commit 86b4b98

File tree

6 files changed

+84
-23
lines changed

6 files changed

+84
-23
lines changed

electron/main.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -506,13 +506,20 @@ ipcMain.handle('working-dir:set', async (_, newPath: string) => {
506506

507507
ipcMain.handle('working-dir:create', async (_, newPath: string) => {
508508
try {
509+
// Expand ~ to home directory on macOS/Linux
510+
let expandedPath = newPath
511+
if (newPath.startsWith('~')) {
512+
const homedir = require('os').homedir()
513+
expandedPath = newPath.replace(/^~/, homedir)
514+
}
515+
509516
// Create the directory if it doesn't exist
510-
if (!fs.existsSync(newPath)) {
511-
fs.mkdirSync(newPath, { recursive: true })
512-
log('Created working directory:', newPath)
517+
if (!fs.existsSync(expandedPath)) {
518+
fs.mkdirSync(expandedPath, { recursive: true })
519+
log('Created working directory:', expandedPath)
513520
}
514-
workingDirectory = newPath
515-
startFileWatcher(newPath)
521+
workingDirectory = expandedPath
522+
startFileWatcher(expandedPath)
516523
return { success: true, path: workingDirectory }
517524
} catch (err) {
518525
log('Error creating working directory:', err)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "blue-pdm",
3-
"version": "0.10.0",
3+
"version": "0.10.1",
44
"description": "Product Data Management for engineering teams",
55
"main": "dist-electron/main.js",
66
"scripts": {

src/components/MenuBar.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export function MenuBar({ minimal = false }: MenuBarProps) {
1717
const [showUserMenu, setShowUserMenu] = useState(false)
1818
const [showSettings, setShowSettings] = useState(false)
1919
const [titleBarPadding, setTitleBarPadding] = useState(140) // Default fallback
20+
const [platform, setPlatform] = useState<string>('win32') // Default to Windows
2021
const [localSearch, setLocalSearch] = useState(searchQuery || '')
2122
const menuRef = useRef<HTMLDivElement>(null)
2223
const searchInputRef = useRef<HTMLInputElement>(null)
@@ -37,6 +38,7 @@ export function MenuBar({ minimal = false }: MenuBarProps) {
3738
useEffect(() => {
3839
if (window.electronAPI) {
3940
window.electronAPI.getVersion().then(setAppVersion)
41+
window.electronAPI.getPlatform().then(setPlatform)
4042
// Get the actual titlebar overlay rect
4143
window.electronAPI.getTitleBarOverlayRect?.().then((rect) => {
4244
if (rect?.width) {
@@ -79,8 +81,11 @@ export function MenuBar({ minimal = false }: MenuBarProps) {
7981

8082
return (
8183
<div className="h-[38px] bg-pdm-activitybar border-b border-pdm-border select-none flex-shrink-0 titlebar-drag-region relative">
82-
{/* Left side - App name */}
83-
<div className="absolute left-0 top-0 h-full flex items-center">
84+
{/* Left side - App name (add padding on macOS for window buttons) */}
85+
<div
86+
className="absolute left-0 top-0 h-full flex items-center"
87+
style={{ paddingLeft: platform === 'darwin' ? 72 : 0 }}
88+
>
8489
<div className="flex items-center gap-2 px-4 titlebar-no-drag">
8590
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" className="text-pdm-accent">
8691
<path
@@ -190,10 +195,10 @@ export function MenuBar({ minimal = false }: MenuBarProps) {
190195
)}
191196
</div>
192197

193-
{/* Right side - Settings and User (with padding for window controls) */}
198+
{/* Right side - Settings and User (with padding for window controls on Windows) */}
194199
<div
195200
className="absolute right-0 top-0 h-full flex items-center gap-2 pl-4 titlebar-no-drag"
196-
style={{ paddingRight: titleBarPadding }}
201+
style={{ paddingRight: platform === 'darwin' ? 16 : titleBarPadding }}
197202
>
198203
{/* Settings gear - hidden on welcome/signin screens */}
199204
{!minimal && (

src/components/SettingsModal.tsx

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@ import {
2929
import { usePDMStore, ConnectedVault } from '../stores/pdmStore'
3030
import { supabase, signOut } from '../lib/supabase'
3131

32+
// Build vault path based on platform
33+
function buildVaultPath(platform: string, vaultSlug: string): string {
34+
if (platform === 'darwin') {
35+
// macOS: ~/Documents/BluePDM/vault-name
36+
return `~/Documents/BluePDM/${vaultSlug}`
37+
} else if (platform === 'linux') {
38+
return `~/BluePDM/${vaultSlug}`
39+
} else {
40+
// Windows: C:\BluePDM\vault-name
41+
return `C:\\BluePDM\\${vaultSlug}`
42+
}
43+
}
44+
3245
type SettingsTab = 'account' | 'vault' | 'organization' | 'preferences' | 'about'
3346

3447
interface OrgUser {
@@ -96,6 +109,16 @@ export function SettingsModal({ onClose }: SettingsModalProps) {
96109
const [isDeleting, setIsDeleting] = useState(false)
97110
const [disconnectingVault, setDisconnectingVault] = useState<{ id: string; name: string } | null>(null)
98111
const [isDisconnecting, setIsDisconnecting] = useState(false)
112+
const [appVersion, setAppVersion] = useState('')
113+
const [platform, setPlatform] = useState<string>('win32')
114+
115+
// Get app version and platform
116+
useEffect(() => {
117+
if (window.electronAPI) {
118+
window.electronAPI.getVersion().then(setAppVersion)
119+
window.electronAPI.getPlatform().then(setPlatform)
120+
}
121+
}, [])
99122

100123
// Load org users and vaults when organization tab is selected
101124
useEffect(() => {
@@ -254,9 +277,11 @@ export function SettingsModal({ onClose }: SettingsModalProps) {
254277
// Rename the local folder too
255278
const api = (window as any).electronAPI
256279
if (api && connectedVault.localPath) {
280+
// Use the same path separator as the original path
281+
const pathSep = connectedVault.localPath.includes('/') ? '/' : '\\'
257282
const pathParts = connectedVault.localPath.split(/[/\\]/)
258283
pathParts[pathParts.length - 1] = newName.replace(/[<>:"/\\|?*]/g, '-')
259-
const newPath = pathParts.join('\\')
284+
const newPath = pathParts.join(pathSep)
260285

261286
if (newPath !== connectedVault.localPath) {
262287
const result = await api.renameItem(connectedVault.localPath, newPath)
@@ -382,8 +407,8 @@ export function SettingsModal({ onClose }: SettingsModalProps) {
382407
return
383408
}
384409

385-
// Create vault folder in C:\BluePDM\ to avoid conflicts with other software
386-
const localPath = `C:\\BluePDM\\${vault.slug}`
410+
// Create vault folder based on platform
411+
const localPath = buildVaultPath(platform, vault.slug)
387412
const result = await api.createWorkingDir(localPath)
388413

389414
if (result.success && result.path) {
@@ -1047,9 +1072,11 @@ export function SettingsModal({ onClose }: SettingsModalProps) {
10471072
<p className="text-pdm-fg-dim mb-2">
10481073
Open source Product Data Management for engineering teams
10491074
</p>
1050-
<p className="text-sm text-pdm-fg-muted">
1051-
Version 0.7.1
1052-
</p>
1075+
{appVersion && (
1076+
<p className="text-sm text-pdm-fg-muted">
1077+
Version {appVersion}
1078+
</p>
1079+
)}
10531080
</div>
10541081

10551082
{/* Links */}

src/components/WelcomeScreen.tsx

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,19 @@ import { FolderPlus, Loader2, HardDrive, WifiOff, LogIn, Check, Settings, Databa
33
import { usePDMStore, ConnectedVault } from '../stores/pdmStore'
44
import { signInWithGoogle, isSupabaseConfigured, supabase } from '../lib/supabase'
55

6+
// Build vault path based on platform
7+
function buildVaultPath(platform: string, vaultSlug: string): string {
8+
if (platform === 'darwin') {
9+
// macOS: ~/Documents/BluePDM/vault-name
10+
return `~/Documents/BluePDM/${vaultSlug}`
11+
} else if (platform === 'linux') {
12+
return `~/BluePDM/${vaultSlug}`
13+
} else {
14+
// Windows: C:\BluePDM\vault-name
15+
return `C:\\BluePDM\\${vaultSlug}`
16+
}
17+
}
18+
619
interface VaultStats {
720
fileCount: number
821
totalSize: number
@@ -51,6 +64,14 @@ export function WelcomeScreen({ onOpenVault, onOpenRecentVault }: WelcomeScreenP
5164
const [orgVaults, setOrgVaults] = useState<Vault[]>([])
5265
const [isLoadingVaults, setIsLoadingVaults] = useState(false)
5366
const [connectingVaultId, setConnectingVaultId] = useState<string | null>(null)
67+
const [platform, setPlatform] = useState<string>('win32')
68+
69+
// Get platform on mount
70+
useEffect(() => {
71+
if (window.electronAPI) {
72+
window.electronAPI.getPlatform().then(setPlatform)
73+
}
74+
}, [])
5475

5576
// Auto-connect on mount if we have connected vaults
5677
useEffect(() => {
@@ -140,8 +161,8 @@ export function WelcomeScreen({ onOpenVault, onOpenRecentVault }: WelcomeScreenP
140161
setConnectingVaultId(vault.id)
141162

142163
try {
143-
// Create vault folder in C:\BluePDM\ to avoid conflicts with other software
144-
const vaultPath = `C:\\BluePDM\\${vault.slug}`
164+
// Create vault folder based on platform
165+
const vaultPath = buildVaultPath(platform, vault.slug)
145166
const result = await window.electronAPI.createWorkingDir(vaultPath)
146167

147168
if (result.success && result.path) {
@@ -179,9 +200,9 @@ export function WelcomeScreen({ onOpenVault, onOpenRecentVault }: WelcomeScreenP
179200
if (recentVaults.length > 0) {
180201
vaultPath = recentVaults[0]
181202
} else if (organization) {
182-
vaultPath = `C:\\BluePDM\\${organization.slug}`
203+
vaultPath = buildVaultPath(platform, organization.slug)
183204
} else {
184-
vaultPath = `C:\\BluePDM\\local-vault`
205+
vaultPath = buildVaultPath(platform, 'local-vault')
185206
}
186207

187208
const result = await window.electronAPI.createWorkingDir(vaultPath)
@@ -473,7 +494,7 @@ export function WelcomeScreen({ onOpenVault, onOpenRecentVault }: WelcomeScreenP
473494
Local Vault
474495
</h2>
475496
<p className="text-xs text-pdm-fg-muted truncate">
476-
{recentVaults[0] || 'C:\\pdm-vault'}
497+
{recentVaults[0] || buildVaultPath(platform, 'local-vault')}
477498
</p>
478499
</div>
479500
</div>

src/components/sidebar/ExplorerView.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,11 @@ export function ExplorerView({ onOpenVault, onOpenRecentVault, onRefresh }: Expl
211211
return
212212
}
213213

214-
// Build new path
214+
// Build new path (use the same path separator as the original)
215+
const pathSep = oldPath.includes('/') ? '/' : '\\'
215216
const pathParts = oldPath.split(/[/\\]/)
216217
pathParts[pathParts.length - 1] = newName
217-
const newPath = pathParts.join('\\')
218+
const newPath = pathParts.join(pathSep)
218219

219220
const result = await window.electronAPI?.moveFile(oldPath, newPath)
220221
if (result?.success) {

0 commit comments

Comments
 (0)