2
2
#![ forbid( unsafe_code) ]
3
3
#![ cfg_attr( not( debug_assertions) , windows_subsystem = "windows" ) ]
4
4
5
- use eframe:: egui:: { self , RichText , Vec2 , Window } ;
5
+ use eframe:: egui:: { self , Color32 , Ui , Pos2 , RichText , Vec2 , Window } ;
6
6
use tokio:: runtime:: Runtime ;
7
7
use std:: sync:: { Arc , Mutex } ;
8
8
use std:: thread;
9
+ use tokio:: time:: Duration ;
9
10
use rfd:: FileDialog ;
10
11
use autct:: autctactions:: request_audit_verify;
11
12
use autct:: config:: AutctConfig ;
@@ -25,11 +26,19 @@ struct AutctVerifierApp {
25
26
is_verif_loading : bool ,
26
27
verif_result : Arc < Mutex < Option < String > > > ,
27
28
verif_runtime : Arc < Runtime > ,
29
+ server_state : Arc < Mutex < ServerState > > ,
28
30
}
29
31
30
32
#[ derive( Debug ) ]
31
33
struct CustomError ( String ) ;
32
34
35
+ #[ derive( PartialEq , Clone , Copy ) ]
36
+ enum ServerState {
37
+ NotStarted ,
38
+ Running ,
39
+ Ready ,
40
+ }
41
+
33
42
#[ tokio:: main]
34
43
async fn main ( ) -> eframe:: Result {
35
44
let mut myapp: AutctVerifierApp = AutctVerifierApp :: default ( ) ;
@@ -88,6 +97,64 @@ impl AutctVerifierApp {
88
97
* result. lock ( ) . unwrap ( ) = Some ( res) ;
89
98
} ) ;
90
99
}
100
+
101
+ /// Starts the verification server in the background
102
+ /// by calling std::process:Command
103
+ fn start_server ( & self ) {
104
+ let server_state = Arc :: clone (
105
+ & self . server_state ) ;
106
+
107
+ // Spawn a new thread to run the process
108
+ thread:: spawn ( move || {
109
+ {
110
+ let mut state = server_state. lock ( ) . unwrap ( ) ;
111
+ * state = ServerState :: Running ;
112
+ }
113
+
114
+ // Simulate running the process
115
+ // Replace this with the actual command,
116
+ // `std::process::Command::new(
117
+ // "./autct -k dummycontext:keysetfile -n network")`
118
+ thread:: sleep ( Duration :: from_secs ( 5 ) ) ;
119
+
120
+ // Need some kind of hook to trigger this independently,
121
+ // because the above process is a daemon not a batch process.
122
+ {
123
+ let mut state = server_state. lock ( ) . unwrap ( ) ;
124
+ * state = ServerState :: Ready ;
125
+ }
126
+ } ) ;
127
+ }
128
+
129
+ fn update_dot ( & mut self , ctx : & egui:: Context , dot_pos : & Pos2 , dot_radius : f32 ) {
130
+ // Determine the color of the dot based on the verification
131
+ // server(called in the background)'s state:
132
+ let process_state = * self . server_state . lock ( ) . unwrap ( ) ;
133
+ let dot_color = match process_state {
134
+ ServerState :: NotStarted => Color32 :: BLUE ,
135
+ ServerState :: Running => Color32 :: YELLOW ,
136
+ ServerState :: Ready => Color32 :: GREEN ,
137
+ } ;
138
+ egui:: Area :: new ( "circle_area" . into ( ) )
139
+ . fixed_pos ( * dot_pos)
140
+ . show ( ctx, |ui| {
141
+ // Create an interactable area using `ui.allocate_response`
142
+ let response = ui. allocate_response (
143
+ Vec2 :: splat ( dot_radius * 2.0 ) ,
144
+ egui:: Sense :: click ( ) ,
145
+ ) ;
146
+
147
+ // Draw the circle
148
+ let painter = ui. painter ( ) ;
149
+ painter. circle_filled ( * dot_pos, dot_radius, dot_color) ;
150
+
151
+ // Handle click on the circle
152
+ if response. clicked ( ) && process_state == ServerState :: NotStarted {
153
+ println ! ( "Circle clicked! Starting the process..." ) ;
154
+ self . start_server ( ) ;
155
+ }
156
+ } ) ;
157
+ }
91
158
}
92
159
93
160
impl Default for AutctVerifierApp {
@@ -103,6 +170,7 @@ impl Default for AutctVerifierApp {
103
170
is_verif_loading : false ,
104
171
verif_result : Arc :: new ( Mutex :: new ( None ) ) ,
105
172
verif_runtime : Arc :: new ( Runtime :: new ( ) . unwrap ( ) ) ,
173
+ server_state : Arc :: new ( Mutex :: new ( ServerState :: NotStarted ) ) ,
106
174
}
107
175
}
108
176
}
@@ -112,8 +180,24 @@ impl eframe::App for AutctVerifierApp {
112
180
// Point of discussion: I think dark mode will work
113
181
// a little better than light:
114
182
//ctx.set_visuals(egui::Visuals::light());
115
- let available_height = ctx. available_rect ( ) . height ( ) ;
116
183
184
+ // GUI does not respond to updates unless
185
+ // user acts (e.g. mouse events), by default,
186
+ // so force it:
187
+ ctx. request_repaint ( ) ;
188
+
189
+ // Calculate the correct center and radius
190
+ // for the dot, and its reaction area:
191
+ let screen_rect = ctx. screen_rect ( ) ;
192
+ let dot_pos = Pos2 :: new ( screen_rect. max . x - 20.0 ,
193
+ screen_rect. max . y - 20.0 ) ;
194
+ // This is very close to the edge?:
195
+ let dot_radius = 15.0 ;
196
+ self . update_dot ( ctx, & dot_pos, dot_radius) ;
197
+
198
+ // bottom section contains verification action and result.
199
+ // use 25% of height:
200
+ let available_height = ctx. available_rect ( ) . height ( ) ;
117
201
egui:: TopBottomPanel :: bottom ( "actionpanel" )
118
202
. min_height ( available_height * 0.25 )
119
203
. show ( ctx, |ui| {
0 commit comments