Skip to content

Commit

Permalink
Add a progressbar for flashing (#53)
Browse files Browse the repository at this point in the history
This PR adds a progress bar do show the progress of the flashing.
  • Loading branch information
tsterbak authored Jan 9, 2023
2 parents 53712c1 + d28853a commit 2e471b3
Show file tree
Hide file tree
Showing 5 changed files with 238 additions and 7 deletions.
10 changes: 6 additions & 4 deletions openandroidinstaller/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ def __init__(self, state: AppState, image: str = "placeholder.png"):
self.state = state

# configs
column_width = 600
self.column_width = 600
# right part of the display, add content here.
self.right_view_header = Column(width=column_width, height=100, spacing=30)
self.right_view = Column(alignment="center", width=column_width, height=650)
self.right_view_header = Column(width=self.column_width, height=100, spacing=30)
self.right_view = Column(
alignment="center", width=self.column_width, height=650
)
# left part of the display: used for displaying the images
self.left_view = Column(
width=column_width,
width=self.column_width,
controls=[Image(src=f"/assets/imgs/{image}", height=600)],
expand=True,
horizontal_alignment="center",
Expand Down
91 changes: 89 additions & 2 deletions openandroidinstaller/views/step_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from time import sleep
from typing import Callable
from functools import partial
import regex as re

from flet import (
UserControl,
Expand All @@ -29,6 +30,8 @@
Container,
Switch,
alignment,
ProgressBar,
ProgressRing,
colors,
)

Expand Down Expand Up @@ -99,6 +102,9 @@ def check_advanced_switch(e):
# text box for terminal output
self.terminal_box = TerminalBox(expand=True)

# container for progress indicators
self.progress_indicator = ProgressIndicator(expand=True)

# main controls
steps_indictor_img_lookup = {
"Unlock the bootloader": "steps-header-unlock.png",
Expand Down Expand Up @@ -127,6 +133,7 @@ def check_advanced_switch(e):
self.right_view.controls.extend(
[
Row([self.error_text]),
Row([self.progress_indicator]),
Column(
[
self.advanced_switch,
Expand All @@ -145,6 +152,7 @@ def check_advanced_switch(e):
[
self.inputtext,
Row([self.error_text]),
Row([self.progress_indicator]),
Column(
[
self.advanced_switch,
Expand Down Expand Up @@ -188,6 +196,8 @@ def call_to_phone(self, e, command: str):
"""
# disable the call button while the command is running
self.call_button.disabled = True
# reset the progress indicators
self.progress_indicator.clear()
# reset terminal output
if self.state.advanced:
self.terminal_box.clear()
Expand Down Expand Up @@ -225,7 +235,14 @@ def call_to_phone(self, e, command: str):
# run the right command
if command in cmd_mapping.keys():
for line in cmd_mapping.get(command)(bin_path=self.state.bin_path):
# write the line to advanced output terminal
self.terminal_box.write_line(line)
# in case the install command is run, we want to update the progress bar
if command == "adb_twrp_wipe_and_install":
self.progress_indicator.display_progress_bar(line)
self.progress_indicator.update()
else:
self.progress_indicator.display_progress_ring()
else:
msg = f"Unknown command type: {command}. Stopping."
logger.error(msg)
Expand All @@ -242,9 +259,12 @@ def call_to_phone(self, e, command: str):
else:
sleep(5) # wait to make sure everything is fine
logger.success(f"Command {command} run successfully. Allow to continue.")
# emable the confirm buton and disable the call button
# enable the confirm button and disable the call button
self.confirm_button.disabled = False
self.call_button.disabled = True
# reset the progress indicator (let the progressbar stay for the install command)
if command != "adb_twrp_wipe_and_install":
self.progress_indicator.clear()
self.view.update()


Expand Down Expand Up @@ -277,7 +297,7 @@ def write_line(self, line: str):
self.update()

def toggle_visibility(self):
"""Toogle the visibility of the terminal box."""
"""Toggle the visibility of the terminal box."""
self._box.visible = not self._box.visible
self.update()

Expand All @@ -289,3 +309,70 @@ def clear(self):
def update(self):
"""Update the view."""
self._box.update()


class ProgressIndicator(UserControl):
def __init__(self, expand: bool = True):
super().__init__(expand=expand)
# placeholder for the flashing progressbar
self.progress_bar = None
# progress ring to display
self.progress_ring = None

def build(self):
self._container = Container(
content=Column(scroll="auto", expand=True),
margin=10,
alignment=alignment.center,
height=50,
expand=True,
visible=True,
)
return self._container

def display_progress_bar(self, line: str):
"""Display and update the progress bar for the given line."""
percentage_done = None
result = None
# get the progress numbers from the output lines
if (type(line) == str) and line.strip():
result = re.search(r"\(\~(\d{1,3})\%\)|(Total xfer: 1\.00x)", line.strip())
if result:
if result.group(1):
percentage_done = int(result.group(1))
elif result.group(2):
percentage_done = 100

# create the progress bar on first occurrence
if percentage_done == 0:
self.progress_bar = ProgressBar(
width=500, bar_height=32, color="#00d886", bgcolor="#eeeeee"
)
self.percentage_text = Text(f"{percentage_done}%")
self._container.content.controls.append(
Row([self.percentage_text, self.progress_bar])
)
# update the progress bar
if self.progress_bar:
self.progress_bar.value = percentage_done / 100
self.percentage_text.value = f"{percentage_done}%"

def display_progress_ring(
self,
):
"""Display a progress ring to signal progress."""
if not self.progress_ring:
self.progress_ring = ProgressRing(color="#00d886")
self._container.content.controls.append(self.progress_ring)
self._container.update()

def clear(self):
"""Clear output."""
self._container.content.controls = []
self.progress_ring = None
self.progress_bar = None
self.update()

def update(self):
"""Update the view."""
self._container.update()
94 changes: 93 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ schema = "^0.7.5"
py7zr = "^0.20.0"
pytest-cov = "^4.0.0"
pytest-mock = "^3.10.0"
bandit = "^1.7.4"

[tool.poetry.dev-dependencies]

Expand Down
49 changes: 49 additions & 0 deletions tests/test_progress_bar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""Test the ProgressIndicator class."""

# This file is part of OpenAndroidInstaller.
# OpenAndroidInstaller is free software: you can redistribute it and/or modify it under the terms of
# the GNU General Public License as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.

# OpenAndroidInstaller is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

# You should have received a copy of the GNU General Public License along with OpenAndroidInstaller.
# If not, see <https://www.gnu.org/licenses/>."""
# Author: Tobias Sterbak

import pytest
from flet import Container

from openandroidinstaller.views.step_view import ProgressIndicator


def test_init():
"""Test if the field can be initialized properly."""
progress_indicator = ProgressIndicator(expand=True)
build_indicator = progress_indicator.build()

assert isinstance(build_indicator, Container)


def test_update_progress_bar():
"""Test if the progress bar is updated properly based on lines."""
progress_indicator = ProgressIndicator(expand=True)
build_indicator = progress_indicator.build()

# test if other line is fine
progress_indicator.display_progress_bar(
line="Failed to mount '/data' (Device or resource busy)"
)
assert not progress_indicator.progress_bar

# test if percentages are parsed correctly and update is performed
for percentage in range(0, 47):
line = f"serving: '/home/tobias/Repositories/openandroidinstaller/images/google-pixel3a/lineage-19.1-20221004-nightly-sargo-signed.zip' (~{percentage}%)\n"
progress_indicator.display_progress_bar(line)
assert progress_indicator.progress_bar.value == percentage / 100

# test if the finishing print is detected and updated correctly.
progress_indicator.display_progress_bar(line="Total xfer: 1.00x\n")
assert progress_indicator.progress_bar.value == 1.0

0 comments on commit 2e471b3

Please sign in to comment.