Skip to content

Commit 2f77ca4

Browse files
committed
Implement auto-launch feature and enhance localization
- Added a new `run_on_startup` setting to allow users to enable or disable automatic launching of Mantle on system startup. - Implemented UI elements for managing the auto-launch setting, including success and error notifications. - Updated localization files in German, English, Spanish, French, Portuguese, and Simplified Chinese to include new strings related to the auto-launch feature and its settings.
1 parent 73733a7 commit 2f77ca4

10 files changed

Lines changed: 328 additions & 16 deletions

File tree

Cargo.lock

Lines changed: 234 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ tray-icon = "0.22.0"
4141
rfd = "0.17.2"
4242
anyhow = "1.0.102"
4343
rust-i18n = "3"
44+
auto-launch = "0.6.0"
4445

4546
[target.'cfg(target_os = "linux")'.dependencies]
4647
gtk = "0.18"

locales/de.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ settings.refresh_rate: "Bildwiederholrate:"
169169
settings.refresh_rate_hover: "Wie oft LIFX-Geräte auf Statusaktualisierungen abgefragt werden sollen"
170170
settings.ms: "ms"
171171
settings.samples: "Samples"
172+
settings.run_on_startup: "Beim Start ausführen"
173+
settings.run_on_startup_hover: "Mantle automatisch beim Anmelden starten"
174+
settings.startup_enabled: "Mantle wird beim Anmelden gestartet"
175+
settings.startup_disabled: "Mantle wird nicht mehr beim Anmelden gestartet"
172176

173177
# Szenenplanung
174178
schedule.title: "Szenenplanung"
@@ -239,6 +243,7 @@ error.serialize_scenes: "Fehler beim Serialisieren der Szenen: %{error}"
239243
error.invalid_scene_file: "Ungültige Szenendatei: %{error}"
240244
error.read_file: "Fehler beim Lesen der Datei: %{error}"
241245
error.apply_scene: "Fehler beim Anwenden der Szene: %{errors}"
246+
error.startup: "Fehler beim Aktualisieren der Starteinstellung: %{error}"
242247

243248
# Fehler beim Anwenden von Szenen
244249
error.bulb_color: "Fehler beim Festlegen der Farbe für die Lampe: %{error}"

locales/en.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ settings.refresh_rate: "Refresh Rate:"
169169
settings.refresh_rate_hover: "How often to poll LIFX devices for status updates"
170170
settings.ms: "ms"
171171
settings.samples: "samples"
172+
settings.run_on_startup: "Run on startup"
173+
settings.run_on_startup_hover: "Automatically start Mantle when you log in"
174+
settings.startup_enabled: "Mantle will now start on login"
175+
settings.startup_disabled: "Mantle will no longer start on login"
172176

173177
# Scene schedule
174178
schedule.title: "Scene Schedule"
@@ -239,6 +243,7 @@ error.serialize_scenes: "Failed to serialize scenes: %{error}"
239243
error.invalid_scene_file: "Invalid scene file: %{error}"
240244
error.read_file: "Failed to read file: %{error}"
241245
error.apply_scene: "Failed to apply scene: %{errors}"
246+
error.startup: "Failed to update startup setting: %{error}"
242247

243248
# Scene apply errors
244249
error.bulb_color: "Failed to set color for bulb: %{error}"

locales/es.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ settings.refresh_rate: "Frecuencia de actualización:"
169169
settings.refresh_rate_hover: "Con qué frecuencia consultar los dispositivos LIFX para obtener actualizaciones de estado"
170170
settings.ms: "ms"
171171
settings.samples: "muestras"
172+
settings.run_on_startup: "Iniciar con el sistema"
173+
settings.run_on_startup_hover: "Iniciar Mantle automáticamente al iniciar sesión"
174+
settings.startup_enabled: "Mantle se iniciará con el sistema"
175+
settings.startup_disabled: "Mantle ya no se iniciará con el sistema"
172176

173177
# Programación de escenas
174178
schedule.title: "Programación de escenas"
@@ -239,6 +243,7 @@ error.serialize_scenes: "No se pudieron serializar las escenas: %{error}"
239243
error.invalid_scene_file: "Archivo de escena no válido: %{error}"
240244
error.read_file: "No se pudo leer el archivo: %{error}"
241245
error.apply_scene: "No se pudo aplicar la escena: %{errors}"
246+
error.startup: "Error al actualizar la configuración de inicio: %{error}"
242247

