fix: show oauth url and code properly on device auth popup

- Auth flow now waits for user's Enter before starting
- Start auth only when user presses Enter on DeviceAuth popup
- Proper error handling: missing GOOGLE_CLIENT_ID shows clear message
- Error messages displayed in popup with Retry option
- Popup shows instructions before auth, URL+code during auth
- Handle both verification_url and verification_uri field names from Google
- Check HTTP status code and show error_description on failures
- AuthError propagated to render function for display
- Popup border turns green when URL+code are ready
This commit is contained in:
Ruben Rosario
2026-06-20 19:56:41 +01:00
parent 320a9c2572
commit 985e8c9bc9
5 changed files with 138 additions and 61 deletions
+61 -18
View File
@@ -298,39 +298,82 @@ pub fn render_device_auth_popup(
area: Rect,
url: &str,
code: &str,
error: Option<&str>,
) {
let popup_area = centered_rect(70, 9, area);
let popup_area = centered_rect(75, 11, area);
let border_color = if error.is_some() {
Color::Red
} else if url.is_empty() {
POPUP_BORDER
} else {
Color::Green
};
let block = Block::default()
.borders(Borders::ALL)
.style(Style::default().bg(POPUP_BG))
.border_style(Style::default().fg(POPUP_BORDER))
.border_style(Style::default().fg(border_color))
.title(" Google OAuth ")
.title_alignment(Alignment::Left);
let text = Text::from(vec![
Line::from(""),
Line::from(Span::styled(
let mut lines = Vec::new();
if let Some(err) = error {
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
format!(" ERROR: {} ", err),
Style::default().fg(Color::Red).add_modifier(Modifier::BOLD),
)));
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
" Press Enter to retry or Esc to cancel ",
Style::default().fg(Color::DarkGray),
)));
} else if url.is_empty() {
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
" Google Tasks Authorization Required ",
Style::default().fg(Color::White).add_modifier(Modifier::BOLD),
)));
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
" Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET env vars ",
Style::default().fg(Color::Yellow),
)));
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
" Press Enter to start authorization ",
Style::default().fg(Color::Cyan),
)));
lines.push(Line::from(Span::styled(
" Press Esc to skip ",
Style::default().fg(Color::DarkGray),
)));
} else {
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
" Visit the following URL to authorize: ",
Style::default().fg(Color::White),
)),
Line::from(""),
Line::from(Span::styled(
)));
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
url,
Style::default().fg(Color::Cyan).add_modifier(Modifier::UNDERLINED),
)),
Line::from(" "),
Line::from(Span::styled(
)));
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
format!(" Enter code: {} ", code),
Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD),
)),
Line::from(""),
Line::from(Span::styled(
" After authorizing, press Enter to continue... ",
)));
lines.push(Line::from(""));
lines.push(Line::from(Span::styled(
" Waiting for authorization... (Esc to cancel) ",
Style::default().fg(Color::DarkGray),
)),
]);
)));
}
let paragraph = Paragraph::new(text)
let paragraph = Paragraph::new(Text::from(lines))
.block(block)
.alignment(Alignment::Center);