Skip to content

Commit 97fd7be

Browse files
committed
Enable selecting addons
1 parent 03e50a7 commit 97fd7be

4 files changed

Lines changed: 206 additions & 2 deletions

File tree

openandroidinstaller/openandroidinstaller.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
RequirementsView,
4848
InstallView,
4949
WelcomeView,
50+
AddonsView,
5051
)
5152
from tooling import run_command
5253

@@ -111,6 +112,11 @@ def __init__(self, state: AppState):
111112
self.state.final_default_views = self.final_default_views
112113
self.state.final_view = self.final_view
113114

115+
# 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+
119+
114120
def build(self):
115121
self.view.controls.append(self.default_views.pop())
116122
return self.view

openandroidinstaller/views/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
from .select_view import SelectFilesView # noqa
66
from .step_view import StepView # noqa
77
from .install_view import InstallView # noqa
8+
from .addon_view import AddonsView # noqa
89
from .success_view import SuccessView # noqa
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
"""Contains the select 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+
import webbrowser
17+
from loguru import logger
18+
from typing import Callable
19+
20+
from flet import (
21+
Column,
22+
Divider,
23+
ElevatedButton,
24+
OutlinedButton,
25+
FilledButton,
26+
Markdown,
27+
Row,
28+
Text,
29+
colors,
30+
icons,
31+
TextButton,
32+
AlertDialog,
33+
FilePicker,
34+
FilePickerResultEvent,
35+
)
36+
from flet.buttons import CountinuosRectangleBorder
37+
38+
from views import BaseView
39+
from app_state import AppState
40+
from widgets import get_title, confirm_button
41+
42+
43+
class AddonsView(BaseView):
44+
def __init__(
45+
self,
46+
state: AppState,
47+
on_confirm: Callable,
48+
):
49+
super().__init__(state=state)
50+
self.on_confirm = on_confirm
51+
52+
def build(self):
53+
# dialog box to explain OS images and recovery
54+
self.dlg_explain_addons = AlertDialog(
55+
modal=True,
56+
title=Text("What is an OS image and recovery and why do I need it?"),
57+
content=Markdown(
58+
"""## OS image or ROM
59+
An operating system (OS) is system software that manages computer hardware,
60+
software resources, and provides common services for computer programs.
61+
Popular, custom operating systems for mobile devices based on Android are
62+
- [LineageOS](https://lineageos.org/)
63+
- [/e/OS](https://e.foundation/e-os/) or
64+
- [LineageOS for microG](https://lineage.microg.org/)
65+
- and many others.
66+
67+
Often, the related OS images are called 'ROM'. 'ROM' stands for *R*ead-*o*nly *m*emory,
68+
which is a type of non-volatile memory used in computers for storing software that is
69+
rarely changed during the life of the system, also known as firmware.
70+
71+
## Recovery Image
72+
A custom recovery is used for installing custom software on your device.
73+
This custom software can include smaller modifications like rooting your device or even
74+
replacing the firmware of the device with a completely custom ROM.
75+
76+
OpenAndroidInstaller works with the [TWRP recovery project](https://twrp.me/about/).""",
77+
on_tap_link=lambda e: self.page.launch_url(e.data),
78+
),
79+
actions=[
80+
TextButton("Close", on_click=self.close_close_explain_addons_dlg),
81+
],
82+
actions_alignment="end",
83+
shape=CountinuosRectangleBorder(radius=0),
84+
)
85+
86+
# initialize file pickers
87+
self.pick_addons_dialog = FilePicker(on_result=self.pick_addons_result)
88+
self.selected_addons = Text("Selected addons: ")
89+
90+
# initialize and manage button state.
91+
self.confirm_button = confirm_button(self.on_confirm)
92+
# self.confirm_button.disabled = True
93+
# self.pick_addons_dialog.on_result = self.enable_button_if_ready
94+
95+
# attach hidden dialogues
96+
self.right_view.controls.append(self.pick_addons_dialog)
97+
98+
# create help/info button to show the help dialog
99+
info_button = OutlinedButton(
100+
"What is this?",
101+
on_click=self.open_explain_addons_dlg,
102+
expand=True,
103+
icon=icons.HELP_OUTLINE_OUTLINED,
104+
icon_color=colors.DEEP_ORANGE_500,
105+
tooltip="Get more details on custom operating system images and recoveries.",
106+
)
107+
108+
# add title
109+
self.right_view_header.controls.append(
110+
get_title(
111+
"You can select additional addons to install. Otherwise you can safely continue",
112+
info_button=info_button,
113+
step_indicator_img="steps-header-select.png",
114+
)
115+
)
116+
117+
# text row to show infos during the process
118+
self.info_field = Row()
119+
# if there is an available download, show the button to the page
120+
self.right_view.controls.append(Divider())
121+
self.right_view.controls.append(
122+
Column(
123+
[
124+
Text("Here you can download the right GApps for your device."),
125+
Row(
126+
[
127+
ElevatedButton(
128+
"Download LineageOS image",
129+
icon=icons.DOWNLOAD_OUTLINED,
130+
on_click=lambda _: webbrowser.open(
131+
"https://wiki.lineageos.org/gapps"
132+
),
133+
expand=True,
134+
),
135+
]
136+
),
137+
Divider(),
138+
]
139+
)
140+
)
141+
# attach the controls for uploading addons
142+
self.right_view.controls.extend(
143+
[
144+
Text("Select addons:", style="titleSmall"),
145+
Markdown(
146+
f"""
147+
The image file should look something like `lineage-19.1-20221101-nightly-{self.state.config.metadata.get('devicecode')}-signed.zip`."""
148+
),
149+
Row(
150+
[
151+
FilledButton(
152+
"Pick the addons you want to install",
153+
icon=icons.UPLOAD_FILE,
154+
on_click=lambda _: self.pick_addons_dialog.pick_files(
155+
allow_multiple=True,
156+
file_type="custom",
157+
allowed_extensions=["zip"],
158+
),
159+
expand=True,
160+
),
161+
]
162+
),
163+
self.selected_addons,
164+
Divider(),
165+
self.info_field,
166+
Row([self.confirm_button]),
167+
]
168+
)
169+
return self.view
170+
171+
def open_explain_addons_dlg(self, e):
172+
"""Open the dialog to explain addons."""
173+
self.page.dialog = self.dlg_explain_addons
174+
self.dlg_explain_addons.open = True
175+
self.page.update()
176+
177+
def close_close_explain_addons_dlg(self, e):
178+
"""Close the dialog to explain addons."""
179+
self.dlg_explain_addons.open = False
180+
self.page.update()
181+
182+
def pick_addons_result(self, e: FilePickerResultEvent):
183+
path = ", ".join(map(lambda f: f.name, e.files)) if e.files else "Cancelled!"
184+
# update the textfield with the name of the file
185+
self.selected_addons.value = (
186+
self.selected_addons.value.split(":")[0] + f": {path}"
187+
)
188+
if e.files:
189+
self.addon_paths = [file.path for file in e.files]
190+
self.state.addon_paths = self.addon_paths
191+
logger.info(f"Selected addons: {self.addon_paths}")
192+
else:
193+
logger.info("No addons selected.")
194+
# check if the addons works with the device and show the filename in different colors accordingly
195+
# update
196+
self.selected_addons.update()

openandroidinstaller/views/install_view.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,12 @@ def check_addons_switch(e):
7474
"""Check the switch to enable the addons installation process."""
7575
if self.install_addons_switch.value:
7676
logger.info("Enable flashing addons.")
77-
# TODO: add the addons step here.
77+
# add the addons step here.
78+
self.state.default_views.append(self.state.addon_view)
7879
self.state.install_addons = True
7980
else:
8081
logger.info("Disable flashing addons.")
81-
# TODO: empty the steps again
82+
self.state.default_views = []
8283
self.state.install_addons = False
8384

8485
self.install_addons_switch = Switch(

0 commit comments

Comments
 (0)