Update version to 0.1.3

Add daemon version check and restart logic

Add pane count to CenterToolbar

Add minSlots filter to PresetPicker
This commit is contained in:
2026-06-15 16:32:25 +07:00
parent ce6a8d56be
commit 0a67f401c4
8 changed files with 65 additions and 15 deletions
+1 -1
View File
@@ -3440,7 +3440,7 @@ dependencies = [
[[package]]
name = "spacesh-proto"
version = "0.1.2"
version = "0.1.3"
dependencies = [
"bytes",
"serde",
+50 -2
View File
@@ -78,6 +78,13 @@ fn find_daemon() -> PathBuf {
PathBuf::from("spaceshd") // last resort: rely on PATH
}
/// The installed `spaceshd` binary's mtime as ms since the epoch (for staleness check).
fn daemon_bin_mtime_ms() -> Option<u64> {
let meta = std::fs::metadata(find_daemon()).ok()?;
let mtime = meta.modified().ok()?;
Some(mtime.duration_since(std::time::UNIX_EPOCH).ok()?.as_millis() as u64)
}
async fn ensure_daemon(sock: &PathBuf) -> Result<UnixStream> {
if let Ok(s) = UnixStream::connect(sock).await {
return Ok(s);
@@ -120,7 +127,7 @@ impl Bridge {
let pending: Arc<Mutex<HashMap<u64, oneshot::Sender<Envelope>>>> = Arc::default();
let out_channels: Arc<Mutex<HashMap<String, Channel<Vec<u8>>>>> = Arc::default();
let (tx, reader) = spawn_connection(&sock, &app, pending.clone(), out_channels.clone()).await?;
Ok(Self {
let bridge = Self {
next_id: AtomicU64::new(1),
app,
sock,
@@ -130,7 +137,48 @@ impl Bridge {
reader: Mutex::new(reader),
pending,
out_channels,
})
};
// The daemon outlives the GUI by design, so after an update the GUI may
// attach to a stale daemon — new features that need new daemon code then
// silently don't work. Restart it if it's out of date.
bridge.ensure_matching_daemon().await;
Ok(bridge)
}
/// Restart the running daemon if it predates the installed `spaceshd` binary
/// (or was built from a different commit). The bundled binary's mtime vs the
/// daemon's `started_at_ms` is the reliable signal: it catches every reinstall
/// even while developing dirty, where the git build id doesn't change.
async fn ensure_matching_daemon(&self) {
let Ok(reply) = self.request(Cmd::Health).await else { return };
let (daemon_build, started_at_ms) = match &reply {
Envelope::Res { data, .. } => (
data.get("build").and_then(|v| v.as_str()).map(str::to_string),
data.get("started_at_ms").and_then(|v| v.as_u64()),
),
_ => (None, None),
};
let gui_build = option_env!("SPACESH_BUILD").unwrap_or("dev");
let build_mismatch = gui_build != "dev"
&& daemon_build.as_deref().map(|b| b != gui_build).unwrap_or(false);
let binary_newer = match (daemon_bin_mtime_ms(), started_at_ms) {
(Some(bin_ms), Some(start_ms)) => bin_ms > start_ms,
_ => false,
};
if !build_mismatch && !binary_newer {
return;
}
// Ask the stale daemon to exit, wait for its socket to clear, then reconnect
// — which lazily spawns the fresh bundled daemon.
self.fire(Cmd::Shutdown).await;
for _ in 0..100 {
if UnixStream::connect(&self.sock).await.is_err() {
break;
}
tokio::time::sleep(Duration::from_millis(30)).await;
}
let seen = self.gen.load(Ordering::Acquire);
let _ = self.reconnect(seen).await;
}
/// Send a command without awaiting a reply or retrying. Used for Shutdown:
+1 -1
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "spacesh",
"version": "0.1.2",
"version": "0.1.3",
"identifier": "xyz.spacesh.app",
"build": {
"frontendDist": "../dist",