forked from didirus/AstralRinth
* Make theseus capable of logging messages from the `log` crate * Move update checking entirely into JS and open a modal if an update is available * Fix formatjs on Windows and run formatjs * Add in the buttons and body * Fix lint * Show update size in modal * Fix update not being rechecked if the update modal was directly dismissed * Slight UI tweaks * Fix lint * Implement skipping the update * Implement the Update Now button * Implement updating at next exit * Turn download progress into an error bar on failure * Restore 5 minute update check instead of 30 seconds * Fix PendingUpdateData being seen as a unit struct * Fix lint * Make CI also lint updater code * feat: create AppearingProgressBar component * feat: polish update available modal * feat: add error handling * Open changelog with tauri-plugin-opener * Run intl:extract * Update completion toasts (#3978) * Use single LAUNCHER_USER_AGENT constant for all user agents * Fix build on Mac * Request the update size with HEAD instead of GET * UI tweaks * lint * Fix lint * fix: hide modal header & add "Hide update reminder" button w/ tooltip * Run intl:extract * fix: lint issues * fix: merge issues * notifications.js no longer exists * Add metered network checking * Add a timeout to macOS is_network_metered * Fix tauri.conf.json * vibe debugging * Set a dispatch queue * Have a popup that asks you if you'd like to disable automatic file downloads if you're on a metered network * Move UpdateModal to modal package * Fix lint * Add a toggle for automatic downloads * Fix type Co-authored-by: Alejandro González <7822554+AlexTMjugador@users.noreply.github.com> Signed-off-by: Josiah Glosson <soujournme@gmail.com> * Redo updating UI and experience * lint * fix unlistener issue * remove unneeded translation keys * Fix expose issue * temp disable cranelift, tweak some messages * change version back * Clean up App.vue * move toast to top right * update reload icon * Fixed the bug!!!!!!!!!!!! * improve messages * intl:extract * Add liquid glass icon file * not you! * use dependency injection * lint on apple icon * Fix imports, move download size to button * change update check back to 5 mins * lint + move to providers * intl:extract --------- Signed-off-by: Cal H. <hendersoncal117@gmail.com> Signed-off-by: Josiah Glosson <soujournme@gmail.com> Co-authored-by: Calum <calum@modrinth.com> Co-authored-by: Prospector <prospectordev@gmail.com> Co-authored-by: Cal H. <hendersoncal117@gmail.com> Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com> Co-authored-by: Alejandro González <7822554+AlexTMjugador@users.noreply.github.com>
94 lines
2.8 KiB
Rust
94 lines
2.8 KiB
Rust
use crate::Result;
|
|
use std::io;
|
|
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
|
use tokio::net::TcpListener;
|
|
|
|
pub async fn tcp_listen_any_loopback() -> io::Result<TcpListener> {
|
|
// IPv4 is tried first for the best compatibility and performance with most systems.
|
|
// IPv6 is also tried in case IPv4 is not available. Resolving "localhost" is avoided
|
|
// to prevent failures deriving from improper name resolution setup. Any available
|
|
// ephemeral port is used to prevent conflicts with other services. This is all as per
|
|
// RFC 8252's recommendations
|
|
const ANY_LOOPBACK_SOCKET: &[SocketAddr] = &[
|
|
SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), 0),
|
|
SocketAddr::new(IpAddr::V6(Ipv6Addr::LOCALHOST), 0),
|
|
];
|
|
|
|
TcpListener::bind(ANY_LOOPBACK_SOCKET).await
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
pub async fn is_network_metered() -> Result<bool> {
|
|
use windows::Networking::Connectivity::{
|
|
NetworkCostType, NetworkInformation,
|
|
};
|
|
|
|
let cost_type = NetworkInformation::GetInternetConnectionProfile()?
|
|
.GetConnectionCost()?
|
|
.NetworkCostType()?;
|
|
Ok(matches!(
|
|
cost_type,
|
|
NetworkCostType::Fixed | NetworkCostType::Variable
|
|
))
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
pub async fn is_network_metered() -> Result<bool> {
|
|
use crate::ErrorKind;
|
|
use cidre::dispatch::Queue;
|
|
use cidre::nw::PathMonitor;
|
|
use std::time::Duration;
|
|
use tokio::sync::mpsc;
|
|
use tokio_util::future::FutureExt;
|
|
|
|
let (sender, mut receiver) = mpsc::channel(1);
|
|
|
|
let queue = Queue::new();
|
|
let mut monitor = PathMonitor::new();
|
|
monitor.set_queue(&queue);
|
|
monitor.set_update_handler(move |path| {
|
|
let _ = sender.try_send(path.is_constrained() || path.is_expensive());
|
|
});
|
|
|
|
monitor.start();
|
|
let result = receiver
|
|
.recv()
|
|
.timeout(Duration::from_millis(100))
|
|
.await
|
|
.ok()
|
|
.flatten();
|
|
monitor.cancel();
|
|
|
|
result.ok_or_else(|| {
|
|
ErrorKind::OtherError(
|
|
"NWPathMonitor didn't provide an NWPath in time".to_string(),
|
|
)
|
|
.into()
|
|
})
|
|
}
|
|
|
|
#[cfg(target_os = "linux")]
|
|
pub async fn is_network_metered() -> Result<bool> {
|
|
// Thanks to https://github.com/Hakanbaban53/rclone-manager for showing how to do this
|
|
use zbus::{Connection, Proxy};
|
|
|
|
let connection = Connection::system().await?;
|
|
let proxy = Proxy::new(
|
|
&connection,
|
|
"org.freedesktop.NetworkManager",
|
|
"/org/freedesktop/NetworkManager",
|
|
"org.freedesktop.NetworkManager",
|
|
)
|
|
.await?;
|
|
let metered = proxy.get_property("Metered").await?;
|
|
Ok(matches!(metered, 1 | 3))
|
|
}
|
|
|
|
#[cfg(not(any(windows, target_os = "macos", target_os = "linux")))]
|
|
pub async fn is_network_metered() -> Result<bool> {
|
|
tracing::warn!(
|
|
"is_network_metered called on unsupported platform. Assuming unmetered."
|
|
);
|
|
Ok(false)
|
|
}
|