Skip to content

Commit 2225d84

Browse files
committed
MVP for installing addons
1 parent 97fd7be commit 2225d84

5 files changed

Lines changed: 246 additions & 5 deletions

File tree

openandroidinstaller/openandroidinstaller.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@
4848
InstallView,
4949
WelcomeView,
5050
AddonsView,
51+
InstallAddonsView,
5152
)
5253
from tooling import run_command
54+
from installer_config import Step
5355

5456
# where to write the logs
5557
logger.add("openandroidinstaller.log")
@@ -113,9 +115,26 @@ def __init__(self, state: AppState):
113115
self.state.final_view = self.final_view
114116

115117
# initialize the addon view
116-
self.addon_view = AddonsView(on_confirm=self.confirm, state=self.state)
117-
self.state.addon_view = self.addon_view
118-
118+
self.select_addon_view = AddonsView(on_confirm=self.confirm, state=self.state)
119+
self.flash_recovery_view = StepView(
120+
step=Step(
121+
title="Flash custom recovery",
122+
type="call_button",
123+
content="Flash a custom recovery (temporarily) by pressing 'Confirm and run'. Once your phone screen looks like the picture on the left, continue.",
124+
command="fastboot_flash_recovery",
125+
img="twrp-start.jpeg",
126+
),
127+
state=self.state,
128+
on_confirm=self.confirm,
129+
)
130+
self.install_addons_view = InstallAddonsView(
131+
on_confirm=self.confirm, state=self.state
132+
)
133+
self.state.addon_views = [
134+
self.install_addons_view,
135+
self.flash_recovery_view,
136+
self.select_addon_view,
137+
]
119138

120139
def build(self):
121140
self.view.controls.append(self.default_views.pop())

openandroidinstaller/tooling.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,9 @@ def adb_twrp_copy_partitions(bin_path: Path, config_path: Path):
150150
return True
151151

152152

