diff --git a/camelid-desktop/Info.plist b/camelid-desktop/Info.plist new file mode 100644 index 00000000..08a1e096 --- /dev/null +++ b/camelid-desktop/Info.plist @@ -0,0 +1,8 @@ + + + + + NSRemovableVolumesUsageDescription + Camelid reads local model files from folders you select on external drives. + + diff --git a/camelid-desktop/tauri.conf.json b/camelid-desktop/tauri.conf.json index f60f6b49..e1681508 100644 --- a/camelid-desktop/tauri.conf.json +++ b/camelid-desktop/tauri.conf.json @@ -18,9 +18,7 @@ "minHeight": 560, "center": true, "backgroundColor": "#0e1216", - "url": "index.html", - "titleBarStyle": "Overlay", - "hiddenTitle": true + "url": "index.html" } ], "security": { diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index cde0103c..4364548d 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -7,7 +7,6 @@ import { Notice } from './components/ui/Notice' import { ConfirmDialog } from './components/ui/ConfirmDialog' import { isFirstRunHost } from './lib/firstRunActivation' import { formatPreview, formatSidebarDate } from './lib/formatters' -import { hasOverlayTitleBar } from './lib/desktopShell' import { useDashboardData } from './hooks/useDashboardData' import { useBackendLauncher } from './hooks/useBackendLauncher' import { useNotice } from './hooks/useNotice' @@ -246,14 +245,10 @@ function App() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [loadDashboard]) - /* Above the loading early-return: every hook must run on every render, and - the shell this window lives in cannot change while it is open. */ - const [overlayTitleBar] = useState(hasOverlayTitleBar) - if (!dashboard) { return ( -
-
+
+
Loading Camelid…
@@ -266,17 +261,10 @@ function App() { sidebarCollapsed ? 'is-collapsed' : '', mobileNavOpen ? 'is-mobile-open' : '', DEMO_UI ? 'is-demo' : '', - overlayTitleBar ? 'has-overlay-chrome' : '', ].filter(Boolean).join(' ') return (
- {/* macOS desktop only: the window draws no title bar of its own, so the - traffic lights float over the top-left of our content. This strip is - the room they sit in and the surface the window is dragged by — - without it the app showed the OS bar stacked above our own header, - which is what makes an app look like a web page in a frame. */} - {overlayTitleBar &&
} {!DEMO_UI && ( { + let metadata_path = path.clone(); + let parsed = tokio::time::timeout( + Duration::from_secs(5), + tokio::task::spawn_blocking(move || read_metadata(&metadata_path)), + ) + .await; + match parsed { + Ok(Ok(Ok(gguf))) => { c.embedding_capable = is_embedding_model(&gguf); c.generation_capable = is_generation_model(&gguf); let quant = crate::runnable::headline_quant_of(&gguf); @@ -32951,7 +32957,18 @@ async fn local_models( } } } - Err(err) => c.admission_reason = Some(format!("GGUF parse failed: {err}")), + Ok(Ok(Err(err))) => { + c.admission_reason = Some(format!("GGUF parse failed: {err}")); + } + Ok(Err(err)) => { + c.admission_reason = Some(format!("GGUF metadata task failed: {err}")); + } + Err(_) => { + c.admission_reason = Some( + "GGUF metadata scan timed out; removable-volume access may still need approval" + .to_string(), + ); + } } local_meta_cache() .lock()