use crate::update_checker::{UpdateCheckResult, UpdateInfo};
pub(super) fn notify_update_available(info: &UpdateInfo) {
let version_str = info.version.strip_prefix('v').unwrap_or(&info.version);
let current = env!("CARGO_PKG_VERSION");
let summary = format!("par-term v{} Available", version_str);
let body = format!(
"You have v{}. Check Settings > Advanced > Updates.",
current
);
crate::platform::deliver_desktop_notification(&summary, &body, 8000);
}
pub(super) fn to_settings_update_result(
result: &UpdateCheckResult,
) -> crate::settings_ui::UpdateCheckResult {
match result {
UpdateCheckResult::UpToDate => crate::settings_ui::UpdateCheckResult::UpToDate,
UpdateCheckResult::UpdateAvailable(info) => {
crate::settings_ui::UpdateCheckResult::UpdateAvailable(
crate::settings_ui::UpdateCheckInfo {
version: info.version.clone(),
release_notes: info.release_notes.clone(),
release_url: info.release_url.clone(),
published_at: info.published_at.clone(),
},
)
}
UpdateCheckResult::Disabled => crate::settings_ui::UpdateCheckResult::Disabled,
UpdateCheckResult::Skipped => crate::settings_ui::UpdateCheckResult::Skipped,
UpdateCheckResult::Error(e) => crate::settings_ui::UpdateCheckResult::Error(e.clone()),
}
}
pub(super) fn update_available_version(result: &UpdateCheckResult) -> Option<String> {
match result {
UpdateCheckResult::UpdateAvailable(info) => Some(
info.version
.strip_prefix('v')
.unwrap_or(&info.version)
.to_string(),
),
_ => None,
}
}
use super::WindowManager;
impl WindowManager {
pub fn check_for_updates(&mut self) {
use crate::update_checker::current_timestamp;
use std::time::{Duration, Instant};
let now = Instant::now();
if self.next_update_check.is_none() {
self.next_update_check = Some(now + Duration::from_secs(5));
return;
}
if let Some(next_check) = self.next_update_check
&& now >= next_check
{
let (result, should_save) = self.update_checker.check_now(&self.config, false);
let mut config_changed = should_save;
match &result {
UpdateCheckResult::UpdateAvailable(info) => {
let version_str = info
.version
.strip_prefix('v')
.unwrap_or(&info.version)
.to_string();
log::info!(
"Update available: {} (current: {})",
version_str,
env!("CARGO_PKG_VERSION")
);
let already_notified = self
.config
.updates
.last_notified_version
.as_ref()
.is_some_and(|v| v == &version_str);
if !already_notified {
notify_update_available(info);
self.config.updates.last_notified_version = Some(version_str);
config_changed = true;
}
}
UpdateCheckResult::UpToDate => {
log::info!("par-term is up to date ({})", env!("CARGO_PKG_VERSION"));
}
UpdateCheckResult::Error(e) => {
log::warn!("Update check failed: {}", e);
}
UpdateCheckResult::Disabled | UpdateCheckResult::Skipped => {
}
}
self.last_update_result = Some(result);
let version = self
.last_update_result
.as_ref()
.and_then(update_available_version);
let result_clone = self.last_update_result.clone();
for ws in self.windows.values_mut() {
ws.status_bar_ui.update_available_version = version.clone();
ws.update_state.last_result = result_clone.clone();
}
if config_changed {
self.config.updates.last_update_check = Some(current_timestamp());
if let Err(e) = self.config.save() {
log::warn!("Failed to save config after update check: {}", e);
}
}
self.next_update_check = self
.config
.updates
.update_check_frequency
.as_seconds()
.map(|secs| now + Duration::from_secs(secs));
}
}
pub fn force_update_check(&mut self) {
use crate::update_checker::current_timestamp;
let (result, should_save) = self.update_checker.check_now(&self.config, true);
match &result {
UpdateCheckResult::UpdateAvailable(info) => {
log::info!(
"Update available: {} (current: {})",
info.version,
env!("CARGO_PKG_VERSION")
);
}
UpdateCheckResult::UpToDate => {
log::info!("par-term is up to date ({})", env!("CARGO_PKG_VERSION"));
}
UpdateCheckResult::Error(e) => {
log::warn!("Update check failed: {}", e);
}
_ => {}
}
self.last_update_result = Some(result);
let version = self
.last_update_result
.as_ref()
.and_then(update_available_version);
let result_clone = self.last_update_result.clone();
for ws in self.windows.values_mut() {
ws.status_bar_ui.update_available_version = version.clone();
ws.update_state.last_result = result_clone.clone();
}
if should_save {
self.config.updates.last_update_check = Some(current_timestamp());
if let Err(e) = self.config.save() {
log::warn!("Failed to save config after update check: {}", e);
}
}
}
pub fn force_update_check_for_settings(&mut self) {
self.force_update_check();
if let Some(settings_window) = &mut self.settings_window {
settings_window.settings_ui.last_update_result = self
.last_update_result
.as_ref()
.map(to_settings_update_result);
settings_window.request_redraw();
}
}
pub(super) fn detect_installation_type(&self) -> par_term_settings_ui::InstallationType {
let install = crate::self_updater::detect_installation();
match install {
crate::self_updater::InstallationType::Homebrew => {
par_term_settings_ui::InstallationType::Homebrew
}
crate::self_updater::InstallationType::CargoInstall => {
par_term_settings_ui::InstallationType::CargoInstall
}
crate::self_updater::InstallationType::MacOSBundle => {
par_term_settings_ui::InstallationType::MacOSBundle
}
crate::self_updater::InstallationType::StandaloneBinary => {
par_term_settings_ui::InstallationType::StandaloneBinary
}
}
}
pub fn send_test_notification(&self) {
log::info!("Sending test notification");
crate::platform::deliver_desktop_notification(
"par-term Test Notification",
"If you see this, notifications are working!",
5000,
);
}
}