diff --git a/package.json b/package.json
index 16fb76526..8f018102c 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "parler-app",
"private": true,
- "version": "0.9.0",
+ "version": "0.9.1",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index 60daba6c6..61648b8cc 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -4101,7 +4101,7 @@ dependencies = [
[[package]]
name = "parler"
-version = "0.9.0"
+version = "0.9.1"
dependencies = [
"anyhow",
"base64 0.22.1",
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index 7d0009968..c1191c707 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "parler"
-version = "0.9.0"
+version = "0.9.1"
description = "Parler"
authors = ["cjpais"]
edition = "2021"
diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index 20ca9cbd9..00660660a 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -523,12 +523,19 @@ pub fn run(cli_args: CliArgs) {
// aborts the whole app (the setup hook runs inside
// applicationDidFinishLaunching, where panics cannot unwind).
if app.get_webview_window("main").is_none() {
+ // Dev builds (productName "ParlerDev") get a distinct window
+ // title so the window can't be mistaken for a production Parler.
+ let window_title = if app.package_info().name.ends_with("Dev") {
+ "Parler Dev"
+ } else {
+ "Parler"
+ };
let mut win_builder = tauri::WebviewWindowBuilder::new(
app,
"main",
tauri::WebviewUrl::App("/".into()),
)
- .title("Parler")
+ .title(window_title)
.inner_size(680.0, 570.0)
.min_inner_size(680.0, 570.0)
.resizable(true)
diff --git a/src-tauri/src/shortcut/handy_keys.rs b/src-tauri/src/shortcut/handy_keys.rs
index 995288e77..a9ecfcc3e 100644
--- a/src-tauri/src/shortcut/handy_keys.rs
+++ b/src-tauri/src/shortcut/handy_keys.rs
@@ -36,9 +36,11 @@ use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{self, Receiver, Sender};
use std::sync::{Arc, Mutex};
use std::thread::{self, JoinHandle};
+use std::time::{Duration, Instant};
use tauri::{AppHandle, Emitter, Manager};
use crate::settings::{self, get_settings, ShortcutBinding};
+use crate::transcription_coordinator::is_transcribe_binding;
use super::handler::handle_shortcut_event;
@@ -56,6 +58,14 @@ enum ManagerCommand {
Shutdown,
}
+/// Maximum duration a binding-recording session may suppress global shortcuts.
+///
+/// Safety net: if the frontend never calls `stop_recording` (e.g. the webview
+/// crashes mid-recording), suppression auto-expires after this window instead
+/// of leaving every global shortcut disabled until the app restarts. Recording
+/// a shortcut takes a second or two, so this is far longer than any real use.
+const MAX_RECORDING_DURATION: Duration = Duration::from_secs(30);
+
/// State for the handy-keys shortcut manager
pub struct HandyKeysState {
/// Channel to send commands to the manager thread (wrapped in Mutex for Sync)
@@ -64,8 +74,14 @@ pub struct HandyKeysState {
thread_handle: Mutex