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 import nio
from appdirs import AppDirs from appdirs import AppDirs
import pyotherside
from . import __about__ from . import __about__
from .pyotherside_events import CoroutineDone from .pyotherside_events import CoroutineDone

View File

@ -7,6 +7,7 @@ import hsluv
import nio import nio
from . import utils
from .app import App from .app import App
from .matrix_client import MatrixClient, MatrixError from .matrix_client import MatrixClient, MatrixError
from .models.items import Account, Device, Event, Member, Room, Upload from .models.items import Account, Device, Event, Member, Room, Upload
@ -46,6 +47,7 @@ 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,17 +1,21 @@
import asyncio
import collections import collections
import html import html
import inspect import inspect
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 enum import Enum from enum import Enum
from enum import auto as autostr from enum import auto as autostr
from pathlib import Path from pathlib import Path
from types import ModuleType 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 import filetype
auto = autostr auto = autostr
CANCELLABLE_FUTURES: Dict[Tuple[Any, Callable], asyncio.Future] = {}
class AutoStrEnum(Enum): class AutoStrEnum(Enum):
@staticmethod @staticmethod
@ -83,3 +87,30 @@ 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):
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 theme.icons.colorize
) )
enabled: (modelData.enabled == undefined ? enabled:
true : modelData.enabled) && modelData.enabled === undefined ?
! button.loading true : modelData.enabled
disableWhileLoading:
modelData.disableWhileLoading === undefined ?
true : modelData.disableWhileLoading
onClicked: buttonCallbacks[name](button) onClicked: buttonCallbacks[name](button)

View File

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

View File

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