mirror of
https://github.com/Yubico/yubioath-flutter.git
synced 2024-11-22 00:12:09 +03:00
Introduce helper flags to avoid extra polling
This commit is contained in:
parent
903f96acc8
commit
19d33af7bc
@ -89,7 +89,7 @@ def process(
|
||||
send(dict(kind="signal", status=status, body=body))
|
||||
|
||||
def success(response: RpcResponse):
|
||||
send(dict(kind="success", body=response.body))
|
||||
send(dict(kind="success", body=response.body, flags=response.side_effects))
|
||||
|
||||
event = Event()
|
||||
cmd_queue: Queue = Queue(1)
|
||||
|
@ -224,9 +224,11 @@ final _desktopDeviceDataProvider =
|
||||
ref.watch(rpcProvider).valueOrNull,
|
||||
ref.watch(currentDeviceProvider),
|
||||
);
|
||||
ref.listen<WindowState>(windowStateProvider, (_, windowState) {
|
||||
notifier._notifyWindowState(windowState);
|
||||
}, fireImmediately: true);
|
||||
if (notifier._deviceNode is NfcReaderNode) {
|
||||
ref.listen<WindowState>(windowStateProvider, (_, windowState) {
|
||||
notifier._notifyWindowState(windowState);
|
||||
}, fireImmediately: true);
|
||||
}
|
||||
return notifier;
|
||||
});
|
||||
|
||||
@ -240,6 +242,7 @@ class CurrentDeviceDataNotifier extends StateNotifier<AsyncValue<YubiKeyData>> {
|
||||
final RpcSession? _rpc;
|
||||
final DeviceNode? _deviceNode;
|
||||
Timer? _pollTimer;
|
||||
StreamSubscription? _flagSubscription;
|
||||
|
||||
CurrentDeviceDataNotifier(this._rpc, this._deviceNode)
|
||||
: super(const AsyncValue.loading()) {
|
||||
@ -252,15 +255,27 @@ class CurrentDeviceDataNotifier extends StateNotifier<AsyncValue<YubiKeyData>> {
|
||||
state = AsyncValue.error('device-inaccessible', StackTrace.current);
|
||||
}
|
||||
}
|
||||
_flagSubscription = _rpc?.flags.listen(
|
||||
(flag) {
|
||||
if (flag == 'device_info') {
|
||||
_pollDevice();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _pollDevice() {
|
||||
switch (_deviceNode) {
|
||||
case UsbYubiKeyNode _:
|
||||
_refreshUsb();
|
||||
case NfcReaderNode _:
|
||||
_pollCard();
|
||||
}
|
||||
}
|
||||
|
||||
void _notifyWindowState(WindowState windowState) {
|
||||
if (windowState.active) {
|
||||
if (_deviceNode is UsbYubiKeyNode?) {
|
||||
_pollUsb();
|
||||
} else {
|
||||
_pollCard();
|
||||
}
|
||||
_pollCard();
|
||||
} else {
|
||||
_pollTimer?.cancel();
|
||||
// TODO: Should we clear the key here?
|
||||
@ -272,12 +287,12 @@ class CurrentDeviceDataNotifier extends StateNotifier<AsyncValue<YubiKeyData>> {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_flagSubscription?.cancel();
|
||||
_pollTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _pollUsb() async {
|
||||
_pollTimer?.cancel();
|
||||
void _refreshUsb() async {
|
||||
final node = _deviceNode!;
|
||||
var result = await _rpc?.command('get', node.path.segments);
|
||||
if (mounted && result != null) {
|
||||
@ -288,9 +303,6 @@ class CurrentDeviceDataNotifier extends StateNotifier<AsyncValue<YubiKeyData>> {
|
||||
state = AsyncValue.data(newState);
|
||||
}
|
||||
}
|
||||
if (mounted) {
|
||||
_pollTimer = Timer(_usbPollDelay, _pollUsb);
|
||||
}
|
||||
}
|
||||
|
||||
void _pollCard() async {
|
||||
@ -303,11 +315,13 @@ class CurrentDeviceDataNotifier extends StateNotifier<AsyncValue<YubiKeyData>> {
|
||||
final oldState = state.valueOrNull;
|
||||
final newState = YubiKeyData(node, result['data']['name'],
|
||||
DeviceInfo.fromJson(result['data']['info']));
|
||||
if (oldState != null && oldState != newState) {
|
||||
// Ensure state is cleared
|
||||
state = const AsyncValue.loading();
|
||||
if (oldState != newState) {
|
||||
if (oldState != null) {
|
||||
// Ensure state is cleared
|
||||
state = const AsyncValue.loading();
|
||||
}
|
||||
state = AsyncValue.data(newState);
|
||||
}
|
||||
state = AsyncValue.data(newState);
|
||||
} else {
|
||||
final status = result['data']['status'];
|
||||
// Only update if status is not changed
|
||||
|
@ -21,7 +21,8 @@ part 'models.g.dart';
|
||||
|
||||
@Freezed(unionKey: 'kind')
|
||||
class RpcResponse with _$RpcResponse {
|
||||
factory RpcResponse.success(Map<String, dynamic> body) = Success;
|
||||
factory RpcResponse.success(Map<String, dynamic> body, List<String> flags) =
|
||||
Success;
|
||||
factory RpcResponse.signal(String status, Map<String, dynamic> body) = Signal;
|
||||
factory RpcResponse.error(
|
||||
String status, String message, Map<String, dynamic> body) = RpcError;
|
||||
|
@ -34,7 +34,8 @@ mixin _$RpcResponse {
|
||||
Map<String, dynamic> get body => throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(Map<String, dynamic> body) success,
|
||||
required TResult Function(Map<String, dynamic> body, List<String> flags)
|
||||
success,
|
||||
required TResult Function(String status, Map<String, dynamic> body) signal,
|
||||
required TResult Function(
|
||||
String status, String message, Map<String, dynamic> body)
|
||||
@ -43,7 +44,7 @@ mixin _$RpcResponse {
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(Map<String, dynamic> body)? success,
|
||||
TResult? Function(Map<String, dynamic> body, List<String> flags)? success,
|
||||
TResult? Function(String status, Map<String, dynamic> body)? signal,
|
||||
TResult? Function(String status, String message, Map<String, dynamic> body)?
|
||||
error,
|
||||
@ -51,7 +52,7 @@ mixin _$RpcResponse {
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(Map<String, dynamic> body)? success,
|
||||
TResult Function(Map<String, dynamic> body, List<String> flags)? success,
|
||||
TResult Function(String status, Map<String, dynamic> body)? signal,
|
||||
TResult Function(String status, String message, Map<String, dynamic> body)?
|
||||
error,
|
||||
@ -127,7 +128,7 @@ abstract class _$$SuccessImplCopyWith<$Res>
|
||||
__$$SuccessImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({Map<String, dynamic> body});
|
||||
$Res call({Map<String, dynamic> body, List<String> flags});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@ -142,12 +143,17 @@ class __$$SuccessImplCopyWithImpl<$Res>
|
||||
@override
|
||||
$Res call({
|
||||
Object? body = null,
|
||||
Object? flags = null,
|
||||
}) {
|
||||
return _then(_$SuccessImpl(
|
||||
null == body
|
||||
? _value._body
|
||||
: body // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>,
|
||||
null == flags
|
||||
? _value._flags
|
||||
: flags // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -155,8 +161,10 @@ class __$$SuccessImplCopyWithImpl<$Res>
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$SuccessImpl implements Success {
|
||||
_$SuccessImpl(final Map<String, dynamic> body, {final String? $type})
|
||||
_$SuccessImpl(final Map<String, dynamic> body, final List<String> flags,
|
||||
{final String? $type})
|
||||
: _body = body,
|
||||
_flags = flags,
|
||||
$type = $type ?? 'success';
|
||||
|
||||
factory _$SuccessImpl.fromJson(Map<String, dynamic> json) =>
|
||||
@ -170,12 +178,20 @@ class _$SuccessImpl implements Success {
|
||||
return EqualUnmodifiableMapView(_body);
|
||||
}
|
||||
|
||||
final List<String> _flags;
|
||||
@override
|
||||
List<String> get flags {
|
||||
if (_flags is EqualUnmodifiableListView) return _flags;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_flags);
|
||||
}
|
||||
|
||||
@JsonKey(name: 'kind')
|
||||
final String $type;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RpcResponse.success(body: $body)';
|
||||
return 'RpcResponse.success(body: $body, flags: $flags)';
|
||||
}
|
||||
|
||||
@override
|
||||
@ -183,13 +199,16 @@ class _$SuccessImpl implements Success {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$SuccessImpl &&
|
||||
const DeepCollectionEquality().equals(other._body, _body));
|
||||
const DeepCollectionEquality().equals(other._body, _body) &&
|
||||
const DeepCollectionEquality().equals(other._flags, _flags));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(runtimeType, const DeepCollectionEquality().hash(_body));
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(_body),
|
||||
const DeepCollectionEquality().hash(_flags));
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@ -200,37 +219,38 @@ class _$SuccessImpl implements Success {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(Map<String, dynamic> body) success,
|
||||
required TResult Function(Map<String, dynamic> body, List<String> flags)
|
||||
success,
|
||||
required TResult Function(String status, Map<String, dynamic> body) signal,
|
||||
required TResult Function(
|
||||
String status, String message, Map<String, dynamic> body)
|
||||
error,
|
||||
}) {
|
||||
return success(body);
|
||||
return success(body, flags);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(Map<String, dynamic> body)? success,
|
||||
TResult? Function(Map<String, dynamic> body, List<String> flags)? success,
|
||||
TResult? Function(String status, Map<String, dynamic> body)? signal,
|
||||
TResult? Function(String status, String message, Map<String, dynamic> body)?
|
||||
error,
|
||||
}) {
|
||||
return success?.call(body);
|
||||
return success?.call(body, flags);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(Map<String, dynamic> body)? success,
|
||||
TResult Function(Map<String, dynamic> body, List<String> flags)? success,
|
||||
TResult Function(String status, Map<String, dynamic> body)? signal,
|
||||
TResult Function(String status, String message, Map<String, dynamic> body)?
|
||||
error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (success != null) {
|
||||
return success(body);
|
||||
return success(body, flags);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
@ -278,12 +298,14 @@ class _$SuccessImpl implements Success {
|
||||
}
|
||||
|
||||
abstract class Success implements RpcResponse {
|
||||
factory Success(final Map<String, dynamic> body) = _$SuccessImpl;
|
||||
factory Success(final Map<String, dynamic> body, final List<String> flags) =
|
||||
_$SuccessImpl;
|
||||
|
||||
factory Success.fromJson(Map<String, dynamic> json) = _$SuccessImpl.fromJson;
|
||||
|
||||
@override
|
||||
Map<String, dynamic> get body;
|
||||
List<String> get flags;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$SuccessImplCopyWith<_$SuccessImpl> get copyWith =>
|
||||
@ -380,7 +402,8 @@ class _$SignalImpl implements Signal {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(Map<String, dynamic> body) success,
|
||||
required TResult Function(Map<String, dynamic> body, List<String> flags)
|
||||
success,
|
||||
required TResult Function(String status, Map<String, dynamic> body) signal,
|
||||
required TResult Function(
|
||||
String status, String message, Map<String, dynamic> body)
|
||||
@ -392,7 +415,7 @@ class _$SignalImpl implements Signal {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(Map<String, dynamic> body)? success,
|
||||
TResult? Function(Map<String, dynamic> body, List<String> flags)? success,
|
||||
TResult? Function(String status, Map<String, dynamic> body)? signal,
|
||||
TResult? Function(String status, String message, Map<String, dynamic> body)?
|
||||
error,
|
||||
@ -403,7 +426,7 @@ class _$SignalImpl implements Signal {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(Map<String, dynamic> body)? success,
|
||||
TResult Function(Map<String, dynamic> body, List<String> flags)? success,
|
||||
TResult Function(String status, Map<String, dynamic> body)? signal,
|
||||
TResult Function(String status, String message, Map<String, dynamic> body)?
|
||||
error,
|
||||
@ -570,7 +593,8 @@ class _$RpcErrorImpl implements RpcError {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(Map<String, dynamic> body) success,
|
||||
required TResult Function(Map<String, dynamic> body, List<String> flags)
|
||||
success,
|
||||
required TResult Function(String status, Map<String, dynamic> body) signal,
|
||||
required TResult Function(
|
||||
String status, String message, Map<String, dynamic> body)
|
||||
@ -582,7 +606,7 @@ class _$RpcErrorImpl implements RpcError {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(Map<String, dynamic> body)? success,
|
||||
TResult? Function(Map<String, dynamic> body, List<String> flags)? success,
|
||||
TResult? Function(String status, Map<String, dynamic> body)? signal,
|
||||
TResult? Function(String status, String message, Map<String, dynamic> body)?
|
||||
error,
|
||||
@ -593,7 +617,7 @@ class _$RpcErrorImpl implements RpcError {
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(Map<String, dynamic> body)? success,
|
||||
TResult Function(Map<String, dynamic> body, List<String> flags)? success,
|
||||
TResult Function(String status, Map<String, dynamic> body)? signal,
|
||||
TResult Function(String status, String message, Map<String, dynamic> body)?
|
||||
error,
|
||||
|
@ -9,12 +9,14 @@ part of 'models.dart';
|
||||
_$SuccessImpl _$$SuccessImplFromJson(Map<String, dynamic> json) =>
|
||||
_$SuccessImpl(
|
||||
json['body'] as Map<String, dynamic>,
|
||||
(json['flags'] as List<dynamic>).map((e) => e as String).toList(),
|
||||
$type: json['kind'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$SuccessImplToJson(_$SuccessImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'body': instance.body,
|
||||
'flags': instance.flags,
|
||||
'kind': instance.$type,
|
||||
};
|
||||
|
||||
|
@ -102,8 +102,12 @@ class RpcSession {
|
||||
final String executable;
|
||||
late _RpcConnection _connection;
|
||||
final StreamController<_Request> _requests = StreamController();
|
||||
final StreamController<String> _flags = StreamController();
|
||||
late final Stream<String> flags;
|
||||
|
||||
RpcSession(this.executable);
|
||||
RpcSession(this.executable) {
|
||||
flags = _flags.stream.asBroadcastStream();
|
||||
}
|
||||
|
||||
static void _logEntry(String entry) {
|
||||
try {
|
||||
@ -230,7 +234,7 @@ class RpcSession {
|
||||
|
||||
Future<Map<String, dynamic>> command(String action, List<String>? target,
|
||||
{Map? params, Signaler? signal}) {
|
||||
var request = _Request(action, target ?? [], params ?? {}, signal);
|
||||
final request = _Request(action, target ?? [], params ?? {}, signal);
|
||||
_requests.add(request);
|
||||
return request.completer.future;
|
||||
}
|
||||
@ -278,6 +282,10 @@ class RpcSession {
|
||||
},
|
||||
success: (success) {
|
||||
request.completer.complete(success.body);
|
||||
for (final flag in success.flags) {
|
||||
_log.traffic('FLAG', flag);
|
||||
_flags.add(flag);
|
||||
}
|
||||
completed = true;
|
||||
},
|
||||
error: (error) {
|
||||
|
Loading…
Reference in New Issue
Block a user