From 95473fcd6edef17e62b61ae52a9aaef4ba2a8729 Mon Sep 17 00:00:00 2001 From: Daniel Schwarz Date: Fri, 3 Feb 2023 21:28:18 -0500 Subject: [PATCH 1/4] Add get_relationship method to api --- toot/api.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/toot/api.py b/toot/api.py index 564746f..a608609 100644 --- a/toot/api.py +++ b/toot/api.py @@ -369,6 +369,11 @@ def vote(app, user, poll_id, choices: List[int]): return http.post(app, user, url, json=json).json() +def get_relationship(app, user, account): + params = {"id[]": account} + return http.get(app, user, '/api/v1/accounts/relationships', params).json()[0] + + def mute(app, user, account): return _account_action(app, user, account, 'mute') From a1490461bdad97d6ae63f116ac0e9b0e4b8785d4 Mon Sep 17 00:00:00 2001 From: Daniel Schwarz Date: Fri, 3 Feb 2023 21:28:18 -0500 Subject: [PATCH 2/4] Add relationship support to Account overlay Display relationship details such as followed_by, blocked_by, and add buttons to un/follow, un/mute, un/block. Buttons are nonfunctional for now --- toot/debugger.py | 12 ++++++++++++ toot/tui/app.py | 3 ++- toot/tui/overlays.py | 20 +++++++++++++++++--- 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 toot/debugger.py diff --git a/toot/debugger.py b/toot/debugger.py new file mode 100644 index 0000000..ba4aee9 --- /dev/null +++ b/toot/debugger.py @@ -0,0 +1,12 @@ +from os import getenv + +def initialize_debugger(): + import multiprocessing + + if multiprocessing.current_process().pid > 1: + import debugpy + + debugpy.listen(("0.0.0.0", 9000)) + print("VSCode Debugger is ready to be attached on port 9000, press F5", flush=True) + debugpy.wait_for_client() + print("VSCode Debugger is now attached", flush=True) diff --git a/toot/tui/app.py b/toot/tui/app.py index 64c50c7..12b0473 100644 --- a/toot/tui/app.py +++ b/toot/tui/app.py @@ -521,8 +521,9 @@ class TUI(urwid.Frame): def show_account(self, account_id): account = api.whois(self.app, self.user, account_id) + relationship = api.get_relationship(self.app, self.user, account_id) self.open_overlay( - widget=Account(account), + widget=Account(account, relationship), title="Account", ) diff --git a/toot/tui/overlays.py b/toot/tui/overlays.py index de9dbe6..b91d30f 100644 --- a/toot/tui/overlays.py +++ b/toot/tui/overlays.py @@ -205,12 +205,20 @@ class Help(urwid.Padding): class Account(urwid.ListBox): """Shows account data and provides various actions""" - def __init__(self, account): - actions = list(self.generate_contents(account)) + def __init__(self, account, relationship): + actions = list(self.generate_contents(account, relationship)) walker = urwid.SimpleListWalker(actions) super().__init__(walker) - def generate_contents(self, account): + def generate_contents(self, account, relationship): + if relationship['requested']: + yield urwid.Text(("light grey", "< Follow request is pending >")) + else: + yield Button("Unfollow" if relationship['following'] else "Follow") + yield Button("Unmute" if relationship['muting'] else "Mute") + yield Button("Unblock" if relationship['blocking'] else "Block") + yield urwid.Divider("─") + yield urwid.Divider() yield urwid.Text([('green', f"@{account['acct']}"), f" {account['display_name']}"]) if account["note"]: @@ -232,6 +240,12 @@ class Account(urwid.ListBox): if "suspended" in account and account["suspended"]: yield urwid.Text([("warning", "Suspended \N{cross mark}")]) yield urwid.Divider() + if relationship["followed_by"]: + yield urwid.Text(("green", "Follows you \N{busts in silhouette}")) + yield urwid.Divider() + if relationship["blocked_by"]: + yield urwid.Text(("warning", "Blocks you \N{no entry}")) + yield urwid.Divider() yield urwid.Text(["Followers: ", ("yellow", f"{account['followers_count']}")]) yield urwid.Text(["Following: ", ("yellow", f"{account['following_count']}")]) From 876ad1f53dfae366129ab143eafcfdfc2d4d46d1 Mon Sep 17 00:00:00 2001 From: Daniel Schwarz Date: Fri, 3 Feb 2023 21:28:18 -0500 Subject: [PATCH 3/4] Added framework for action buttons with "Confirm/Cancel" behavior Buttons with confirm/cancel behavior are in place and working TBD: implement actions when user gives confirmation. --- toot/debugger.py | 12 --------- toot/tui/overlays.py | 59 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 52 insertions(+), 19 deletions(-) delete mode 100644 toot/debugger.py diff --git a/toot/debugger.py b/toot/debugger.py deleted file mode 100644 index ba4aee9..0000000 --- a/toot/debugger.py +++ /dev/null @@ -1,12 +0,0 @@ -from os import getenv - -def initialize_debugger(): - import multiprocessing - - if multiprocessing.current_process().pid > 1: - import debugpy - - debugpy.listen(("0.0.0.0", 9000)) - print("VSCode Debugger is ready to be attached on port 9000, press F5", flush=True) - debugpy.wait_for_client() - print("VSCode Debugger is now attached", flush=True) diff --git a/toot/tui/overlays.py b/toot/tui/overlays.py index b91d30f..606cc5e 100644 --- a/toot/tui/overlays.py +++ b/toot/tui/overlays.py @@ -206,17 +206,32 @@ class Help(urwid.Padding): class Account(urwid.ListBox): """Shows account data and provides various actions""" def __init__(self, account, relationship): - actions = list(self.generate_contents(account, relationship)) + self.last_action = None + self.account = account + self.relationship = relationship + self.setup_listbox() + + def setup_listbox(self): + actions = list(self.generate_contents(self.account, self.relationship, self.last_action)) walker = urwid.SimpleListWalker(actions) super().__init__(walker) - def generate_contents(self, account, relationship): - if relationship['requested']: - yield urwid.Text(("light grey", "< Follow request is pending >")) + def generate_contents(self, account, relationship=None, last_action=None): + if self.last_action and not self.last_action.startswith("Confirm"): + yield Button(f"Confirm {self.last_action}", on_press=take_action, user_data=self) + yield Button("Cancel", on_press=cancel_action, user_data=self) else: - yield Button("Unfollow" if relationship['following'] else "Follow") - yield Button("Unmute" if relationship['muting'] else "Mute") - yield Button("Unblock" if relationship['blocking'] else "Block") + if relationship['requested']: + yield urwid.Text(("light grey", "< Follow request is pending >")) + else: + yield Button("Unfollow" if relationship['following'] else "Follow", + on_press=confirm_action, user_data=self) + + yield Button("Unmute" if relationship['muting'] else "Mute", + on_press=confirm_action, user_data=self) + yield Button("Unblock" if relationship['blocking'] else "Block", + on_press=confirm_action, user_data=self) + yield urwid.Divider("─") yield urwid.Divider() yield urwid.Text([('green', f"@{account['acct']}"), f" {account['display_name']}"]) @@ -265,6 +280,36 @@ class Account(urwid.ListBox): yield link("", account["url"]) +def take_action(button: Button, self: Account): + action = button.get_label() + + if action == "Confirm Follow": + pass + elif action == "Confirm Unfollow": + pass + elif action == "Confirm Mute": + pass + elif action == "Confirm Unmute": + pass + elif action == "Confirm Block": + pass + elif action == "Confirm Unblock": + pass + + self.last_action = None + self.setup_listbox() + + +def confirm_action(button: Button, self: Account): + self.last_action = button.get_label() + self.setup_listbox() + + +def cancel_action(button: Button, self: Account): + self.last_action = None + self.setup_listbox() + + def link(text, url): attr_map = {"link": "link_focused"} text = SelectableText([text, ("link", url)]) From 85df15f53333b18a9b5415b3d00e8e4af401b8d1 Mon Sep 17 00:00:00 2001 From: Daniel Schwarz Date: Fri, 3 Feb 2023 21:28:18 -0500 Subject: [PATCH 4/4] Implement actions for Account Actions: un/follow, un/mute, un/block are invoked synchronously and the Account overlay window is updated to reflect the changes. --- toot/tui/app.py | 2 +- toot/tui/overlays.py | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/toot/tui/app.py b/toot/tui/app.py index 12b0473..1b8fbf1 100644 --- a/toot/tui/app.py +++ b/toot/tui/app.py @@ -523,7 +523,7 @@ class TUI(urwid.Frame): account = api.whois(self.app, self.user, account_id) relationship = api.get_relationship(self.app, self.user, account_id) self.open_overlay( - widget=Account(account, relationship), + widget=Account(self.app, self.user, account, relationship), title="Account", ) diff --git a/toot/tui/overlays.py b/toot/tui/overlays.py index 606cc5e..e6c1777 100644 --- a/toot/tui/overlays.py +++ b/toot/tui/overlays.py @@ -7,6 +7,7 @@ from toot import __version__ from toot.utils import format_content from .utils import highlight_hashtags, highlight_keys from .widgets import Button, EditBox, SelectableText +from toot import api class StatusSource(urwid.Padding): @@ -205,10 +206,12 @@ class Help(urwid.Padding): class Account(urwid.ListBox): """Shows account data and provides various actions""" - def __init__(self, account, relationship): - self.last_action = None + def __init__(self, app, user, account, relationship): + self.app = app + self.user = user self.account = account self.relationship = relationship + self.last_action = None self.setup_listbox() def setup_listbox(self): @@ -284,17 +287,17 @@ def take_action(button: Button, self: Account): action = button.get_label() if action == "Confirm Follow": - pass + self.relationship = api.follow(self.app, self.user, self.account["id"]) elif action == "Confirm Unfollow": - pass + self.relationship = api.unfollow(self.app, self.user, self.account["id"]) elif action == "Confirm Mute": - pass + self.relationship = api.mute(self.app, self.user, self.account["id"]) elif action == "Confirm Unmute": - pass + self.relationship = api.unmute(self.app, self.user, self.account["id"]) elif action == "Confirm Block": - pass + self.relationship = api.block(self.app, self.user, self.account["id"]) elif action == "Confirm Unblock": - pass + self.relationship = api.unblock(self.app, self.user, self.account["id"]) self.last_action = None self.setup_listbox()