225 lines
7.2 KiB
Rust
225 lines
7.2 KiB
Rust
use openworm::net::{CreateAccount, CreateAccountResp, Login, LoginResp};
|
|
|
|
use crate::{
|
|
data::{AccountInfo, ClientData, ServerInfo, ServerList},
|
|
net::{ConnectInfo, NetHandle},
|
|
session::Session,
|
|
};
|
|
|
|
use super::*;
|
|
|
|
pub fn start(rsc: &mut Rsc, data: &ClientData) -> WeakWidget {
|
|
let mut accounts = Span::empty(Dir::DOWN);
|
|
|
|
let accts = data.accounts();
|
|
if accts.is_empty() {
|
|
accounts.push(
|
|
wtext("no accounts")
|
|
.size(20)
|
|
.center_text()
|
|
.color(Color::GRAY)
|
|
.height(60)
|
|
.add_strong(rsc),
|
|
);
|
|
} else {
|
|
for account in accts.iter() {
|
|
let button = Button::new_fg(
|
|
wtext(&account.username)
|
|
.size(20)
|
|
.center_text()
|
|
.height(60)
|
|
.add(rsc),
|
|
color::DARK,
|
|
rsc,
|
|
)
|
|
.add(rsc);
|
|
let account = account.clone();
|
|
let cert_hex = data
|
|
.data
|
|
.load::<ServerList>()
|
|
.get(&account.url)
|
|
.unwrap()
|
|
.cert_hex
|
|
.clone();
|
|
let cert = decode_hex(&cert_hex).unwrap();
|
|
keyring::use_native_store(true).unwrap();
|
|
rsc.events.register(button, Submit, move |ctx, rsc| {
|
|
let account = account.clone();
|
|
let cert = cert.clone();
|
|
let password = ctx.state.data.password(&account);
|
|
rsc.spawn_task(async move |mut ctx| {
|
|
let mut fail = |reason: &str| {
|
|
let reason = reason.to_string();
|
|
ctx.update(move |ctx, rsc| {
|
|
ctx.error(&reason, rsc);
|
|
})
|
|
};
|
|
let con = match NetHandle::connect(
|
|
async |msg| {
|
|
println!("msg recv :joy:");
|
|
},
|
|
ConnectInfo {
|
|
url: account.url.clone(),
|
|
cert,
|
|
},
|
|
)
|
|
.await
|
|
{
|
|
Ok(v) => v,
|
|
Err(e) => {
|
|
return fail(&e);
|
|
}
|
|
};
|
|
|
|
let Ok(resp) = con
|
|
.request(Login {
|
|
username: account.username.clone(),
|
|
password: password.clone(),
|
|
})
|
|
.await
|
|
else {
|
|
return fail("failed to create account");
|
|
};
|
|
let user_id = match resp {
|
|
LoginResp::Ok { id } => id,
|
|
LoginResp::UnknownUsername => {
|
|
return fail("unknown username");
|
|
}
|
|
LoginResp::InvalidPassword => {
|
|
return fail("invalid password");
|
|
}
|
|
};
|
|
let session = Session { con, user_id };
|
|
ctx.update(move |ctx, rsc| {
|
|
main_view(rsc, session).set_ptr(ctx.main_ui, rsc);
|
|
});
|
|
});
|
|
});
|
|
accounts.push(button.add_strong(rsc));
|
|
}
|
|
}
|
|
|
|
let connect = Button::submit("connect", rsc);
|
|
let create = Button::submit("create", rsc);
|
|
rsc.events.register(connect, Submit, move |_, rsc| {
|
|
connect.disable(rsc);
|
|
create.disable(rsc);
|
|
});
|
|
|
|
rsc.events.register(create, Submit, move |ctx, rsc| {
|
|
create_account(rsc).set_ptr(ctx.state.main_ui, rsc);
|
|
});
|
|
|
|
(
|
|
wtext("Select Account").text_align(Align::CENTER).size(30),
|
|
accounts,
|
|
(connect, create).span(Dir::RIGHT).gap(10),
|
|
)
|
|
.span(Dir::DOWN)
|
|
.gap(30)
|
|
.modal(400)
|
|
.add(rsc)
|
|
}
|
|
|
|
pub fn create_account(rsc: &mut Rsc) -> WeakWidget {
|
|
let url = field("", "server").add(rsc);
|
|
let token = field("", "account creation token").add(rsc);
|
|
let cert = field("", "certificate hex").add(rsc);
|
|
let username = field("", "username").add(rsc);
|
|
let password = field("", "password").add(rsc);
|
|
|
|
let create = Button::submit("create", rsc);
|
|
rsc.events.register(create, Submit, move |ctx, rsc| {
|
|
let url = rsc[url].content().trim().to_string();
|
|
let token = rsc[token].content().trim().to_string();
|
|
let cert_hex = rsc[cert].content().trim().to_string();
|
|
let Some(cert) = decode_hex(&cert_hex) else {
|
|
rsc[ctx.state.notif].inner = Some(werror("Invalid certificate hex", rsc));
|
|
return;
|
|
};
|
|
let username = rsc[username].content();
|
|
let password = rsc[password].content();
|
|
|
|
create.disable(rsc);
|
|
rsc.spawn_task(async move |mut ctx| {
|
|
let mut fail = |reason: &str| {
|
|
let reason = reason.to_string();
|
|
ctx.update(move |ctx, rsc| {
|
|
ctx.error(&reason, rsc);
|
|
create.enable(rsc);
|
|
})
|
|
};
|
|
keyring::use_native_store(true).unwrap();
|
|
let con = match NetHandle::connect(
|
|
async |msg| {
|
|
println!("msg recv :joy:");
|
|
},
|
|
ConnectInfo {
|
|
url: url.clone(),
|
|
cert,
|
|
},
|
|
)
|
|
.await
|
|
{
|
|
Ok(v) => v,
|
|
Err(e) => {
|
|
return fail(&e);
|
|
}
|
|
};
|
|
|
|
let Ok(resp) = con
|
|
.request(CreateAccount {
|
|
username: username.clone(),
|
|
password: password.clone(),
|
|
token,
|
|
})
|
|
.await
|
|
else {
|
|
return fail("failed to create account");
|
|
};
|
|
let user_id = match resp {
|
|
CreateAccountResp::Ok { id } => id,
|
|
CreateAccountResp::UsernameExists => {
|
|
return fail("username already exists");
|
|
}
|
|
CreateAccountResp::InvalidToken => {
|
|
return fail("invalid account token");
|
|
}
|
|
};
|
|
let session = Session { con, user_id };
|
|
ctx.update(move |ctx, rsc| {
|
|
main_view(rsc, session).set_ptr(ctx.main_ui, rsc);
|
|
ctx.data.create_account(
|
|
ServerInfo { cert_hex },
|
|
AccountInfo { url, username },
|
|
&password,
|
|
);
|
|
});
|
|
});
|
|
});
|
|
|
|
(
|
|
wtext("Create Account").text_align(Align::CENTER).size(30),
|
|
field_box(url),
|
|
field_box(token),
|
|
field_box(cert),
|
|
field_box(username),
|
|
field_box(password),
|
|
create,
|
|
)
|
|
.span(Dir::DOWN)
|
|
.gap(15)
|
|
.modal(400)
|
|
.add(rsc)
|
|
}
|
|
|
|
pub fn decode_hex(s: &str) -> Option<Vec<u8>> {
|
|
if !s.len().is_multiple_of(2) {
|
|
return None;
|
|
}
|
|
(0..s.len())
|
|
.step_by(2)
|
|
.map(|i| u8::from_str_radix(&s[i..i + 2], 16).ok())
|
|
.collect()
|
|
}
|