153-
def adb_twrp_wipe_and_install(bin_path: Path, target: str, config_path: Path, install_addons=True) -> bool:
153+
def adb_twrp_wipe_and_install(
154+
bin_path: Path, target: str, config_path: Path, install_addons=True
155+
) -> bool:
154156
"""Wipe and format data with twrp, then flash os image with adb.
155157
156158
Only works for twrp recovery.
@@ -237,6 +239,45 @@ def adb_twrp_wipe_and_install(bin_path: Path, target: str, config_path: Path, in
237239
yield True
238240

239241

242+
def adb_twrp_install_addons(bin_path: Path, addons: List[str]) -> bool:
243+
"""Flash addons through adb and twrp.
244+
245+
Only works for twrp recovery.
246+
"""
247+
logger.info("Install addons with twrp.")
248+
sleep(7)
249+
# activate sideload
250+
logger.info("Activate sideload.")
251+
for line in run_command("adb", ["shell", "twrp", "sideload"], bin_path):
252+
yield line
253+
if (type(line) == bool) and not line:
254+
logger.error("Activating sideload failed.")
255+
yield False
256+
return
257+
# now flash os image
258+
sleep(5)
259+
logger.info("Sideload and install addons.")
260+
for addon in addons:
261+
for line in run_command("adb", ["sideload", f"{addon}"], bin_path):
262+
yield line
263+
if (type(line) == bool) and not line:
264+
logger.error(f"Sideloading {addon} failed.")
265+
# TODO: this might sometimes think it failed, but actually it's fine. So skip for now.
266+
# yield False
267+
# return
268+
# finally reboot into os
269+
sleep(7)
270+
logger.info("Reboot into OS.")
271+
for line in run_command("adb", ["reboot"], bin_path): # "shell", "twrp",
272+
yield line
273+
if (type(line) == bool) and not line:
274+
logger.error("Rebooting failed.")
275+
yield False
276+
return
277+
else:
278+
yield True
279+
280+
240281
def fastboot_unlock_with_code(bin_path: Path, unlock_code: str) -> bool:
241282
"""Unlock the device with fastboot and code given."""
242283
logger.info(f"Unlock the device with fastboot and code: {unlock_code}.")

openandroidinstaller/views/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66
from .step_view import StepView # noqa
77
from .install_view import InstallView # noqa
88
from .addon_view import AddonsView # noqa
9+
from .install_addons_view import InstallAddonsView # noqa
910
from .success_view import SuccessView # noqa
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
"""Contains the install addons view."""
2+
3+
# This file is part of OpenAndroidInstaller.
4+
# OpenAndroidInstaller is free software: you can redistribute it and/or modify it under the terms of
5+
# the GNU General Public License as published by the Free Software Foundation,
6+
# either version 3 of the License, or (at your option) any later version.
7+
8+
# OpenAndroidInstaller is distributed in the hope that it will be useful, but WITHOUT ANY
9+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
11+
12+
# You should have received a copy of the GNU General Public License along with OpenAndroidInstaller.
13+
# If not, see <https://www.gnu.org/licenses/>."""
14+
# Author: Tobias Sterbak
15+
16+
from loguru import logger
17+
from time import sleep
18+
from typing import Callable
19+
20+
from flet import (
21+
Column,
22+
ElevatedButton,
23+
Row,
24+
Text,
25+
icons,
26+
Switch,
27+
colors,
28+
Markdown,
29+
)
30+
31+
from views import BaseView
32+
from app_state import AppState
33+
from tooling import adb_twrp_install_addons
34+
from widgets import (
35+
confirm_button,
36+
get_title,
37+
)
38+
from views.step_view import TerminalBox, ProgressIndicator
39+
40+
41+
class InstallAddonsView(BaseView):
42+
def __init__(
43+
self,
44+
state: AppState,
45+
on_confirm: Callable,
46+
):
47+
super().__init__(state=state)
48+
self.on_confirm = on_confirm
49+
50+
def build(self):
51+
"""Create the content of the view."""
52+
# error text
53+
self.error_text = Text("", color=colors.RED)
54+
55+
# switch to enable advanced output - here it means show terminal input/output in tool
56+
def check_advanced_switch(e):
57+
"""Check the box to enable advanced output."""
58+
if self.advanced_switch.value:
59+
logger.info("Enable advanced output.")
60+
self.state.advanced = True
61+
self.terminal_box.toggle_visibility()
62+
else:
63+
logger.info("Disable advanced output.")
64+
self.state.advanced = False
65+
self.terminal_box.toggle_visibility()
66+
67+
self.advanced_switch = Switch(
68+
label="Advanced output",
69+
on_change=check_advanced_switch,
70+
disabled=False,
71+
)
72+
73+
# text box for terminal output
74+
self.terminal_box = TerminalBox(expand=True)
75+
76+
# container for progress indicators
77+
self.progress_indicator = ProgressIndicator(expand=True)
78+
79+
# main controls
80+
self.right_view_header.controls = [
81+
get_title(
82+
"Install Addons",
83+
step_indicator_img="steps-header-install.png",
84+
)
85+
]
86+
self.right_view.controls = [
87+
Markdown(
88+
"""In the next steps, you finally flash the selected Addons.
89+
90+
Confirm to install.
91+
92+
This might take a while. At the end your phone will boot into the new OS.
93+
"""
94+
)
95+
]
96+
# basic view
97+
logger.info("Starting addon installation.")
98+
self.confirm_button = confirm_button(self.on_confirm)
99+
self.confirm_button.disabled = True
100+
# button to run the installation process
101+
self.install_button = ElevatedButton(
102+
"Confirm and install addons",
103+
on_click=self.run_install_addons,
104+
expand=True,
105+
icon=icons.DIRECTIONS_RUN_OUTLINED,
106+
)
107+
# build the view
108+
self.right_view.controls.extend(
109+
[
110+
Row([self.error_text]),
111+
Row([self.progress_indicator]),
112+
Column(
113+
[
114+
self.advanced_switch,
115+
Row([self.install_button, self.confirm_button]),
116+
]
117+
),
118+
Row([self.terminal_box]),
119+
]
120+
)
121+
122+
# if skipping is allowed add a button to the view
123+
if self.state.test:
124+
self.right_view.controls.append(
125+
Row(
126+
[
127+
Text("Do you want to skip?"),
128+
ElevatedButton(
129+
"Skip",
130+
on_click=self.on_confirm,
131+
icon=icons.NEXT_PLAN_OUTLINED,
132+
expand=True,
133+
),
134+
]
135+
)
136+
)
137+
return self.view
138+
139+
def run_install_addons(self, e):
140+
"""
141+
Run the addon installation process trough twrp.
142+
143+
Some parts of the command are changed by placeholders.
144+
"""
145+
# disable the call button while the command is running
146+
self.install_button.disabled = True
147+
self.install_addons_switch.disabled = True
148+
# reset the progress indicators
149+
self.progress_indicator.clear()
150+
# reset terminal output
151+
if self.state.advanced:
152+
self.terminal_box.clear()
153+
self.right_view.update()
154+
155+
# run the install script
156+
for line in adb_twrp_install_addons(
157+
addons=self.state.addon_paths,
158+
bin_path=self.state.bin_path,
159+
):
160+
# write the line to advanced output terminal
161+
self.terminal_box.write_line(line)
162+
# in case the install command is run, we want to update progress ring for now
163+
self.progress_indicator.display_progress_ring()
164+
success = line # the last element of the iterable is a boolean encoding success/failure
165+
166+
# update the view accordingly
167+
if not success:
168+
# enable call button to retry
169+
self.install_button.disabled = False
170+
# also remove the last error text if it happened
171+
self.error_text.value = "Installation failed! Try again or make sure everything is setup correctly."
172+
else:
173+
sleep(5) # wait to make sure everything is fine
174+
logger.success("Installation process was successful. Allow to continue.")
175+
# enable the confirm button and disable the call button
176+
self.confirm_button.disabled = False
177+
self.install_button.disabled = True
178+
# reset the progress indicator
179+
self.progress_indicator.clear()
180+
self.view.update()

openandroidinstaller/views/install_view.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def check_addons_switch(e):
7575
if self.install_addons_switch.value:
7676
logger.info("Enable flashing addons.")
7777
# add the addons step here.
78-
self.state.default_views.append(self.state.addon_view)
78+
self.state.default_views.extend(self.state.addon_views)
7979
self.state.install_addons = True
8080
else:
8181
logger.info("Disable flashing addons.")

0 commit comments

Comments
 (0)