Skip to content

Commit

Permalink
Parse query in egui_router
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasmerlin committed Aug 27, 2024
1 parent 72fa3d1 commit 37beaa3
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 3 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions crates/egui_router/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# egui_router changelog

## Unreleased

- Parse query parameters and expose them in `Request::query` and `OwnedRequest::query`

## 0.1.2

- Make RouterBuilder public
Expand Down
1 change: 1 addition & 0 deletions crates/egui_router/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ egui_suspense = { workspace = true, optional = true }

matchit = "0.8"
thiserror = "1"
form_urlencoded = "1"

[target.'cfg(target_arch = "wasm32")'.dependencies]
web-sys = { version = "0.3", features = ["History", "PopStateEvent", "HtmlCollection"] }
Expand Down
15 changes: 14 additions & 1 deletion crates/egui_router/examples/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use eframe::NativeOptions;
use egui::{CentralPanel, Color32, Context, Frame, ScrollArea, Ui, Window};
use egui_inbox::type_inbox::TypeInbox;
use egui_router::{EguiRouter, Request, Route, TransitionConfig};
use std::borrow::Cow;

#[derive(Debug, Clone)]
struct AppState {
Expand Down Expand Up @@ -104,6 +105,12 @@ fn home() -> impl Route<AppState> {
.send(RouterMessage::Navigate("/post/2".to_string()));
}

if ui.link("Post With Query").clicked() {
state
.inbox
.send(RouterMessage::Navigate("/post/3?search=test".to_string()));
}

if ui.link("Invalid Post").clicked() {
state
.inbox
Expand Down Expand Up @@ -132,9 +139,11 @@ fn edit_message() -> impl Route<AppState> {
}
}

fn post(request: Request<AppState>) -> impl Route<AppState> {
fn post(mut request: Request<AppState>) -> impl Route<AppState> {
let id = request.params.get("id").map(ToOwned::to_owned);

let search: Option<String> = request.query.remove("search").map(Cow::into_owned);

move |ui: &mut Ui, state: &mut AppState| {
background(ui, ui.style().visuals.extreme_bg_color, |ui| {
ScrollArea::vertical().show(ui, |ui| {
Expand All @@ -143,6 +152,10 @@ fn post(request: Request<AppState>) -> impl Route<AppState> {

ui.label(format!("Id: {:?}", ui.next_auto_id()));

if let Some(search) = &search {
ui.label(format!("Search: {}", search));
}

if ui.button("back").clicked() {
state.inbox.send(RouterMessage::Back);
}
Expand Down
8 changes: 7 additions & 1 deletion crates/egui_router/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use crate::history::HistoryError;
use crate::transition::{ActiveTransition, SlideFadeTransition, SlideTransition, Transition};
use egui::emath::ease_in_ease_out;
use egui::{Ui, Vec2};
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::sync::atomic::AtomicUsize;

pub use handler::{HandlerError, HandlerResult};
Expand Down Expand Up @@ -142,6 +144,8 @@ struct CurrentTransition<State> {
pub struct Request<'a, State = ()> {
/// The parsed path params
pub params: matchit::Params<'a, 'a>,
/// The parsed query params
pub query: BTreeMap<Cow<'a, str>, Cow<'a, str>>,
/// The custom state
pub state: &'a mut State,
}
Expand All @@ -150,7 +154,9 @@ pub struct Request<'a, State = ()> {
/// Owned request, passed to [handler::AsyncMakeHandler]
pub struct OwnedRequest<State = ()> {
/// The parsed path params
pub params: std::collections::BTreeMap<String, String>,
pub params: BTreeMap<String, String>,
/// The parsed query params
pub query: BTreeMap<String, String>,
/// The custom state
pub state: State,
}
17 changes: 16 additions & 1 deletion crates/egui_router/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use crate::{
};
use egui::Ui;
use matchit::MatchError;
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::sync::atomic::Ordering;

/// A router instance
Expand Down Expand Up @@ -52,7 +54,7 @@ impl<State: 'static, H: History + Default> EguiRouter<State, H> {
{
router
.navigate_impl(state, r, TransitionConfig::none(), state_index.unwrap_or(0))
.ok();
.unwrap();
}

router
Expand All @@ -63,13 +65,22 @@ impl<State: 'static, H: History + Default> EguiRouter<State, H> {
self.history.last().map(|r| r.path.as_str())
}

fn parse_query(path: &str) -> BTreeMap<Cow<str>, Cow<str>> {
let query = path.split_once('?').map(|(_, q)| q);
query
.map(|q| form_urlencoded::parse(q.as_bytes()).collect())
.unwrap_or(BTreeMap::new())
}

fn navigate_impl(
&mut self,
state: &mut State,
path: String,
transition_config: TransitionConfig,
new_state: u32,
) -> RouterResult {
let query = Self::parse_query(&path);

let mut redirect = None;
let result = self.router.at_mut(&path);

Expand All @@ -80,6 +91,7 @@ impl<State: 'static, H: History + Default> EguiRouter<State, H> {
let route = handler(Request {
state,
params: match_.params,
query,
});
self.history.push(RouteState {
path,
Expand Down Expand Up @@ -171,6 +183,8 @@ impl<State: 'static, H: History + Default> EguiRouter<State, H> {
let current_state = self.history.last().map(|r| r.state).unwrap_or(0);
let new_state = current_state;

let query = Self::parse_query(&path);

let result = match result {
Ok(match_) => match match_.value {
RouteKind::Route(handler) => {
Expand All @@ -179,6 +193,7 @@ impl<State: 'static, H: History + Default> EguiRouter<State, H> {
let route = handler(Request {
state,
params: match_.params,
query,
});
self.history.push(RouteState {
path,
Expand Down
5 changes: 5 additions & 0 deletions crates/egui_router/src/router_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ impl<State: 'static, H: History + Default> RouterBuilder<State, H> {
.iter()
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect(),
query: req
.query
.into_iter()
.map(|(k, v)| (k.into_owned(), v.into_owned()))
.collect(),
state: req.state.clone(),
};

Expand Down

0 comments on commit 37beaa3

Please sign in to comment.