forked from jeena/FeedTheMonkey
fix: tokio runtime, Enter-to-login, and server URL handling
Three bugs fixed: - No tokio reactor: glib::spawn_future_local does not provide a tokio context, so reqwest/hyper panicked at runtime. Introduce src/runtime.rs with a multi-thread tokio Runtime (init() called from main before the GTK app starts). runtime::spawn() posts the async result back to GTK via a tokio oneshot channel awaited by glib::spawn_future_local, which only polls a flag (no I/O). runtime::spawn_bg() is used for fire-and-forget background calls. - Enter key didn't submit login: connect_apply on AdwEntryRow only fires when show-apply-button is true. Switch to connect_entry_activated which fires on Return in all three login rows. - Wrong API URL: the app constructed /accounts/ClientLogin directly off the server host, yielding a 404. Add normalize_base_url() in api.rs that appends /api/greader.php when the URL doesn't already contain it, so users can enter just https://rss.example.com.
This commit is contained in:
parent
d157f3f244
commit
5dee5cc52b
6 changed files with 161 additions and 67 deletions
50
src/runtime.rs
Normal file
50
src/runtime.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
use std::sync::OnceLock;
|
||||
use tokio::runtime::Runtime;
|
||||
|
||||
static RT: OnceLock<Runtime> = OnceLock::new();
|
||||
|
||||
pub fn init() {
|
||||
RT.get_or_init(|| {
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("failed to build tokio runtime")
|
||||
});
|
||||
}
|
||||
|
||||
/// Spawn `future` on the tokio runtime. When it completes, `callback`
|
||||
/// is invoked on the GLib main context (GTK main thread).
|
||||
///
|
||||
/// Works by routing the result through a tokio oneshot channel; the
|
||||
/// receiving end is awaited by `glib::spawn_future_local`, which runs
|
||||
/// on the GLib event loop but does no I/O, so it never needs tokio's
|
||||
/// reactor itself.
|
||||
pub fn spawn<F, T, C>(future: F, callback: C)
|
||||
where
|
||||
F: std::future::Future<Output = T> + Send + 'static,
|
||||
T: Send + 'static,
|
||||
C: FnOnce(T) + 'static,
|
||||
{
|
||||
let (tx, rx) = tokio::sync::oneshot::channel::<T>();
|
||||
|
||||
RT.get().expect("runtime not initialised").spawn(async move {
|
||||
let result = future.await;
|
||||
let _ = tx.send(result);
|
||||
});
|
||||
|
||||
// The receive future only polls a mutex-protected flag — no I/O,
|
||||
// so running it on the GLib event loop is fine.
|
||||
glib::spawn_future_local(async move {
|
||||
if let Ok(value) = rx.await {
|
||||
callback(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Fire-and-forget: spawn on the tokio runtime, no callback.
|
||||
pub fn spawn_bg<F>(future: F)
|
||||
where
|
||||
F: std::future::Future<Output = ()> + Send + 'static,
|
||||
{
|
||||
RT.get().expect("runtime not initialised").spawn(future);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue