Added "Start Hidden" (#105)

* Added "Start Hidden"

* revert visible option in tauri conf

---------

Co-authored-by: CJ Pais <cj@cjpais.com>
This commit is contained in:
Dylan 2025-09-06 17:07:33 -04:00 committed by GitHub
parent 76785d5b47
commit b82b3b2f20
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 82 additions and 0 deletions

View file

@ -91,6 +91,14 @@ pub fn run() {
))
.manage(Mutex::new(ShortcutToggleStates::default()))
.setup(move |app| {
// Apply macOS Accessory policy early if starting hidden
#[cfg(target_os = "macos")]
{
let settings = settings::get_settings(&app.handle());
if settings.start_hidden {
let _ = app.set_activation_policy(tauri::ActivationPolicy::Accessory);
}
}
// Get the current theme to set the appropriate initial icon
let initial_theme = tray::get_current_theme(&app.handle());
@ -134,6 +142,17 @@ pub fn run() {
// Enable autostart
let _ = autostart_manager.enable();
// Window is configured to start hidden to avoid flicker.
// If user didn't choose Start Hidden, show it now.
let settings = settings::get_settings(&app.handle());
if settings.start_hidden {
if let Some(main_window) = app.get_webview_window("main") {
let _ = main_window.hide();
}
} else {
show_main_window(&app.handle());
}
let recording_manager = Arc::new(
AudioRecordingManager::new(app).expect("Failed to initialize recording manager"),
);
@ -185,6 +204,7 @@ pub fn run() {
shortcut::reset_binding,
shortcut::change_ptt_setting,
shortcut::change_audio_feedback_setting,
shortcut::change_start_hidden_setting,
shortcut::change_translate_to_english_setting,
shortcut::change_selected_language_setting,
shortcut::change_overlay_position_setting,

View file

@ -69,6 +69,8 @@ pub struct AppSettings {
pub bindings: HashMap<String, ShortcutBinding>,
pub push_to_talk: bool,
pub audio_feedback: bool,
#[serde(default = "default_start_hidden")]
pub start_hidden: bool,
#[serde(default = "default_model")]
pub selected_model: String,
#[serde(default = "default_always_on_microphone")]
@ -105,6 +107,10 @@ fn default_translate_to_english() -> bool {
false
}
fn default_start_hidden() -> bool {
false
}
fn default_selected_language() -> String {
"auto".to_string()
}
@ -149,6 +155,7 @@ pub fn get_default_settings() -> AppSettings {
bindings,
push_to_talk: true,
audio_feedback: false,
start_hidden: default_start_hidden(),
selected_model: "".to_string(),
always_on_microphone: false,
selected_microphone: None,

View file

@ -173,6 +173,24 @@ pub fn change_debug_mode_setting(app: AppHandle, enabled: bool) -> Result<(), St
Ok(())
}
#[tauri::command]
pub fn change_start_hidden_setting(app: AppHandle, enabled: bool) -> Result<(), String> {
let mut settings = settings::get_settings(&app);
settings.start_hidden = enabled;
settings::write_settings(&app, settings);
// Notify frontend
let _ = app.emit(
"settings-changed",
serde_json::json!({
"setting": "start_hidden",
"value": enabled
}),
);
Ok(())
}
#[tauri::command]
pub fn update_custom_words(app: AppHandle, words: Vec<String>) -> Result<(), String> {
let mut settings = settings::get_settings(&app);

View file

@ -5,11 +5,13 @@ import { ModelUnloadTimeoutSetting } from "./ModelUnloadTimeout";
import { CustomWords } from "./CustomWords";
import { AlwaysOnMicrophone } from "./AlwaysOnMicrophone";
import { SettingsGroup } from "../ui/SettingsGroup";
import { StartHidden } from "./StartHidden";
export const AdvancedSettings: React.FC = () => {
return (
<div className="max-w-3xl w-full mx-auto space-y-6">
<SettingsGroup title="Advanced">
<StartHidden descriptionMode="tooltip" grouped={true} />
<ShowOverlay descriptionMode="tooltip" grouped={true} />
<TranslateToEnglish descriptionMode="tooltip" grouped={true} />
<ModelUnloadTimeoutSetting descriptionMode="tooltip" grouped={true} />

View file

@ -0,0 +1,29 @@
import React from "react";
import { ToggleSwitch } from "../ui/ToggleSwitch";
import { useSettings } from "../../hooks/useSettings";
interface StartHiddenProps {
descriptionMode?: "inline" | "tooltip";
grouped?: boolean;
}
export const StartHidden: React.FC<StartHiddenProps> = React.memo(({
descriptionMode = "tooltip",
grouped = false,
}) => {
const { getSetting, updateSetting, isUpdating } = useSettings();
const startHidden = getSetting("start_hidden") ?? false;
return (
<ToggleSwitch
checked={startHidden}
onChange={(enabled) => updateSetting("start_hidden", enabled)}
isUpdating={isUpdating("start_hidden")}
label="Start Hidden"
description="Launch to system tray without opening the window."
descriptionMode={descriptionMode}
grouped={grouped}
/>
);
});

View file

@ -17,3 +17,4 @@ export { TranslateToEnglish } from "./TranslateToEnglish";
export { CustomWords } from "./CustomWords";
export { AppDataDirectory } from "./AppDataDirectory";
export { ModelUnloadTimeoutSetting } from "./ModelUnloadTimeout";
export { StartHidden } from "./StartHidden";

View file

@ -38,6 +38,7 @@ export const SettingsSchema = z.object({
bindings: ShortcutBindingsMapSchema,
push_to_talk: z.boolean(),
audio_feedback: z.boolean(),
start_hidden: z.boolean().optional().default(false),
selected_model: z.string(),
always_on_microphone: z.boolean(),
selected_microphone: z.string().nullable().optional(),

View file

@ -33,6 +33,7 @@ interface SettingsStore {
const DEFAULT_SETTINGS: Partial<Settings> = {
always_on_microphone: false,
audio_feedback: true,
start_hidden: false,
push_to_talk: false,
selected_microphone: "Default",
selected_output_device: "Default",
@ -162,6 +163,9 @@ export const useSettingsStore = create<SettingsStore>()(
case "audio_feedback":
await invoke("change_audio_feedback_setting", { enabled: value });
break;
case "start_hidden":
await invoke("change_start_hidden_setting", { enabled: value });
break;
case "push_to_talk":
await invoke("change_ptt_setting", { enabled: value });
break;