Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(login): change ordering of account creation pages #1976

Merged
merged 3 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 79 additions & 19 deletions ui/src/layouts/log_in/copy_seed_words.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,21 @@ use dioxus_desktop::{use_window, LogicalSize};
use kit::elements::{button::Button, label::Label, Appearance};
use tokio::time::sleep;

use crate::get_app_style;

use super::AuthPages;
use crate::get_app_style;
use common::state::configuration::Configuration;
use common::{
sounds,
warp_runner::{MultiPassCmd, WarpCmd},
WARP_CMD_CH,
};
use futures::channel::oneshot;
use futures::StreamExt;
use warp::multipass;

// styles for this layout are in layouts/style.scss
#[component]
pub fn Layout(cx: Scope, page: UseState<AuthPages>, seed_words: UseRef<String>) -> Element {
pub fn Layout(cx: Scope, page: UseState<AuthPages>, username: String, pin: String) -> Element {
let state = use_ref(cx, State::load);
let window = use_window(cx);

Expand All @@ -24,20 +32,18 @@ pub fn Layout(cx: Scope, page: UseState<AuthPages>, seed_words: UseRef<String>)
});
}

let words = use_future(cx, (), |_| {
to_owned![seed_words];
async move {
let mnemonic = warp::crypto::keypair::generate_mnemonic_phrase(
warp::crypto::keypair::PhraseType::Standard,
)
.into_phrase();

seed_words.set(mnemonic.clone());
let words = use_future(cx, (), |_| async move {
stavares843 marked this conversation as resolved.
Show resolved Hide resolved
let mnemonic = warp::crypto::keypair::generate_mnemonic_phrase(
warp::crypto::keypair::PhraseType::Standard,
)
.into_phrase();
(
mnemonic.clone(),
mnemonic
.split_ascii_whitespace()
.map(|x| x.to_string())
.collect::<Vec<String>>()
}
.collect::<Vec<String>>(),
)
});

cx.render(rsx!(
Expand All @@ -53,25 +59,76 @@ pub fn Layout(cx: Scope, page: UseState<AuthPages>, seed_words: UseRef<String>)
aria_label: "copy-seed-words".into(),
text: get_local_text("copy-seed-words")
},
if let Some(words) = words.value() {
rsx!{ SeedWords { page: page.clone(), words: words.clone() } }
if let Some((seed_words, words)) = words.value() {
rsx!{ SeedWords { page: page.clone(), username: username.clone(), pin: pin.clone(), seed_words: seed_words.clone(), words: words.clone() } }
}
}
))
}

