Use new way to cancel current login for signin btn

This commit is contained in:
miruka 2019-12-07 18:45:03 -04:00
parent 6f589dbda5
commit 455801a641
5 changed files with 21 additions and 53 deletions

View File

@ -1,4 +1,4 @@
- cancel sign in, sign out key icon - better cancel for all boxes
- Media - Media
- Confirmation box after picking file to upload - Confirmation box after picking file to upload
- Handle set avatar upload errors - Handle set avatar upload errors

View File

@ -50,7 +50,6 @@ class Backend:
# Clients management # Clients management
@utils.cancel_previous
async def login_client(self, async def login_client(self,
user: str, user: str,
password: str, password: str,

View File

@ -1,19 +1,16 @@
"""Contains various utilities that are used throughout the package.""" """Contains various utilities that are used throughout the package."""
import asyncio
import collections import collections
import html import html
import inspect import inspect
import io import io
import logging as log
import xml.etree.cElementTree as xml_etree # FIXME: bandit warning import xml.etree.cElementTree as xml_etree # FIXME: bandit warning
from datetime import timedelta from datetime import timedelta
from enum import Enum from enum import Enum
from enum import auto as autostr from enum import auto as autostr
from functools import wraps
from pathlib import Path from pathlib import Path
from types import ModuleType from types import ModuleType
from typing import Any, Callable, Dict, Tuple, Type from typing import Any, Dict, Tuple, Type
from uuid import UUID from uuid import UUID
import filetype import filetype
@ -25,8 +22,6 @@ from nio.crypto import async_generator_from_data
Size = Tuple[int, int] Size = Tuple[int, int]
auto = autostr auto = autostr
CANCELLABLE_FUTURES: Dict[Tuple[Any, Callable], asyncio.Future] = {}
class AutoStrEnum(Enum): class AutoStrEnum(Enum):
"""An Enum where auto() assigns the member's name instead of an int. """An Enum where auto() assigns the member's name instead of an int.
@ -159,35 +154,3 @@ def classes_defined_in(module: ModuleType) -> Dict[str, Type]:
if not m[0].startswith("_") and if not m[0].startswith("_") and
m[1].__module__.startswith(module.__name__) m[1].__module__.startswith(module.__name__)
} }
def cancel_previous(async_func):
"""When the wrapped coroutine is called, cancel any previous instance
of that coroutine that may still be running.
"""
@wraps(async_func)
async def wrapper(*args, **kwargs):
try:
arg0_is_self = inspect.getfullargspec(async_func).args[0] == "self"
except IndexError:
parent_obj = None
else:
parent_obj = args[0] if arg0_is_self else None
previous = CANCELLABLE_FUTURES.get((parent_obj, async_func))
if previous:
previous.cancel()
log.info("Cancelled previous coro: %s", previous)
future = asyncio.ensure_future(async_func(*args, **kwargs))
CANCELLABLE_FUTURES[parent_obj, async_func] = future
try:
result = await future
return result
finally:
# Make sure to do this even if an exception happens
del CANCELLABLE_FUTURES[parent_obj, async_func]
return wrapper

View File

@ -74,6 +74,8 @@ Rectangle {
modelData.enabled === undefined ? modelData.enabled === undefined ?
true : modelData.enabled true : modelData.enabled
loading: modelData.loading || false
disableWhileLoading: disableWhileLoading:
modelData.disableWhileLoading === undefined ? modelData.disableWhileLoading === undefined ?
true : modelData.disableWhileLoading true : modelData.disableWhileLoading

View File

@ -14,14 +14,18 @@ HBox {
text: qsTr("Sign in"), text: qsTr("Sign in"),
enabled: canSignIn, enabled: canSignIn,
iconName: "sign-in", iconName: "sign-in",
disableWhileLoading: false loading: loginFuture !== null,
disableWhileLoading: false,
}, },
{ name: "cancel", text: qsTr("Cancel"), iconName: "cancel"}, { name: "cancel", text: qsTr("Cancel"), iconName: "cancel"},
] ]
buttonCallbacks: ({ buttonCallbacks: ({
apply: button => { apply: button => {
button.loading = true if (loginFuture) loginFuture.cancel()
signInTimeout.restart()
errorMessage.text = "" errorMessage.text = ""
let args = [ let args = [
@ -29,12 +33,10 @@ HBox {
undefined, serverField.text, undefined, serverField.text,
] ]
signInTimeout.restart()
loginFuture = py.callCoro("login_client", args, userId => { loginFuture = py.callCoro("login_client", args, userId => {
signInTimeout.stop() signInTimeout.stop()
errorMessage.text = "" errorMessage.text = ""
button.loading = false loginFuture = null
py.callCoro( py.callCoro(
rememberAccount.checked ? rememberAccount.checked ?
@ -48,13 +50,10 @@ HBox {
) )
}, type => { }, type => {
signInTimeout.stop() if (type === "CancelledError") return
if (type === "CancelledError") { loginFuture = null
loginFuture = null signInTimeout.stop()
button.loading = false
return
}
let txt = qsTr("Invalid request or login type") let txt = qsTr("Invalid request or login type")
@ -65,11 +64,16 @@ HBox {
txt = qsTr("This account was deactivated") txt = qsTr("This account was deactivated")
errorMessage.text = txt errorMessage.text = txt
button.loading = false
}) })
}, },
cancel: button => { if (loginFuture) loginFuture.cancel() } cancel: button => {
if (! loginFuture) return
signInTimeout.stop()
loginFuture.cancel()
loginFuture = null
}
}) })