243248
# Aplicación de escena errores
244249
error.bulb_color: "No se pudo establecer el color de la bombilla: %{error}"

locales/fr.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ settings.refresh_rate: "Taux de rafraîchissement :"
169169
settings.refresh_rate_hover: "Fréquence d'interrogation des appareils LIFX pour les mises à jour de statut"
170170
settings.ms: "ms"
171171
settings.samples: "échantillons"
172+
settings.run_on_startup: "Lancer au démarrage"
173+
settings.run_on_startup_hover: "Lancer Mantle automatiquement à la connexion"
174+
settings.startup_enabled: "Mantle se lancera à la connexion"
175+
settings.startup_disabled: "Mantle ne se lancera plus à la connexion"
172176

173177
# Planification des scènes
174178
schedule.title: "Planification des scènes"
@@ -239,6 +243,7 @@ error.serialize_scenes: "Échec de la sérialisation des scènes : %{error}"
239243
error.invalid_scene_file: "Fichier de scène invalide : %{error}"
240244
error.read_file: "Échec de la lecture du fichier : %{error}"
241245
error.apply_scene: "Échec de l'application de la scène : %{errors}"
246+
error.startup: "Échec de la mise à jour du paramètre de démarrage : %{error}"
242247

243248
# Erreurs d'application de scène
244249
error.bulb_color: "Échec de la définition de la couleur de l'ampoule : %{error}"

locales/pt-BR.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ settings.refresh_rate: "Taxa de Atualização de Status:"
169169
settings.refresh_rate_hover: "Com que frequência consultar os dispositivos LIFX para atualizações de status"
170170
settings.ms: "ms"
171171
settings.samples: "amostras"
172+
settings.run_on_startup: "Iniciar com o sistema"
173+
settings.run_on_startup_hover: "Iniciar o Mantle automaticamente ao fazer login"
174+
settings.startup_enabled: "O Mantle será iniciado no login"
175+
settings.startup_disabled: "O Mantle não será mais iniciado no login"
172176

173177
# Agendamento de Cenas
174178
schedule.title: "Agendamento de Cenas"
@@ -239,6 +243,7 @@ error.serialize_scenes: "Falha ao serializar cenas: %{error}"
239243
error.invalid_scene_file: "Arquivo de cena inválido: %{error}"
240244
error.read_file: "Falha ao ler arquivo: %{error}"
241245
error.apply_scene: "Falha ao aplicar cena: %{errors}"
246+
error.startup: "Falha ao atualizar configuração de inicialização: %{error}"
242247

243248
# Erros de aplicação de cena
244249
error.bulb_color: "Falha ao definir a cor da lâmpada: %{error}"

locales/zh-CN.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ settings.refresh_rate: "刷新频率:"
169169
settings.refresh_rate_hover: "轮询 LIFX 设备以获取状态更新的频率"
170170
settings.ms: "毫秒"
171171
settings.samples: "采样"
172+
settings.run_on_startup: "开机自启动"
173+
settings.run_on_startup_hover: "登录时自动启动 Mantle"
174+
settings.startup_enabled: "Mantle 将在登录时自动启动"
175+
settings.startup_disabled: "Mantle 将不再在登录时自动启动"
172176

173177
# 场景日程
174178
schedule.title: "场景日程"
@@ -239,6 +243,7 @@ error.serialize_scenes: "序列化场景失败:%{error}"
239243
error.invalid_scene_file: "无效的场景文件:%{error}"
240244
error.read_file: "读取文件失败:%{error}"
241245
error.apply_scene: "应用场景失败: %{errors}"
246+
error.startup: "更新启动设置失败:%{error}"
242247

243248
# 场景应用错误
244249
error.bulb_color: "无法设置灯泡颜色:%{error}"

src/app.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,12 @@ impl MantleApp {
313313
details = format!("{:?}", failures)
314314
));
315315
}
316+
app.sync_auto_launch_state();
316317
app.setup_tray_icon(&cc.egui_ctx);
317318
return app;
318319
}
319320
let mut app = Self::default();
321+
app.sync_auto_launch_state();
320322
app.setup_tray_icon(&cc.egui_ctx);
321323
app
322324
}

