1717from time import sleep
1818from typing import Callable
1919from functools import partial
20+ import regex as re
2021
2122from flet import (
2223 UserControl ,
2930 Container ,
3031 Switch ,
3132 alignment ,
33+ ProgressBar ,
34+ ProgressRing ,
3235 colors ,
3336)
3437
@@ -99,6 +102,9 @@ def check_advanced_switch(e):
99102 # text box for terminal output
100103 self .terminal_box = TerminalBox (expand = True )
101104
105+ # container for progress indicators
106+ self .progress_indicator = ProgressIndicator (expand = True )
107+
102108 # main controls
103109 steps_indictor_img_lookup = {
104110 "Unlock the bootloader" : "steps-header-unlock.png" ,
@@ -127,6 +133,7 @@ def check_advanced_switch(e):
127133 self .right_view .controls .extend (
128134 [
129135 Row ([self .error_text ]),
136+ Row ([self .progress_indicator ]),
130137 Column (
131138 [
132139 self .advanced_switch ,
@@ -145,6 +152,7 @@ def check_advanced_switch(e):
145152 [
146153 self .inputtext ,
147154 Row ([self .error_text ]),
155+ Row ([self .progress_indicator ]),
148156 Column (
149157 [
150158 self .advanced_switch ,
@@ -188,6 +196,8 @@ def call_to_phone(self, e, command: str):
188196 """
189197 # disable the call button while the command is running
190198 self .call_button .disabled = True
199+ # reset the progress indicators
200+ self .progress_indicator .clear ()
191201 # reset terminal output
192202 if self .state .advanced :
193203 self .terminal_box .clear ()
@@ -225,7 +235,14 @@ def call_to_phone(self, e, command: str):
225235 # run the right command
226236 if command in cmd_mapping .keys ():
227237 for line in cmd_mapping .get (command )(bin_path = self .state .bin_path ):
238+ # write the line to advanced output terminal
228239 self .terminal_box .write_line (line )
240+ # in case the install command is run, we want to update the progress bar
241+ if command == "adb_twrp_wipe_and_install" :
242+ self .progress_indicator .display_progress_bar (line )
243+ self .progress_indicator .update ()
244+ else :
245+ self .progress_indicator .display_progress_ring ()
229246 else :
230247 msg = f"Unknown command type: { command } . Stopping."
231248 logger .error (msg )
@@ -242,9 +259,12 @@ def call_to_phone(self, e, command: str):
242259 else :
243260 sleep (5 ) # wait to make sure everything is fine
244261 logger .success (f"Command { command } run successfully. Allow to continue." )
245- # emable the confirm buton and disable the call button
262+ # enable the confirm button and disable the call button
246263 self .confirm_button .disabled = False
247264 self .call_button .disabled = True
265+ # reset the progress indicator (let the progressbar stay for the install command)
266+ if command != "adb_twrp_wipe_and_install" :
267+ self .progress_indicator .clear ()
248268 self .view .update ()
249269
250270
@@ -277,7 +297,7 @@ def write_line(self, line: str):
277297 self .update ()
278298
279299 def toggle_visibility (self ):
280- """Toogle the visibility of the terminal box."""
300+ """Toggle the visibility of the terminal box."""
281301 self ._box .visible = not self ._box .visible
282302 self .update ()
283303
@@ -289,3 +309,70 @@ def clear(self):
289309 def update (self ):
290310 """Update the view."""
291311 self ._box .update ()
312+
313+
314+ class ProgressIndicator (UserControl ):
315+ def __init__ (self , expand : bool = True ):
316+ super ().__init__ (expand = expand )
317+ # placeholder for the flashing progressbar
318+ self .progress_bar = None
319+ # progress ring to display
320+ self .progress_ring = None
321+
322+ def build (self ):
323+ self ._container = Container (
324+ content = Column (scroll = "auto" , expand = True ),
325+ margin = 10 ,
326+ alignment = alignment .center ,
327+ height = 50 ,
328+ expand = True ,
329+ visible = True ,
330+ )
331+ return self ._container
332+
333+ def display_progress_bar (self , line : str ):
334+ """Display and update the progress bar for the given line."""
335+ percentage_done = None
336+ result = None
337+ # get the progress numbers from the output lines
338+ if (type (line ) == str ) and line .strip ():
339+ result = re .search (r"\(\~(\d{1,3})\%\)|(Total xfer: 1\.00x)" , line .strip ())
340+ if result :
341+ if result .group (1 ):
342+ percentage_done = int (result .group (1 ))
343+ elif result .group (2 ):
344+ percentage_done = 100
345+
346+ # create the progress bar on first occurrence
347+ if percentage_done == 0 :
348+ self .progress_bar = ProgressBar (
349+ width = 500 , bar_height = 32 , color = "#00d886" , bgcolor = "#eeeeee"
350+ )
351+ self .percentage_text = Text (f"{ percentage_done } %" )
352+ self ._container .content .controls .append (
353+ Row ([self .percentage_text , self .progress_bar ])
354+ )
355+ # update the progress bar
356+ if self .progress_bar :
357+ self .progress_bar .value = percentage_done / 100
358+ self .percentage_text .value = f"{ percentage_done } %"
359+
360+ def display_progress_ring (
361+ self ,
362+ ):
363+ """Display a progress ring to signal progress."""
364+ if not self .progress_ring :
365+ self .progress_ring = ProgressRing (color = "#00d886" )
366+ self ._container .content .controls .append (self .progress_ring )
367+ self ._container .update ()
368+
369+ def clear (self ):
370+ """Clear output."""
371+ self ._container .content .controls = []
372+ self .progress_ring = None
373+ self .progress_bar = None
374+ self .update ()
375+
376+ def update (self ):
377+ """Update the view."""
378+ self ._container .update ()
0 commit comments