@@ -472,13 +472,15 @@ impl Station {
472472#[ derive( Clone , Debug , Default ) ]
473473pub struct WiFiDeviceList < T : WiFiDeviceType > {
474474 devices : HashMap < MacAddress , T > ,
475+ devices_sorted : Vec < T > ,
475476}
476477
477478// Common functions for any type of device
478479impl < T : WiFiDeviceType > WiFiDeviceList < T > {
479480 pub fn new ( ) -> Self {
480481 WiFiDeviceList {
481482 devices : HashMap :: new ( ) ,
483+ devices_sorted : Vec :: new ( ) ,
482484 }
483485 }
484486
@@ -561,6 +563,75 @@ impl WiFiDeviceList<AccessPoint> {
561563 all_clients
562564 }
563565
566+ pub fn sort_devices ( & mut self , sort : u8 , sort_reverse : bool ) {
567+ let mut access_points: Vec < AccessPoint > = self
568+ . get_devices ( )
569+ . iter ( )
570+ . map ( |( _, access_point) | access_point. clone ( ) )
571+ . collect ( ) ;
572+
573+ match sort {
574+ 0 => access_points. sort_by ( |a, b| {
575+ // TGT
576+ match (
577+ a. is_target ( ) ,
578+ a. is_whitelisted ( ) ,
579+ b. is_target ( ) ,
580+ b. is_whitelisted ( ) ,
581+ ) {
582+ // Highest priority: is_target() = true, is_whitelist() = false
583+ ( true , false , _, _) => std:: cmp:: Ordering :: Less ,
584+ ( _, _, true , false ) => std:: cmp:: Ordering :: Greater ,
585+
586+ // Middle priority: is_target() = false, is_whitelist() = false
587+ ( false , false , false , true ) => std:: cmp:: Ordering :: Less ,
588+ ( false , true , false , false ) => std:: cmp:: Ordering :: Greater ,
589+
590+ // Lowest priority: is_target() = false, is_whitelist() = true
591+ // This case is covered implicitly by the previous matches
592+
593+ // Fallback for equal cases
594+ _ => std:: cmp:: Ordering :: Equal ,
595+ }
596+ } ) ,
597+ 1 => access_points. sort_by ( |a, b| b. channel . cmp ( & a. channel ) ) , // CH
598+ 2 => access_points. sort_by ( |a, b| {
599+ // RSSI
600+ let a_val = a. last_signal_strength . value ;
601+ let b_val = b. last_signal_strength . value ;
602+
603+ match ( a_val, b_val) {
604+ // If both values are the same (and it doesn't matter if they are zero or not)
605+ _ if a_val == b_val => std:: cmp:: Ordering :: Equal ,
606+
607+ // Prioritize any non-zero value over zero
608+ ( 0 , _) => std:: cmp:: Ordering :: Greater , // A is worse if it's zero
609+ ( _, 0 ) => std:: cmp:: Ordering :: Less , // B is worse if it's zero
610+
611+ // Otherwise, just do a normal comparison
612+ _ => b_val. cmp ( & a_val) ,
613+ }
614+ } ) ,
615+ 3 => access_points. sort_by ( |a, b| b. last_recv . cmp ( & a. last_recv ) ) , // Last
616+ 4 => access_points. sort_by ( |a, b| b. client_list . size ( ) . cmp ( & a. client_list . size ( ) ) ) , // Clients
617+ 5 => access_points. sort_by ( |a, b| b. interactions . cmp ( & a. interactions ) ) , // Tx
618+ 6 => access_points. sort_by ( |a, b| b. has_hs . cmp ( & a. has_hs ) ) , // HS
619+ 7 => access_points. sort_by ( |a, b| b. has_pmkid . cmp ( & a. has_pmkid ) ) , // PM
620+ _ => {
621+ access_points. sort_by ( |a, b| b. last_recv . cmp ( & a. last_recv ) ) ;
622+ }
623+ }
624+
625+ if sort_reverse {
626+ access_points. reverse ( ) ;
627+ }
628+ self . devices_sorted = access_points;
629+ }
630+
631+ pub fn get_devices_sorted ( & self ) -> & Vec < AccessPoint > {
632+ & self . devices_sorted
633+ }
634+
564635 pub fn clear_all_interactions ( & mut self ) {
565636 for dev in self . devices . values_mut ( ) {
566637 dev. interactions = 0 ;
@@ -621,8 +692,6 @@ impl WiFiDeviceList<AccessPoint> {
621692 selected_row : Option < usize > ,
622693 sort : u8 ,
623694 sort_reverse : bool ,
624- copys : bool ,
625- copyl : bool ,
626695 ) -> ( Vec < String > , Vec < ( Vec < String > , u16 ) > ) {
627696 // Header fields
628697 let headers = vec ! [
@@ -638,66 +707,8 @@ impl WiFiDeviceList<AccessPoint> {
638707 "PMKID" . to_string( ) ,
639708 ] ;
640709
641- let mut access_points: Vec < _ > = self
642- . get_devices ( )
643- . iter ( )
644- . map ( |( _, access_point) | access_point)
645- . collect ( ) ;
646- match sort {
647- 0 => access_points. sort_by ( |a, b| {
648- // TGT
649- match (
650- a. is_target ( ) ,
651- a. is_whitelisted ( ) ,
652- b. is_target ( ) ,
653- b. is_whitelisted ( ) ,
654- ) {
655- // Highest priority: is_target() = true, is_whitelist() = false
656- ( true , false , _, _) => std:: cmp:: Ordering :: Less ,
657- ( _, _, true , false ) => std:: cmp:: Ordering :: Greater ,
658-
659- // Middle priority: is_target() = false, is_whitelist() = false
660- ( false , false , false , true ) => std:: cmp:: Ordering :: Less ,
661- ( false , true , false , false ) => std:: cmp:: Ordering :: Greater ,
662-
663- // Lowest priority: is_target() = false, is_whitelist() = true
664- // This case is covered implicitly by the previous matches
665-
666- // Fallback for equal cases
667- _ => std:: cmp:: Ordering :: Equal ,
668- }
669- } ) ,
670- 1 => access_points. sort_by ( |a, b| b. channel . cmp ( & a. channel ) ) , // CH
671- 2 => access_points. sort_by ( |a, b| {
672- // RSSI
673- let a_val = a. last_signal_strength . value ;
674- let b_val = b. last_signal_strength . value ;
675-
676- match ( a_val, b_val) {
677- // If both values are the same (and it doesn't matter if they are zero or not)
678- _ if a_val == b_val => std:: cmp:: Ordering :: Equal ,
679-
680- // Prioritize any non-zero value over zero
681- ( 0 , _) => std:: cmp:: Ordering :: Greater , // A is worse if it's zero
682- ( _, 0 ) => std:: cmp:: Ordering :: Less , // B is worse if it's zero
683-
684- // Otherwise, just do a normal comparison
685- _ => b_val. cmp ( & a_val) ,
686- }
687- } ) ,
688- 3 => access_points. sort_by ( |a, b| b. last_recv . cmp ( & a. last_recv ) ) , // Last
689- 4 => access_points. sort_by ( |a, b| b. client_list . size ( ) . cmp ( & a. client_list . size ( ) ) ) , // Clients
690- 5 => access_points. sort_by ( |a, b| b. interactions . cmp ( & a. interactions ) ) , // Tx
691- 6 => access_points. sort_by ( |a, b| b. has_hs . cmp ( & a. has_hs ) ) , // HS
692- 7 => access_points. sort_by ( |a, b| b. has_pmkid . cmp ( & a. has_pmkid ) ) , // PM
693- _ => {
694- access_points. sort_by ( |a, b| b. last_recv . cmp ( & a. last_recv ) ) ;
695- }
696- }
697-
698- if sort_reverse {
699- access_points. reverse ( ) ;
700- }
710+ self . sort_devices ( sort, sort_reverse) ;
711+ let access_points = & self . devices_sorted ;
701712
702713 let mut rows: Vec < ( Vec < String > , u16 ) > = Vec :: new ( ) ;
703714 for ( idx, ap) in access_points. iter ( ) . enumerate ( ) {
@@ -746,12 +757,7 @@ impl WiFiDeviceList<AccessPoint> {
746757 ap_row = merged;
747758 height += 1 ;
748759 }
749- if copys {
750- terminal_clipboard:: set_string ( ap. mac_address . to_string ( ) ) . unwrap ( ) ;
751- }
752- if copyl {
753- terminal_clipboard:: set_string ( ap. to_json_str ( ) ) . unwrap ( ) ;
754- }
760+
755761 }
756762 rows. push ( ( ap_row, height) ) ;
757763 }
@@ -851,31 +857,11 @@ fn add_probe_rows(
851857
852858// Functions specific to a WiFiDeviceList holding Stations
853859impl WiFiDeviceList < Station > {
854- pub fn get_table (
855- & mut self ,
856- selected_row : Option < usize > ,
857- sort : u8 ,
858- sort_reverse : bool ,
859- copys : bool ,
860- copyl : bool ,
861- ) -> ( Vec < String > , Vec < ( Vec < String > , u16 ) > ) {
862- // Header fields
863- //"MAC Address", "RSSI", "Last", Tx, "Probes"
864- let headers = vec ! [
865- "MAC Address" . to_string( ) ,
866- "RSSI" . to_string( ) ,
867- "Last" . to_string( ) ,
868- "Tx" . to_string( ) ,
869- "Rogue M2" . to_string( ) ,
870- "Probes" . to_string( ) ,
871- ] ;
872-
873- // Make our stations object
874-
860+ pub fn sort_devices ( & mut self , sort : u8 , sort_reverse : bool ) {
875861 let mut stations: Vec < _ > = self
876862 . get_devices ( )
877863 . iter ( )
878- . map ( |( _, access_point ) | access_point )
864+ . map ( |( _, station ) | station . clone ( ) )
879865 . collect ( ) ;
880866
881867 match sort {
@@ -914,6 +900,33 @@ impl WiFiDeviceList<Station> {
914900 if sort_reverse {
915901 stations. reverse ( ) ;
916902 }
903+ self . devices_sorted = stations;
904+ }
905+
906+ pub fn get_devices_sorted ( & self ) -> & Vec < Station > {
907+ & self . devices_sorted
908+ }
909+
910+ pub fn get_table (
911+ & mut self ,
912+ selected_row : Option < usize > ,
913+ sort : u8 ,
914+ sort_reverse : bool
915+ ) -> ( Vec < String > , Vec < ( Vec < String > , u16 ) > ) {
916+ // Header fields
917+ //"MAC Address", "RSSI", "Last", Tx, "Probes"
918+ let headers = vec ! [
919+ "MAC Address" . to_string( ) ,
920+ "RSSI" . to_string( ) ,
921+ "Last" . to_string( ) ,
922+ "Tx" . to_string( ) ,
923+ "Rogue M2" . to_string( ) ,
924+ "Probes" . to_string( ) ,
925+ ] ;
926+
927+ // Make our stations object
928+ self . sort_devices ( sort, sort_reverse) ;
929+ let stations = & self . devices_sorted ;
917930
918931 let mut rows: Vec < ( Vec < String > , u16 ) > = Vec :: new ( ) ;
919932 for ( idx, station) in stations. iter ( ) . enumerate ( ) {
@@ -954,12 +967,6 @@ impl WiFiDeviceList<Station> {
954967 height += 1 ;
955968 }
956969 }
957- if copys {
958- terminal_clipboard:: set_string ( station. mac_address . to_string ( ) ) . unwrap ( ) ;
959- }
960- if copyl {
961- terminal_clipboard:: set_string ( station. to_json_str ( ) ) . unwrap ( ) ;
962- }
963970 }
964971 rows. push ( ( cl_row, height) ) ;
965972 }
0 commit comments