Skip to content
Open
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
100 changes: 85 additions & 15 deletions src/verification_modal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,32 @@ script_mod! {
use mod.widgets.*


mod.widgets.VerificationEmojiCell = View {
width: Fit, height: Fit
flow: Down
align: Align{x: 0.5}
padding: Inset{top: 6, right: 6, bottom: 6, left: 6}
spacing: 4

symbol := Label {
width: Fit, height: Fit
align: Align{x: 0.5}
draw_text +: {
text_style: REGULAR_TEXT {font_size: 30},
color: #000
}
}
description := Label {
width: Fit{max: FitBound.Abs(72.0)}, height: Fit

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, i don't quite understand this width choice. Can you explain why we need a max width here? Seems like for something like this we would want both the symbol and the description to have a fixed width (perhaps 72 as you used for the max width here).

I can't think of a scenario where we'd need a width that is Fit but expands to a max of 72. But let me know if i'm overlooking something.

flow: Flow.Right{wrap: true}
align: Align{x: 0.5}
draw_text +: {
text_style: REGULAR_TEXT {font_size: 9},
color: #000
}
}
}

mod.widgets.VerificationModal = set_type_default() do #(VerificationModal::register_widget(vm)) {
..mod.widgets.SmallModal

Expand All @@ -19,6 +45,24 @@ script_mod! {

body := ModalBody {}

// SAS V1 always produces exactly 7 emojis, so 7 cells are declared up front.
emojis_view := View {
width: Fill, height: Fit
flow: Flow.Right{wrap: true}
align: Align{x: 0.5}
spacing: 10
margin: Inset{top: 15, bottom: 5}
visible: false

emoji0 := mod.widgets.VerificationEmojiCell {}
emoji1 := mod.widgets.VerificationEmojiCell {}
emoji2 := mod.widgets.VerificationEmojiCell {}
emoji3 := mod.widgets.VerificationEmojiCell {}
emoji4 := mod.widgets.VerificationEmojiCell {}
emoji5 := mod.widgets.VerificationEmojiCell {}
emoji6 := mod.widgets.VerificationEmojiCell {}
}

buttons_view := ModalButtonsRow {
margin: Inset{top: 30}

Expand Down Expand Up @@ -111,6 +155,10 @@ impl WidgetMatchEvent for VerificationModal {
// Outgoing verification requests start with the accept button hidden
// since we're still in the waiting state then, so show it now
accept_button.set_visible(cx, true);
// The emoji grid is only relevant during the `KeysExchanged` emoji
// step; hide it by default and let that branch re-show it, so it
// never leaks into other states.
Comment on lines +158 to +160

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please don't use LLM-style comments. This can be really simple.

Suggested change
// The emoji grid is only relevant during the `KeysExchanged` emoji
// step; hide it by default and let that branch re-show it, so it
// never leaks into other states.
// The emoji grid is hidden by default and only shown during emoji verification.

self.view.view(cx, ids!(emojis_view)).set_visible(cx, false);
match verification_action {
VerificationAction::RequestCancelled(cancel_info) => {
self.label(cx, ids!(body)).set_text(
Expand Down Expand Up @@ -193,26 +241,25 @@ impl WidgetMatchEvent for VerificationModal {
}

VerificationAction::KeysExchanged { emojis, decimals } => {
let text = if let Some(emoji_list) = emojis {
format!(
"Keys have been exchanged. Please verify the following emoji:\
\n {}\n\n\
if let Some(emoji_list) = emojis {
self.label(cx, ids!(body)).set_text(
cx,
"Keys have been exchanged. Please verify the following emoji:\n\n\
Do these emoji keys match?",
emoji_list.emojis
.iter()
.map(|em| format!("{} ({})", em.symbol, em.description))
.collect::<Vec<_>>()
.join("\n ")
)
);
for (index, emoji) in emoji_list.emojis.iter().enumerate() {
self.populate_emoji_cell(cx, index, emoji.symbol, emoji.description);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is better than the previous C-style loop that you had before, but we can do even better than this with Rust. Check out the .zip() iterator function, which will let you iterate over the emoji list and the set of emoji cells in lockstep, which itself will let you avoid the match index { ... } block in populate_emoji_cell().

Once you see how that works, you'll recognize that you can also easily move the body of populate_emoji_cell() (which is really just the two lines that set the symbol and description labels) directly into this code block.

self.view.view(cx, ids!(emojis_view)).set_visible(cx, true);
} else {
format!(
let text = format!(
"Keys have been exchanged. Please verify the following numbers:\n\
\n {}\n {}\n {}\n\n\
Do these number keys match?",
decimals.0, decimals.1, decimals.2,
)
};
self.label(cx, ids!(body)).set_text(cx, &text);
);
self.label(cx, ids!(body)).set_text(cx, &text);
}
accept_button.set_enabled(cx, true);
accept_button.set_text(cx, "Yes");
cancel_button.set_text(cx, "No");
Expand Down Expand Up @@ -245,7 +292,12 @@ impl WidgetMatchEvent for VerificationModal {
}

VerificationAction::RequestCompleted => {
self.label(cx, ids!(body)).set_text(cx, "Verification completed successfully!");
self.label(cx, ids!(body)).set_text(
cx,
"Verification completed successfully!\n\
Now you can send and receive encrypted messages, \
and everyone you chat with can trust this device is yours.",
);
accept_button.set_text(cx, "Ok");
accept_button.set_enabled(cx, true);
cancel_button.set_visible(cx, false);
Expand All @@ -270,6 +322,21 @@ impl VerificationModal {
self.is_final = false;
}

fn populate_emoji_cell(&mut self, cx: &mut Cx, index: usize, symbol: &str, description: &str) {
let cell = match index {
0 => self.view.view(cx, ids!(emoji0)),
1 => self.view.view(cx, ids!(emoji1)),
2 => self.view.view(cx, ids!(emoji2)),
3 => self.view.view(cx, ids!(emoji3)),
4 => self.view.view(cx, ids!(emoji4)),
5 => self.view.view(cx, ids!(emoji5)),
6 => self.view.view(cx, ids!(emoji6)),
_ => return,
};
cell.label(cx, ids!(symbol)).set_text(cx, symbol);
cell.label(cx, ids!(description)).set_text(cx, description);
}

fn initialize_with_data(
&mut self,
cx: &mut Cx,
Expand All @@ -296,6 +363,9 @@ impl VerificationModal {
).into()
};
self.label(cx, ids!(body)).set_text(cx, &prompt_text);
// Ensure the emoji grid from any prior verification is not shown
// on the initial prompt screen.
Comment on lines +366 to +367

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, LLM comments like this aren't necessary, you can just delete it entirely. Good comments explain a design choice or why we're doing something complex that is non-obvious, but here it is very obvious what's happening.

Suggested change
// Ensure the emoji grid from any prior verification is not shown
// on the initial prompt screen.

self.view.view(cx, ids!(emojis_view)).set_visible(cx, false);

let accept_button = self.button(cx, ids!(accept_button));
let cancel_button = self.button(cx, ids!(cancel_button));
Expand Down
Loading