From b8d43ecfec6cbbc68619cfed507db395c89a7c2c Mon Sep 17 00:00:00 2001 From: miruka Date: Wed, 21 Aug 2019 17:45:05 -0400 Subject: [PATCH] Add account logout feature via context menu --- TODO.md | 8 ++++-- src/icons/light-thin/logout.svg | 1 + src/python/backend.py | 8 ++---- src/python/matrix_client.py | 8 ++++-- src/qml/Chat/Chat.qml | 2 +- src/qml/Pages/EditAccount/EditAccount.qml | 1 + src/qml/SidePane/DelegateAccount.qml | 34 +++++++++++++++++++++-- 7 files changed, 47 insertions(+), 15 deletions(-) create mode 100644 src/icons/light-thin/logout.svg diff --git a/TODO.md b/TODO.md index 84e7aff4..d19ff7d8 100644 --- a/TODO.md +++ b/TODO.md @@ -18,7 +18,10 @@ - When qml syntax highlighting supports ES6 string interpolation, use them - Fixes - - Restore previous focus after right click + - Button loading icon with only text + - Highlight when adding new account + + - Restore previous focus after closing right click context menu - Reloading config files (cache) - Run import in thread and AsyncClient.olm functions, they block async loop @@ -82,6 +85,7 @@ blank space - Sidepane + - Animate when logging out last account and sidepane turns invisible - Header back button when reduced - Better look for arrows and option button when collapsed - Show it when hovering/hitting focus keybind on the left when collapsed @@ -91,7 +95,7 @@ - Server selection - Register/Forgot? for SignIn dialog - Add room - - Leave/forget room warning popup + - Logout & leave/forget room warning popup - Prevent using the SendBox if no permission (power levels) - Prevent using an alias if that user is not in the room or no permission - Spinner when loading account, past room events, images or clicking buttons diff --git a/src/icons/light-thin/logout.svg b/src/icons/light-thin/logout.svg new file mode 100644 index 00000000..1ce1078c --- /dev/null +++ b/src/icons/light-thin/logout.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/python/backend.py b/src/python/backend.py index 375dcd35..16dc48da 100644 --- a/src/python/backend.py +++ b/src/python/backend.py @@ -99,14 +99,10 @@ class Backend: async def logout_client(self, user_id: str) -> None: client = self.clients.pop(user_id, None) if client: - self.models[Account].pop(client.user_id, None) + self.models[Account].pop(user_id, None) await client.logout() - - async def logout_all_clients(self) -> None: - await asyncio.gather(*( - self.logout_client(user_id) for user_id in self.clients.copy() - )) + await self.saved_accounts.delete(user_id) async def wait_until_client_exists(self, user_id: str = "") -> None: diff --git a/src/python/matrix_client.py b/src/python/matrix_client.py index 0ce0e131..0ee0fa95 100644 --- a/src/python/matrix_client.py +++ b/src/python/matrix_client.py @@ -131,6 +131,7 @@ class MatrixClient(nio.AsyncClient): with suppress(asyncio.CancelledError): await self.sync_task + await super().logout() await self.close() @@ -146,13 +147,14 @@ class MatrixClient(nio.AsyncClient): ft = asyncio.ensure_future(self.backend.get_profile(self.user_id)) ft.add_done_callback(on_profile_response) - def on_unexpected_sync_stop(future) -> None: - raise future.exception() + def on_sync_stop(future) -> None: + if isinstance(future.exception(), BaseException): + raise future.exception() self.sync_task = asyncio.ensure_future( self.sync_forever(timeout=10_000), ) - self.sync_task.add_done_callback(on_unexpected_sync_stop) + self.sync_task.add_done_callback(on_sync_stop) @property diff --git a/src/qml/Chat/Chat.qml b/src/qml/Chat/Chat.qml index d9515215..d5f4473e 100644 --- a/src/qml/Chat/Chat.qml +++ b/src/qml/Chat/Chat.qml @@ -21,7 +21,7 @@ HPage { onRoomInfoChanged: { if (roomInfo.left) { - // The room will most likely be gone on client restart + // If left, the room will most likely be gone on client restart window.uiState.page = "Pages/Default.qml" window.uiState.pageProperties = {} window.uiStateChanged() diff --git a/src/qml/Pages/EditAccount/EditAccount.qml b/src/qml/Pages/EditAccount/EditAccount.qml index e4de7d54..c0cf7866 100644 --- a/src/qml/Pages/EditAccount/EditAccount.qml +++ b/src/qml/Pages/EditAccount/EditAccount.qml @@ -25,6 +25,7 @@ HPage { Utils.coloredNameHtml(headerName, userId) ) + HSpacer {} Repeater { diff --git a/src/qml/SidePane/DelegateAccount.qml b/src/qml/SidePane/DelegateAccount.qml index 1cb45e37..59f95600 100644 --- a/src/qml/SidePane/DelegateAccount.qml +++ b/src/qml/SidePane/DelegateAccount.qml @@ -19,6 +19,7 @@ HTileDelegate { Behavior on opacity { HNumberAnimation {} } + property bool disconnecting: false readonly property bool forceExpand: Boolean(accountRoomList.filter) // Hide harmless error when a filter matches nothing @@ -27,9 +28,11 @@ HTileDelegate { } catch (err) {} - onActivated: pageLoader.showPage( - "EditAccount/EditAccount", { "userId": model.data.user_id } - ) + onActivated: if (! disconnecting) { + pageLoader.showPage( + "EditAccount/EditAccount", { "userId": model.data.user_id } + ) + } function toggleCollapse() { @@ -70,4 +73,29 @@ HTileDelegate { Behavior on opacity { HNumberAnimation {} } } + + contextMenu: HMenu { + HMenuItem { + icon.name: "logout" + text: qsTr("Logout") + onTriggered: { + disconnecting = true + + let page = window.uiState.page + let userId = model.data.user_id + + if ((modelSources["Account"] || []).length < 2) { + pageLoader.showPage("SignIn") + } + else if ((page == "Pages/EditAccount/EditAccount.qml" || + page == "Chat/Chat.qml") && + window.uiState.pageProperties.userId == userId) + { + pageLoader.showPage("Default") + } + + py.callCoro("logout_client", [userId]) + } + } + } }