From ccf8ce1e84743787590e87925268c436231551a5 Mon Sep 17 00:00:00 2001 From: Jean Do Date: Wed, 25 Jan 2023 12:08:22 -0400 Subject: [PATCH 1/7] conditional power-off: 'Powering Off' or 'Just Unplug It' --- src/seedsigner/gui/screens/screen.py | 17 ++++++++++++++++- src/seedsigner/views/view.py | 20 +++++++++----------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/seedsigner/gui/screens/screen.py b/src/seedsigner/gui/screens/screen.py index 3da014a0..c0e01f3b 100644 --- a/src/seedsigner/gui/screens/screen.py +++ b/src/seedsigner/gui/screens/screen.py @@ -906,6 +906,21 @@ class PowerOffScreen(BaseTopNavScreen): +@dataclass +class PowerOffNotRequiredScreen(BaseTopNavScreen): + def __post_init__(self): + self.title = "Just Unplug It" + self.show_back_button = True + super().__post_init__() + + self.components.append(TextArea( + text="In SeedSigner-OS, it is safe to disconnect power at any time.", + screen_y=self.top_nav.height, + height=self.canvas_height - self.top_nav.height, + )) + + + @dataclass class KeyboardScreen(BaseTopNavScreen): """ @@ -1149,4 +1164,4 @@ class MicroSDToastScreen(BaseScreen): label_text="MicroSD inserted" ) - self.toast.render() \ No newline at end of file + self.toast.render() diff --git a/src/seedsigner/views/view.py b/src/seedsigner/views/view.py index 50b1c40a..02543c4d 100644 --- a/src/seedsigner/views/view.py +++ b/src/seedsigner/views/view.py @@ -3,7 +3,7 @@ from typing import List from seedsigner.gui.components import FontAwesomeIconConstants, GUIConstants from seedsigner.gui.screens import RET_CODE__POWER_BUTTON -from seedsigner.gui.screens.screen import RET_CODE__BACK_BUTTON, DireWarningScreen, LargeButtonScreen, PowerOffScreen, ResetScreen, WarningScreen +from seedsigner.gui.screens.screen import RET_CODE__BACK_BUTTON, DireWarningScreen, LargeButtonScreen, PowerOffScreen, PowerOffNotRequiredScreen, ResetScreen, WarningScreen from seedsigner.models.threads import BaseThread from seedsigner.models import Settings @@ -199,9 +199,13 @@ class RestartView(View): class PowerOffView(View): def run(self): - thread = PowerOffView.PowerOffThread() - thread.start() - PowerOffScreen().display() + if Settings.HOSTNAME == Settings.SEEDSIGNER_OS: + PowerOffNotRequiredScreen().display() + return Destination(BackStackView) + else: + thread = PowerOffView.PowerOffThread() + thread.start() + PowerOffScreen().display() class PowerOffThread(BaseThread): @@ -210,13 +214,7 @@ class PowerOffView(View): from subprocess import call while self.keep_running: time.sleep(5) - if Settings.HOSTNAME == Settings.SEEDSIGNER_OS: - # disable microsd detection before shutdown to prevent display of toast notification during shutdown - from seedsigner.controller import Controller - Controller.get_instance().microsd.stop() - call("poweroff", shell=True) - else: - call("sudo shutdown --poweroff now", shell=True) + call("sudo shutdown --poweroff now", shell=True) From 98679505a3611f4443616b5c26b55d7ca0fc60ec Mon Sep 17 00:00:00 2001 From: Jean Do Date: Thu, 26 Jan 2023 17:43:32 -0400 Subject: [PATCH 2/7] No mention of OS since it's the new standard. --- src/seedsigner/gui/screens/screen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/seedsigner/gui/screens/screen.py b/src/seedsigner/gui/screens/screen.py index c0e01f3b..e32bf984 100644 --- a/src/seedsigner/gui/screens/screen.py +++ b/src/seedsigner/gui/screens/screen.py @@ -914,7 +914,7 @@ class PowerOffNotRequiredScreen(BaseTopNavScreen): super().__post_init__() self.components.append(TextArea( - text="In SeedSigner-OS, it is safe to disconnect power at any time.", + text="It is safe to disconnect power at any time.", screen_y=self.top_nav.height, height=self.canvas_height - self.top_nav.height, )) From 0a377a8db8d0a33f0b354c2ba173b88728172de8 Mon Sep 17 00:00:00 2001 From: Jean Do Date: Fri, 27 Jan 2023 10:30:46 -0400 Subject: [PATCH 3/7] Denomination: Btc-only/Sats-only become BTC/sats --- src/seedsigner/models/settings_definition.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/seedsigner/models/settings_definition.py b/src/seedsigner/models/settings_definition.py index 273c78b9..e69478f3 100644 --- a/src/seedsigner/models/settings_definition.py +++ b/src/seedsigner/models/settings_definition.py @@ -53,10 +53,10 @@ class SettingsConstants: BTC_DENOMINATION__THRESHOLD = "thr" BTC_DENOMINATION__BTCSATSHYBRID = "hyb" ALL_BTC_DENOMINATIONS = [ - (BTC_DENOMINATION__BTC, "Btc-only"), - (BTC_DENOMINATION__SATS, "Sats-only"), + (BTC_DENOMINATION__BTC, "BTC"), + (BTC_DENOMINATION__SATS, "sats"), (BTC_DENOMINATION__THRESHOLD, "Threshold at 0.01"), - (BTC_DENOMINATION__BTCSATSHYBRID, "Btc | Sats hybrid"), + (BTC_DENOMINATION__BTCSATSHYBRID, "BTC | sats hybrid"), ] CAMERA_ROTATION__0 = 0 From 7481b45b9f03e2b872db8a487cdb1e3b96082036 Mon Sep 17 00:00:00 2001 From: kdmukai Date: Sat, 28 Jan 2023 07:52:13 -0600 Subject: [PATCH 4/7] Preserve list state in Advanced settings --- src/seedsigner/gui/screens/screen.py | 10 +++++----- src/seedsigner/views/settings_views.py | 25 +++++++++++++++++-------- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/seedsigner/gui/screens/screen.py b/src/seedsigner/gui/screens/screen.py index e32bf984..50a94e70 100644 --- a/src/seedsigner/gui/screens/screen.py +++ b/src/seedsigner/gui/screens/screen.py @@ -265,6 +265,9 @@ class ButtonListScreen(BaseTopNavScreen): Button_cls = Button checked_buttons: List[int] = None + # Enables returning w/buttons rendered at the same place + scroll_y_initial_offset: int = None + def __post_init__(self): super().__post_init__() @@ -315,6 +318,7 @@ class ButtonListScreen(BaseTopNavScreen): right_icon_name=right_icon_name, screen_x=GUIConstants.EDGE_PADDING, screen_y=button_list_y + i * (button_height + GUIConstants.LIST_ITEM_PADDING), + scroll_y=self.scroll_y_initial_offset if self.scroll_y_initial_offset is not None else 0, width=self.canvas_width - (2 * GUIConstants.EDGE_PADDING), height=button_height, is_text_centered=self.is_button_text_centered, @@ -330,7 +334,7 @@ class ButtonListScreen(BaseTopNavScreen): if self.has_scroll_arrows: self.arrow_half_width = 10 - self.cur_scroll_y = 0 + self.cur_scroll_y = self.scroll_y_initial_offset if self.scroll_y_initial_offset is not None else 0 self.up_arrow_img = Image.new("RGBA", size=(2 * self.arrow_half_width, 8), color="black") self.up_arrow_img_y = self.top_nav.height - 12 arrow_draw = ImageDraw.Draw(self.up_arrow_img) @@ -346,10 +350,6 @@ class ButtonListScreen(BaseTopNavScreen): cur_selected_button = self.buttons[self.selected_button] cur_selected_button.is_selected = True - if self.has_scroll_arrows: - frame_scroll = self.buttons[0].screen_y - cur_selected_button.screen_y - for button in self.buttons: - button.scroll_y -= frame_scroll def _render(self): diff --git a/src/seedsigner/views/settings_views.py b/src/seedsigner/views/settings_views.py index 655b61d1..7d5ef6c0 100644 --- a/src/seedsigner/views/settings_views.py +++ b/src/seedsigner/views/settings_views.py @@ -9,11 +9,14 @@ from seedsigner.models.settings import SettingsConstants, SettingsDefinition class SettingsMenuView(View): - def __init__(self, visibility: str = SettingsConstants.VISIBILITY__GENERAL, selected_attr: str = None): + def __init__(self, visibility: str = SettingsConstants.VISIBILITY__GENERAL, selected_attr: str = None, initial_scroll: int = 0): super().__init__() self.visibility = visibility self.selected_attr = selected_attr + # Used to preserve the rendering position in the list + self.initial_scroll = initial_scroll + def run(self): IO_TEST = "I/O test" @@ -53,12 +56,17 @@ class SettingsMenuView(View): title = "Dev Options" next = None - selected_menu_num = ButtonListScreen( + screen = ButtonListScreen( title=title, is_button_text_centered=False, button_data=button_data, selected_button=selected_button, - ).display() + scroll_y_initial_offset=self.initial_scroll, + ) + selected_menu_num = screen.display() + + # Preserve our scroll position in this Screen so we can return + initial_scroll = screen.buttons[0].scroll_y if selected_menu_num == RET_CODE__BACK_BUTTON: if self.visibility == SettingsConstants.VISIBILITY__GENERAL: @@ -78,8 +86,7 @@ class SettingsMenuView(View): return Destination(DonateView) else: - # TODO: Free-entry types (are there any?) will need their own SettingsEntryUpdateFreeEntryView(?). - return Destination(SettingsEntryUpdateSelectionView, view_args={"attr_name": settings_entries[selected_menu_num].attr_name}) + return Destination(SettingsEntryUpdateSelectionView, view_args=dict(attr_name=settings_entries[selected_menu_num].attr_name, parent_initial_scroll=initial_scroll)) @@ -88,10 +95,11 @@ class SettingsEntryUpdateSelectionView(View): Handles changes to all selection-type settings (Multiselect, SELECT_1, Enabled/Disabled, etc). """ - def __init__(self, attr_name: str): + def __init__(self, attr_name: str, parent_initial_scroll: int = 0): super().__init__() self.settings_entry = SettingsDefinition.get_settings_entry(attr_name) self.selected_button = None + self.parent_initial_scroll = parent_initial_scroll def run(self): @@ -129,7 +137,8 @@ class SettingsEntryUpdateSelectionView(View): SettingsMenuView, view_args={ "visibility": self.settings_entry.visibility, - "selected_attr": self.settings_entry.attr_name + "selected_attr": self.settings_entry.attr_name, + "initial_scroll": self.parent_initial_scroll, } ) @@ -188,4 +197,4 @@ class DonateView(View): def run(self): settings_screens.DonateScreen().display() - return Destination(SettingsMenuView) + return Destination(SettingsMenuView) \ No newline at end of file From 6c3b4016601697b83076ec3b8cea4cbcabe963f9 Mon Sep 17 00:00:00 2001 From: kdmukai Date: Sat, 28 Jan 2023 08:01:41 -0600 Subject: [PATCH 5/7] Update settings_views.py --- src/seedsigner/views/settings_views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/seedsigner/views/settings_views.py b/src/seedsigner/views/settings_views.py index 7d5ef6c0..8a13b43d 100644 --- a/src/seedsigner/views/settings_views.py +++ b/src/seedsigner/views/settings_views.py @@ -197,4 +197,4 @@ class DonateView(View): def run(self): settings_screens.DonateScreen().display() - return Destination(SettingsMenuView) \ No newline at end of file + return Destination(SettingsMenuView) From 357cd14e82c8261e0dbe97efded7b6126797bf33 Mon Sep 17 00:00:00 2001 From: kdmukai Date: Sat, 28 Jan 2023 08:25:09 -0600 Subject: [PATCH 6/7] Updates AddressExplorer to keep scroll position --- src/seedsigner/views/tools_views.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/seedsigner/views/tools_views.py b/src/seedsigner/views/tools_views.py index 14a775d5..2c5fa017 100644 --- a/src/seedsigner/views/tools_views.py +++ b/src/seedsigner/views/tools_views.py @@ -559,11 +559,12 @@ class ToolsAddressExplorerAddressTypeView(View): class ToolsAddressExplorerAddressListView(View): - def __init__(self, is_change: bool = False, start_index: int = 0, selected_button_index: int = 0): + def __init__(self, is_change: bool = False, start_index: int = 0, selected_button_index: int = 0, initial_scroll: int = 0): super().__init__() self.is_change = is_change self.start_index = start_index self.selected_button_index = selected_button_index + self.initial_scroll = initial_scroll def run(self): @@ -632,6 +633,7 @@ class ToolsAddressExplorerAddressListView(View): is_button_text_centered=False, is_bottom_list=True, selected_button=self.selected_button_index, + scroll_y_initial_offset=self.initial_scroll, ) finally: # Everything is set. Stop the loading screen @@ -647,20 +649,23 @@ class ToolsAddressExplorerAddressListView(View): # User clicked NEXT return Destination(ToolsAddressExplorerAddressListView, view_args=dict(is_change=self.is_change, start_index=self.start_index + addrs_per_screen)) + # Preserve the list's current scroll so we can return to the same spot + initial_scroll = screen.buttons[0].scroll_y + index = selected_menu_num + self.start_index - return Destination(ToolsAddressExplorerAddressView, view_args=dict(index=index, address=addresses[selected_menu_num], is_change=self.is_change, start_index=self.start_index), skip_current_view=True) + return Destination(ToolsAddressExplorerAddressView, view_args=dict(index=index, address=addresses[selected_menu_num], is_change=self.is_change, start_index=self.start_index, parent_initial_scroll=initial_scroll), skip_current_view=True) class ToolsAddressExplorerAddressView(View): - def __init__(self, index: int, address: str, is_change: bool, start_index: int): + def __init__(self, index: int, address: str, is_change: bool, start_index: int, parent_initial_scroll: int = 0): super().__init__() self.index = index self.address = address self.is_change = is_change self.start_index = start_index + self.parent_initial_scroll = parent_initial_scroll - data = self.controller.address_explorer_data def run(self): qr_encoder = EncodeQR(qr_type=QRType.BITCOIN_ADDRESS, bitcoin_address=self.address) @@ -669,4 +674,4 @@ class ToolsAddressExplorerAddressView(View): ).display() # Exiting/Cancelling the QR display screen always returns to the list - return Destination(ToolsAddressExplorerAddressListView, view_args=dict(is_change=self.is_change, start_index=self.start_index, selected_button_index=self.index - self.start_index), skip_current_view=True) + return Destination(ToolsAddressExplorerAddressListView, view_args=dict(is_change=self.is_change, start_index=self.start_index, selected_button_index=self.index - self.start_index, initial_scroll=self.parent_initial_scroll), skip_current_view=True) From 8776e928a2e58c0db328e4ccf6c987c872d55afb Mon Sep 17 00:00:00 2001 From: Nick Klockenga Date: Tue, 7 Feb 2023 14:04:46 -0500 Subject: [PATCH 7/7] bump version to 0.6.0 --- setup.py | 2 +- src/seedsigner/controller.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 9aa1e28b..82dcfb5d 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh: setuptools.setup( name="seedsigner", - version="0.5.2", + version="0.6.0", author="SeedSigner", author_email="author@example.com", description="Build an offline, airgapped Bitcoin signing device for less than $50!", diff --git a/src/seedsigner/controller.py b/src/seedsigner/controller.py index 4aa0b41c..4976d6f7 100644 --- a/src/seedsigner/controller.py +++ b/src/seedsigner/controller.py @@ -50,7 +50,7 @@ class Controller(Singleton): rather than at the top in order avoid circular imports. """ - VERSION = "0.5.2" + VERSION = "0.6.0" # Declare class member vars with type hints to enable richer IDE support throughout # the code.