SignIn: cancel previous task when clicking button

This commit is contained in:
miruka 2019-11-11 09:12:31 -04:00
parent c9ddd4ee80
commit 746a9259db
6 changed files with 54 additions and 8 deletions

View File

@ -11,8 +11,6 @@ from typing import Coroutine, Sequence
import nio
from appdirs import AppDirs
import pyotherside
from . import __about__
from .pyotherside_events import CoroutineDone

View File

@ -7,6 +7,7 @@ import hsluv
import nio
from . import utils
from .app import App
from .matrix_client import MatrixClient, MatrixError
from .models.items import Account, Device, Event, Member, Room, Upload
@ -46,6 +47,7 @@ class Backend:
# Clients management
@utils.cancel_previous
async def login_client(self,
user: str,
password: str,

View File

@ -1,17 +1,21 @@
import asyncio
import collections
import html
import inspect
import logging as log
import xml.etree.cElementTree as xml_etree # FIXME: bandit warning
from enum import Enum
from enum import auto as autostr
from pathlib import Path
from types import ModuleType
from typing import IO, Any, Dict, Tuple, Type, Union
from typing import IO, Any, Callable, Dict, Tuple, Type, Union
import filetype
auto = autostr
CANCELLABLE_FUTURES: Dict[Tuple[Any, Callable], asyncio.Future] = {}
class AutoStrEnum(Enum):
@staticmethod
@ -83,3 +87,30 @@ def classes_defined_in(module: ModuleType) -> Dict[str, Type]:
if not m[0].startswith("_") and
m[1].__module__.startswith(module.__name__)
}
def cancel_previous(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

@ -98,9 +98,13 @@ Rectangle {
theme.icons.colorize
)
enabled: (modelData.enabled == undefined ?
true : modelData.enabled) &&
! button.loading
enabled:
modelData.enabled === undefined ?
true : modelData.enabled
disableWhileLoading:
modelData.disableWhileLoading === undefined ?
true : modelData.disableWhileLoading
onClicked: buttonCallbacks[name](button)

View File

@ -12,7 +12,6 @@ Button {
iconItem.svgName: loading ? "hourglass" : icon.name
icon.color: theme.icons.colorize
enabled: ! loading
// Must be explicitely set to display correctly on KDE
implicitWidth: Math.max(
@ -32,6 +31,7 @@ Button {
readonly property alias label: contentItem.label
property color backgroundColor: theme.controls.button.background
property bool disableWhileLoading: true
property bool loading: false
property bool circle: false
@ -41,6 +41,14 @@ Button {
}
Binding {
when: disableWhileLoading && loading
target: button
property: "enabled"
value: false
}
background: HButtonBackground {
button: button
buttonTheme: theme.controls.button

View File

@ -19,7 +19,8 @@ HPage {
buttonModel: [
{ name: "register", text: qsTr("Register"), enabled: false },
{ name: "login", text: qsTr("Login"), enabled: canLogin },
{ name: "login", text: qsTr("Login"), enabled: canLogin,
disableWhileLoading: false },
{ name: "forgot", text: qsTr("Forgot?"), enabled: false },
]
@ -52,6 +53,8 @@ HPage {
"AccountSettings/AccountSettings", {userId: data}
)
}, type => {
if (type === "CancelledError") return
loginTimeout.stop()
let txt = qsTr("Invalid request or login type")