use openworm::net::{AddFriend, AddFriendResp, GenerateToken, RequestFriends, ServerPerms}; use super::*; pub fn view(rsc: &mut Rsc, session: &Session) -> StrongWidget { ( gen_token(rsc, session), add_friend_area(rsc, session), friends_list(rsc, session), ) .span(Dir::DOWN) .add_strong(rsc) } fn add_friend_area(rsc: &mut Rsc, session: &Session) -> WeakWidget { let username_field = field("", "username").add(rsc); let add = Button::submit("add friend", rsc); let con = session.con.clone(); rsc.events.register(add, Submit, move |ctx, rsc| { let con = con.clone(); let username = username_field.edit(rsc).take(); add.disable(rsc); rsc.tasks.spawn(async move |mut ctx| { let Ok(resp) = con.request(AddFriend { username }).await else { ctx.update(move |ctx, rsc| { ctx.error("failed to add user", rsc); }); return; }; ctx.update(move |ctx, rsc| { add.enable(rsc); match resp { AddFriendResp::Ok => {} AddFriendResp::UnknownUser => { ctx.error("unknown user", rsc); } AddFriendResp::CannotAddSelf => { ctx.error("cannot add self", rsc); } AddFriendResp::AlreadySent => { ctx.error("already sent request to user", rsc); } AddFriendResp::AlreadyFriends => { ctx.error("already friends with user", rsc); } } }); }); }); (field_box(username_field).width(300), add.width(200)) .span(Dir::RIGHT) .add(rsc) } fn gen_token(rsc: &mut Rsc, session: &Session) -> WeakWidget { let generate = Button::normal("generate token", rsc); let con = session.con.clone(); let token = wtext("") .size(30) .editable(EditMode::SingleLine) .attr::(()) .add(rsc); rsc.events.register(generate, Submit, move |_, rsc| { let con = con.clone(); token.edit(rsc).set("loading..."); rsc.spawn_task(async move |mut ctx| { let resp = con .request(GenerateToken { perms: ServerPerms::NONE, }) .await; ctx.update(move |_, rsc| match resp { Ok(resp) => { token.edit(rsc).set(&resp.token); } Err(_) => { token.edit(rsc).set("failed to generate token"); } }); }); }); (generate.width(200), token).span(Dir::RIGHT).add(rsc) } fn friends_list(rsc: &mut Rsc, session: &Session) -> WeakWidget { let ptr = loading_area("loading friends").add(rsc); let con = session.con.clone(); rsc.events.register(ptr, Draw, move |_, rsc| { let con = con.clone(); // TODO: maybe have rsc.request method that takes in &con? // need to also handle error tho rsc.spawn_task(async move |mut ctx| { let Ok(resp) = con.request(RequestFriends).await else { return; }; ctx.update(move |_, rsc| { let mut all = Span::empty(Dir::DOWN); if !resp.incoming.is_empty() { all.push(section_label("incoming").add_strong(rsc)); all.push(user_list(&resp.incoming, rsc).add_strong(rsc)) } all.push(section_label("friends").add_strong(rsc)); all.push(user_list(&resp.current, rsc).add_strong(rsc)); if !resp.outgoing.is_empty() { all.push(section_label("outgoing").add_strong(rsc)); all.push(user_list(&resp.outgoing, rsc).add_strong(rsc)) } all.set_ptr(ptr, rsc); }); }); }); ptr }