#[component]
fn SeedWords(cx: Scope, page: UseState<AuthPages>, words: Vec<String>) -> Element {
fn SeedWords(
cx: Scope,
page: UseState<AuthPages>,
username: String,
pin: String,
seed_words: String,
words: Vec<String>,
) -> Element {
let copied = use_ref(cx, || false);
let loading = use_state(cx, || false);

use_future(cx, copied, |current| async move {
if *current.read() {
sleep(Duration::from_secs(3)).await;
*current.write() = false;
}
});

let ch = use_coroutine(cx, |mut rx: UnboundedReceiver<()>| {
to_owned![page, loading, username, pin, seed_words];
async move {
let config = Configuration::load_or_default();
let warp_cmd_tx = WARP_CMD_CH.tx.clone();
while let Some(()) = rx.next().await {
loading.set(true);
let (tx, rx) =
oneshot::channel::<Result<multipass::identity::Identity, warp::error::Error>>();

if let Err(e) = warp_cmd_tx.send(WarpCmd::MultiPass(MultiPassCmd::CreateIdentity {
username: username.clone(),
tesseract_passphrase: pin.clone(),
seed_words: seed_words.clone(),
rsp: tx,
})) {
log::error!("failed to send warp command: {}", e);
continue;
}

let res = rx.await.expect("failed to get response from warp_runner");

match res {
Ok(ident) => {
if config.audiovideo.interface_sounds {
sounds::Play(sounds::Sounds::On);
}

page.set(AuthPages::Success(ident));
}
// todo: notify user
Err(e) => log::error!("create identity failed: {}", e),
}
}
}
});
render! {
loading.get().then(|| rsx!(
div {
class: "overlay-load-shadow",
},
)),
div {
class: "seed-words",
class: format_args!("seed-words {}", if *loading.get() {"progress"} else {""}),
words.chunks_exact(2).enumerate().map(|(idx, vals)| rsx! {
div {
class: "row",
Expand Down Expand Up @@ -126,16 +183,19 @@ fn SeedWords(cx: Scope, page: UseState<AuthPages>, words: Vec<String>) -> Elemen
class: "controls",
Button {
text: get_local_text("uplink.go-back"),
disabled: *loading.get(),
aria_label: "back-button".into(),
icon: icons::outline::Shape::ChevronLeft,
onpress: move |_| page.set(AuthPages::CreateOrRecover),
appearance: Appearance::Secondary
},
Button {
aria_label: "i-saved-it-button".into(),
disabled: *loading.get(),
loading: *loading.get(),
text: get_local_text("copy-seed-words.finished"),
onpress: move |_| {
page.set(AuthPages::EnterUserName);
ch.send(());
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion ui/src/layouts/log_in/create_or_recover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub fn Layout(cx: Scope, page: UseState<AuthPages>) -> Element {
aria_label: "create-button".into(),
text: get_local_text("create-or-recover.create"),
onpress: move |_| {
page.set(AuthPages::CopySeedWords);
page.set(AuthPages::EnterUserName);
}
},
Button {
Expand Down
90 changes: 5 additions & 85 deletions ui/src/layouts/log_in/enter_username.rs
Original file line number Diff line number Diff line change
@@ -1,44 +1,23 @@
use common::icons::outline::Shape as Icon;
use common::language::get_local_text;
use common::state::configuration::Configuration;
use common::{
sounds,
warp_runner::{MultiPassCmd, WarpCmd},
WARP_CMD_CH,
};
use dioxus::prelude::*;
use dioxus_desktop::{use_window, LogicalSize};
use futures::channel::oneshot;
use futures::StreamExt;
use kit::elements::label::Label;
use kit::elements::{
button::Button,
input::{Input, Options, Validation},
};
use tracing::log;
use warp::multipass;

use crate::AuthPages;

pub const MIN_USERNAME_LEN: i32 = 4;
pub const MAX_USERNAME_LEN: i32 = 32;

struct CreateAccountCmd {
username: String,
passphrase: String,
seed_words: String,
}

#[component]
pub fn Layout(
cx: Scope,
page: UseState<AuthPages>,
pin: UseRef<String>,
seed_words: UseRef<String>,
) -> Element {
pub fn Layout(cx: Scope, page: UseState<AuthPages>, user_name: UseRef<String>) -> Element {
log::trace!("rendering enter username layout");
let window = use_window(cx);
let loading = use_state(cx, || false);

if !matches!(&*page.current(), AuthPages::Success(_)) {
window.set_inner_size(LogicalSize {
Expand All @@ -47,7 +26,6 @@ pub fn Layout(
});
}

let username = use_state(cx, String::new);
//let error = use_state(cx, String::new);
let button_disabled = use_state(cx, || true);

Expand All @@ -67,57 +45,9 @@ pub fn Layout(
special_chars: None,
};

let ch = use_coroutine(cx, |mut rx: UnboundedReceiver<CreateAccountCmd>| {
to_owned![page, loading];
async move {
let config = Configuration::load_or_default();
let warp_cmd_tx = WARP_CMD_CH.tx.clone();
while let Some(CreateAccountCmd {
username,
passphrase,
seed_words,
}) = rx.next().await
{
loading.set(true);
let (tx, rx) =
oneshot::channel::<Result<multipass::identity::Identity, warp::error::Error>>();

if let Err(e) = warp_cmd_tx.send(WarpCmd::MultiPass(MultiPassCmd::CreateIdentity {
username,
tesseract_passphrase: passphrase,
seed_words,
rsp: tx,
})) {
log::error!("failed to send warp command: {}", e);
continue;
}

let res = rx.await.expect("failed to get response from warp_runner");

match res {
Ok(ident) => {
if config.audiovideo.interface_sounds {
sounds::Play(sounds::Sounds::On);
}

page.set(AuthPages::Success(ident));
}
// todo: notify user
Err(e) => log::error!("create identity failed: {}", e),
}
}
}
});

cx.render(rsx!(
loading.get().then(|| rsx!(
div {
class: "overlay-load-shadow",
},
)),
div {
id: "unlock-layout",
class: format_args!("{}", if *loading.get() {"progress"} else {""}),
aria_label: "unlock-layout",
Label {
text: get_local_text("auth.enter-username")
Expand All @@ -134,7 +64,6 @@ pub fn Layout(
icon: Icon::Identification,
aria_label: "username-input".into(),
disable_onblur: true,
disabled: *loading.get(),
placeholder: get_local_text("auth.enter-username"),
options: Options {
with_validation: Some(username_validation),
Expand All @@ -147,30 +76,21 @@ pub fn Layout(
if *button_disabled.get() != should_disable {
button_disabled.set(should_disable);
}
username.set(val);
user_name.set(val);
},
onreturn: move |_| {
if !*button_disabled.get() {
ch.send(CreateAccountCmd {
username: username.get().to_string(),
passphrase: pin.read().to_string(),
seed_words: seed_words.read().to_string()
});
page.set(AuthPages::CopySeedWords);
}
}
},
Button {
text: get_local_text("unlock.create-account"),
aria_label: "create-account-button".into(),
appearance: kit::elements::Appearance::Primary,
loading: *loading.get(),
disabled: *button_disabled.get() || *loading.get(),
disabled: *button_disabled.get(),
onpress: move |_| {
ch.send(CreateAccountCmd {
username: username.get().to_string(),
passphrase: pin.read().to_string(),
seed_words: seed_words.read().to_string()
});
page.set(AuthPages::CopySeedWords);
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions ui/src/layouts/log_in/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub fn AuthGuard(cx: Scope, page: UseState<AuthPages>) -> Element {
log::trace!("rendering auth guard");

let pin = use_ref(cx, String::new);
let seed_words = use_ref(cx, String::new);
let user_name = use_ref(cx, String::new);
let desktop = use_window(cx);
let theme = "";

Expand Down Expand Up @@ -64,10 +64,10 @@ pub fn AuthGuard(cx: Scope, page: UseState<AuthPages>) -> Element {

match *page.current() {
AuthPages::EntryPoint => rsx!(entry_point::Layout { page: page.clone(), pin: pin.clone() }),
AuthPages::EnterUserName => rsx!(enter_username::Layout { page: page.clone(), pin: pin.clone(), seed_words: seed_words.clone() }),
AuthPages::EnterUserName => rsx!(enter_username::Layout { page: page.clone(), user_name: user_name.clone() }),
AuthPages::CreateOrRecover => rsx!(create_or_recover::Layout { page: page.clone() }),
AuthPages::EnterSeedWords => rsx!(enter_seed_words::Layout { page: page.clone(), pin: pin.clone(), }),
AuthPages::CopySeedWords => rsx!(copy_seed_words::Layout { page: page.clone(), seed_words: seed_words.clone() }),
AuthPages::CopySeedWords => rsx!(copy_seed_words::Layout { page: page.clone(), username: user_name.read().clone(), pin: pin.read().clone() }),
_ => unreachable!("this view should disappear when an account is unlocked or created"),
}
}
Expand Down
Loading