@@ -1397,90 +1397,102 @@ impl BitVaultApp {
13971397
13981398 // Helper function to draw arrow navigation indicators
13991399 fn draw_navigation_arrows ( & self , ui : & mut Ui , screen_number : usize ) {
1400- let total_width = ui. available_width ( ) ;
1400+ // Available width needed for centering calculation
1401+ let available_width = ui. available_width ( ) ;
1402+
1403+ // Create fixed-width dots
1404+ let active_width = 15.0 ;
1405+ let inactive_width = 5.0 ;
1406+ let dot_height = 4.0 ; // Slightly thicker for better visibility while still bead-like
1407+ let dot_spacing = 3.0 ;
1408+ let click_padding = 12.0 ; // Larger click area padding for better usability
1409+
1410+ // Calculate total width of all dots
1411+ let total_dot_width = match screen_number {
1412+ 1 => active_width + 2.0 * inactive_width + 2.0 * dot_spacing,
1413+ 2 => inactive_width + active_width + inactive_width + 2.0 * dot_spacing,
1414+ 3 => 2.0 * inactive_width + active_width + 2.0 * dot_spacing,
1415+ _ => active_width + 2.0 * inactive_width + 2.0 * dot_spacing,
1416+ } ;
1417+
1418+ // Add space for centering
1419+ let left_padding = ( available_width - total_dot_width) / 2.0 ;
14011420
14021421 ui. horizontal ( |ui| {
1403- // Left padding - depends on the current screen (no left arrow on first screen)
1404- let left_arrow_visible = screen_number > 1 ;
1405- let offset_mult = if left_arrow_visible { 6.0 } else { 7.5 } ;
1406- ui. add_space ( total_width / offset_mult) ;
1407-
1408- // Left arrow - only for screens 2 and 3
1409- if left_arrow_visible {
1410- // Use separate labels for emoji and text to avoid rendering issues
1411- ui. label (
1412- RichText :: new ( "◀" )
1413- . color ( Color32 :: from_rgb ( 120 , 120 , 120 ) )
1414- . size ( 16.0 ) ,
1415- ) ;
1416- ui. add_space ( 2.0 ) ;
1417- ui. label (
1418- RichText :: new ( "Prev" )
1419- . color ( Color32 :: from_rgb ( 120 , 120 , 120 ) )
1420- . size ( 16.0 ) ,
1421- ) ;
1422- ui. add_space ( 10.0 ) ;
1423- }
1422+ ui. add_space ( left_padding) ;
1423+
1424+ // Create a container for our dots with extra height for easier clicking
1425+ let response = ui. allocate_rect (
1426+ egui:: Rect :: from_min_size (
1427+ ui. cursor ( ) . min ,
1428+ egui:: vec2 ( total_dot_width, dot_height + click_padding) ,
1429+ ) ,
1430+ egui:: Sense :: click ( ) , // Make the entire area clickable
1431+ ) ;
14241432
1425- // Indicator dots
1433+ // Draw the dots directly using the painter
1434+ let painter = ui. painter ( ) ;
1435+ let mut current_x = response. rect . min . x ;
1436+ let center_y = response. rect . center ( ) . y ;
1437+
1438+ // Store click positions for later processing
1439+ let mut click_areas = Vec :: new ( ) ;
1440+
1441+ // Draw all dots
14261442 for i in 1 ..=3 {
14271443 if i > 1 {
1428- ui . add_space ( 4.0 ) ;
1444+ current_x += dot_spacing ;
14291445 }
14301446
1431- if i == screen_number {
1432- // Active indicator
1433- ui. add (
1434- egui:: widgets:: Button :: new ( "" )
1435- . min_size ( egui:: vec2 ( 15.0 , 5.0 ) )
1436- . fill ( Color32 :: from_rgb ( 17 , 165 , 238 ) )
1437- . frame ( false ) ,
1438- ) ;
1447+ // Determine dot properties based on state
1448+ let ( width, color) = if i == screen_number {
1449+ ( active_width, Color32 :: from_rgb ( 17 , 165 , 238 ) )
14391450 } else {
1440- // Inactive indicator (clickable)
1441- let clicked = ui
1442- . add (
1443- egui:: widgets:: Button :: new ( "" )
1444- . min_size ( egui:: vec2 ( 5.0 , 5.0 ) )
1445- . fill ( Color32 :: from_rgb ( 217 , 217 , 217 ) )
1446- . frame ( false ) ,
1447- )
1448- . clicked ( ) ;
1449-
1450- if clicked {
1451- // Store which view to navigate to
1452- let target_view = match i {
1453- 1 => View :: OnboardingOne ,
1454- 2 => View :: OnboardingTwo ,
1455- 3 => View :: OnboardingThree ,
1456- _ => View :: OnboardingOne , // Fallback
1457- } ;
1458-
1459- // Update state in a separate step after UI is processed
1460- ui. ctx ( ) . request_repaint ( ) ;
1451+ ( inactive_width, Color32 :: from_rgb ( 217 , 217 , 217 ) )
1452+ } ;
14611453
1462- if let Ok ( mut state) = self . state . write ( ) {
1463- state. current_view = target_view;
1464- }
1465- }
1454+ // Calculate the dot rectangle
1455+ let dot_rect = egui:: Rect :: from_min_size (
1456+ egui:: pos2 ( current_x, center_y - dot_height / 2.0 ) ,
1457+ egui:: vec2 ( width, dot_height) ,
1458+ ) ;
1459+
1460+ // Draw the dot
1461+ painter. rect_filled ( dot_rect, dot_height / 2.0 , color) ;
1462+
1463+ // Store click area if this is an inactive dot
1464+ if i != screen_number {
1465+ // Create a larger clickable area
1466+ let click_rect = egui:: Rect :: from_min_max (
1467+ egui:: pos2 ( current_x - 2.0 , center_y - ( click_padding / 2.0 ) ) ,
1468+ egui:: pos2 ( current_x + width + 2.0 , center_y + ( click_padding / 2.0 ) ) ,
1469+ ) ;
1470+
1471+ click_areas. push ( ( click_rect, i) ) ;
14661472 }
1473+
1474+ // Move to the next dot position
1475+ current_x += width;
14671476 }
14681477
1469- // Right arrow - only for screens 1 and 2
1470- if screen_number < 3 {
1471- ui. add_space ( 10.0 ) ;
1472- // Use separate labels for text and emoji to avoid rendering issues
1473- ui. label (
1474- RichText :: new ( "Next" )
1475- . color ( Color32 :: from_rgb ( 120 , 120 , 120 ) )
1476- . size ( 16.0 ) ,
1477- ) ;
1478- ui. add_space ( 2.0 ) ;
1479- ui. label (
1480- RichText :: new ( "▶" )
1481- . color ( Color32 :: from_rgb ( 120 , 120 , 120 ) )
1482- . size ( 16.0 ) ,
1483- ) ;
1478+ // Handle clicks for navigation
1479+ if response. clicked ( ) {
1480+ if let Some ( mouse_pos) = ui. ctx ( ) . pointer_latest_pos ( ) {
1481+ // Handle clicks directly on dots
1482+ for ( rect, idx) in click_areas {
1483+ if rect. contains ( mouse_pos) {
1484+ if let Ok ( mut state) = self . state . write ( ) {
1485+ state. current_view = match idx {
1486+ 1 => View :: OnboardingOne ,
1487+ 2 => View :: OnboardingTwo ,
1488+ 3 => View :: OnboardingThree ,
1489+ _ => View :: OnboardingOne ,
1490+ } ;
1491+ }
1492+ break ;
1493+ }
1494+ }
1495+ }
14841496 }
14851497 } ) ;
14861498 }
0 commit comments