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 (
-
-
+
+
@@ -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()