generated from nhcarrigan/template
3f30997f0e
## Explanation This PR bundles several user-facing improvements and feature additions for the v0.3.0 release, including quality-of-life improvements to the UI, new slash commands, better state persistence, and auto-update checking. ## Included Changes - **Resizable chat input** with drag handle (#58 partial) - **Arrow key navigation fix** - cursor keys now navigate text when user has typed input (#58) - **Scroll position persistence** per conversation tab - **/skill command** for invoking Claude Code skills (#57) - **Stats persistence fix** - stats now persist across session changes, only reset on disconnect (#59) - **Auto-update checker** on startup (#17) - **Resizable character panel** with full-height sprites (#10) - **Font size and zoom settings** with keyboard shortcuts (Ctrl++/Ctrl+-/Ctrl+0) (#19) ## Closes Closes #10, #17, #19, #57, #58, #59 ## Attestations - [x] I have read and agree to the Code of Conduct - [x] I have read and agree to the Community Guidelines - [x] My contribution complies with the Contributor Covenant - [x] I have run the linter and resolved any errors - [x] My pull request uses an appropriate title, matching the conventional commit standards - [x] My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request - [x] All new and existing tests pass locally with my changes - [x] Code coverage remains at or above the configured threshold ## Documentation N/A - Internal app features ## Versioning Minor - My pull request introduces new non-breaking features. --- ✨ This PR was created with help from Hikari~ 🌸 Co-authored-by: Hikari <hikari@nhcarrigan.com> Reviewed-on: #61 Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com> Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
65 lines
1.8 KiB
Rust
65 lines
1.8 KiB
Rust
use tauri::command;
|
|
|
|
#[cfg(target_os = "windows")]
|
|
use windows::{
|
|
core::{Result as WindowsResult, HSTRING},
|
|
Data::Xml::Dom::*,
|
|
UI::Notifications::*,
|
|
};
|
|
|
|
#[cfg(target_os = "windows")]
|
|
#[command]
|
|
pub async fn send_windows_toast(title: String, body: String) -> Result<(), String> {
|
|
show_toast_notification(&title, &body)
|
|
.map_err(|e| format!("Failed to show toast notification: {}", e))
|
|
}
|
|
|
|
#[cfg(target_os = "windows")]
|
|
fn show_toast_notification(title: &str, body: &str) -> WindowsResult<()> {
|
|
// Create the XML for the toast notification
|
|
let toast_xml = format!(
|
|
r#"<toast>
|
|
<visual>
|
|
<binding template="ToastGeneric">
|
|
<text>{}</text>
|
|
<text>{}</text>
|
|
</binding>
|
|
</visual>
|
|
<audio src="ms-winsoundevent:Notification.Default" />
|
|
</toast>"#,
|
|
escape_xml(title),
|
|
escape_xml(body)
|
|
);
|
|
|
|
let xml_doc = XmlDocument::new()?;
|
|
xml_doc.LoadXml(&HSTRING::from(toast_xml))?;
|
|
|
|
// Create the toast notification
|
|
let toast = ToastNotification::CreateToastNotification(&xml_doc)?;
|
|
|
|
// Create a toast notifier with an application ID
|
|
let notifier =
|
|
ToastNotificationManager::CreateToastNotifierWithId(&HSTRING::from("Hikari Desktop"))?;
|
|
|
|
// Show the notification
|
|
notifier.Show(&toast)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(target_os = "windows")]
|
|
fn escape_xml(text: &str) -> String {
|
|
text.replace('&', "&")
|
|
.replace('<', "<")
|
|
.replace('>', ">")
|
|
.replace('"', """)
|
|
.replace('\'', "'")
|
|
}
|
|
|
|
// Stub for non-Windows platforms
|
|
#[cfg(not(target_os = "windows"))]
|
|
#[command]
|
|
pub async fn send_windows_toast(_title: String, _body: String) -> Result<(), String> {
|
|
Err("Windows toast notifications are only available on Windows".to_string())
|
|
}
|