Refactor Tauri crate into a library and add OS version header

This commit is contained in:
2026-07-08 21:29:26 +03:00
parent 2e80f7b8eb
commit a2581187da
17 changed files with 244 additions and 244 deletions
+94
View File
@@ -40,6 +40,7 @@ pub struct SubscriptionFetchIdentity {
pub app_name: String,
pub user_agent: String,
pub device_os: String,
pub device_os_version: Option<String>,
pub device_model: String,
}
@@ -64,6 +65,7 @@ impl Default for SubscriptionFetchIdentity {
app_name: DEFAULT_APP_NAME.to_string(),
user_agent: format!("{DEFAULT_APP_NAME}/{device_os}"),
device_os,
device_os_version: detect_device_os_version(),
device_model: DEFAULT_APP_NAME.to_string(),
}
}
@@ -124,6 +126,18 @@ pub fn fetch_subscription_with_identity(
.header("x-device-os", identity.device_os.as_str())
.header("x-device-model", identity.device_model.as_str());
if let Some(device_os_version) = identity
.device_os_version
.as_deref()
.map(str::trim)
.filter(|value| !value.is_empty())
{
let header_value = sanitize_header_value(device_os_version);
if !header_value.is_empty() {
request = request.header("x-device-os-version", header_value);
}
}
if let Some(device_hwid) = identity
.device_hwid
.as_deref()
@@ -318,6 +332,86 @@ fn query_value(url: &Url, key: &str) -> Option<String> {
.map(|(_, value)| value.into_owned())
}
fn sanitize_header_value(value: &str) -> String {
value
.chars()
.filter(|ch| ch.is_ascii_graphic() || *ch == ' ')
.collect::<String>()
}
fn detect_device_os_version() -> Option<String> {
#[cfg(windows)]
{
windows_device_os_version()
}
#[cfg(not(windows))]
{
None
}
}
#[cfg(windows)]
fn windows_device_os_version() -> Option<String> {
use winreg::{enums::HKEY_LOCAL_MACHINE, RegKey};
let current_version = RegKey::predef(HKEY_LOCAL_MACHINE)
.open_subkey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion")
.ok()?;
let product_name = current_version
.get_value::<String, _>("ProductName")
.ok()
.map(|value| normalize_windows_product_name(&value, &current_version))
.filter(|value| !value.trim().is_empty());
let display_version = current_version
.get_value::<String, _>("DisplayVersion")
.ok()
.or_else(|| current_version.get_value::<String, _>("ReleaseId").ok())
.filter(|value| !value.trim().is_empty());
let build = current_version
.get_value::<String, _>("CurrentBuildNumber")
.ok()
.or_else(|| current_version.get_value::<String, _>("CurrentBuild").ok())
.filter(|value| !value.trim().is_empty());
let ubr = current_version.get_value::<u32, _>("UBR").ok();
let build = match (build, ubr) {
(Some(build), Some(ubr)) => Some(format!("{build}.{ubr}")),
(build, _) => build,
};
let mut parts = Vec::new();
if let Some(product_name) = product_name {
parts.push(product_name);
}
if let Some(display_version) = display_version {
parts.push(display_version);
}
if let Some(build) = build {
parts.push(format!("build {build}"));
}
let version = parts.join(" | ");
(!version.is_empty()).then_some(version)
}
#[cfg(windows)]
fn normalize_windows_product_name(value: &str, current_version: &winreg::RegKey) -> String {
let trimmed = value.trim();
let build_number = current_version
.get_value::<String, _>("CurrentBuildNumber")
.ok()
.or_else(|| current_version.get_value::<String, _>("CurrentBuild").ok())
.and_then(|value| value.parse::<u32>().ok())
.unwrap_or_default();
if build_number >= 22000 && trimmed.starts_with("Windows 10") {
return trimmed.replacen("Windows 10", "Windows 11", 1);
}
trimmed.to_string()
}
fn now_timestamp() -> String {
let seconds = SystemTime::now()
.duration_since(UNIX_EPOCH)