src/settings.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ pub struct Settings {
3636
pub audio_buffer_size: usize,
3737
#[serde(default)]
3838
pub custom_colors: Vec<(String, HSBK32)>,
39+
#[serde(default)]
40+
pub run_on_startup: bool,
3941
}
4042

4143
impl Default for Settings {
@@ -50,6 +52,7 @@ impl Default for Settings {
5052
scheduled_scenes: Vec::new(),
5153
audio_buffer_size: AUDIO_BUFFER_DEFAULT,
5254
custom_colors: Vec::new(),
55+
run_on_startup: false,
5356
}
5457
}
5558
}
@@ -82,6 +85,8 @@ impl MantleApp {
8285

8386
self.render_locale_selector(ui);
8487

88+
self.render_run_on_startup(ui);
89+
8590
self.render_refresh_rate(ui);
8691

8792
self.render_update_rate(ui);
@@ -364,6 +369,60 @@ impl MantleApp {
364369
});
365370
}
366371

372+
fn render_run_on_startup(&mut self, ui: &mut egui::Ui) {
373+
let mut run_on_startup = self.settings.run_on_startup;
374+
if ui
375+
.checkbox(
376+
&mut run_on_startup,
377+
t!("settings.run_on_startup").to_string(),
378+
)
379+
.on_hover_text(t!("settings.run_on_startup_hover").to_string())
380+
.changed()
381+
{
382+
self.settings.run_on_startup = run_on_startup;
383+
match Self::set_auto_launch(run_on_startup) {
384+
Ok(_) => {
385+
if run_on_startup {
386+
self.success_toast(&t!("settings.startup_enabled"));
387+
} else {
388+
self.info_toast(&t!("settings.startup_disabled"));
389+
}
390+
}
391+
Err(e) => {
392+
self.settings.run_on_startup = !run_on_startup;
393+
self.error_toast(&t!("error.startup", error = e));
394+
}
395+
}
396+
}
397+
}
398+
399+
fn build_auto_launch() -> Result<auto_launch::AutoLaunch, String> {
400+
let exe = std::env::current_exe().map_err(|e| e.to_string())?;
401+
let exe_str = exe.to_str().ok_or("Invalid executable path")?;
402+
auto_launch::AutoLaunchBuilder::new()
403+
.set_app_name("Mantle")
404+
.set_app_path(exe_str)
405+
.set_macos_launch_mode(auto_launch::MacOSLaunchMode::LaunchAgent)
406+
.build()
407+
.map_err(|e| e.to_string())
408+
}
409+
410+
fn set_auto_launch(enable: bool) -> Result<(), String> {
411+
let auto = Self::build_auto_launch()?;
412+
if enable {
413+
auto.enable().map_err(|e| e.to_string())
414+
} else {
415+
auto.disable().map_err(|e| e.to_string())
416+
}
417+
}
418+
419+
pub fn sync_auto_launch_state(&mut self) {
420+
match Self::build_auto_launch().and_then(|a| a.is_enabled().map_err(|e| e.to_string())) {
421+
Ok(enabled) => self.settings.run_on_startup = enabled,
422+
Err(e) => log::warn!("Could not query auto-launch state: {}", e),
423+
}
424+
}
425+
367426
fn render_refresh_rate(&mut self, ui: &mut egui::Ui) {
368427
ui.horizontal(|ui| {
369428
ui.label(t!("settings.refresh_rate").to_string());
@@ -760,6 +819,7 @@ mod tests {
760819
scheduled_scenes: Vec::new(),
761820
audio_buffer_size: 4096,
762821
custom_colors: Vec::new(),
822+
run_on_startup: false,
763823
};
764824
let json = serde_json::to_string(&settings).unwrap();
765825
let deserialized: Settings = serde_json::from_str(&json).unwrap();
@@ -769,6 +829,7 @@ mod tests {
769829
assert!(deserialized.custom_shortcuts.is_empty());
770830
assert!(deserialized.scenes.is_empty());
771831
assert!(deserialized.custom_colors.is_empty());
832+
assert!(!deserialized.run_on_startup);
772833
}
773834

774835
#[test]

0 commit comments

Comments
 (0)