yubioath-flutter/lib/android/overlay/nfc/nfc_event_notifier.dart

124 lines
3.4 KiB
Dart
Raw Normal View History

/*
* Copyright (C) 2024 Yubico.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
2024-09-04 14:34:00 +03:00
import 'package:logging/logging.dart';
2024-09-04 14:34:00 +03:00
import '../../../app/logging.dart';
2024-09-05 20:13:16 +03:00
import '../../../app/state.dart';
2024-09-09 14:13:36 +03:00
import 'nfc_overlay.dart';
2024-09-09 11:31:03 +03:00
import 'views/nfc_overlay_widget.dart';
2024-09-09 11:31:03 +03:00
final _log = Logger('android.nfc_event_notifier');
class NfcEvent {
const NfcEvent();
}
class NfcHideViewEvent extends NfcEvent {
final Duration delay;
const NfcHideViewEvent({this.delay = Duration.zero});
}
class NfcSetViewEvent extends NfcEvent {
final Widget child;
final bool showIfHidden;
const NfcSetViewEvent({required this.child, this.showIfHidden = true});
}
final nfcEventNotifier =
NotifierProvider<_NfcEventNotifier, NfcEvent>(_NfcEventNotifier.new);
class _NfcEventNotifier extends Notifier<NfcEvent> {
@override
NfcEvent build() {
return const NfcEvent();
}
void send(NfcEvent event) {
state = event;
}
}
2024-09-04 14:34:00 +03:00
2024-09-06 18:21:59 +03:00
final nfcEventNotifierListener = Provider<_NfcEventNotifierListener>(
(ref) => _NfcEventNotifierListener(ref));
2024-09-06 18:21:59 +03:00
class _NfcEventNotifierListener {
final ProviderRef _ref;
2024-08-30 14:36:03 +03:00
ProviderSubscription<NfcEvent>? listener;
2024-09-06 18:21:59 +03:00
_NfcEventNotifierListener(this._ref);
void startListener(BuildContext context) {
listener?.close();
2024-09-06 17:58:30 +03:00
listener = _ref.listen(nfcEventNotifier, (previous, action) {
2024-09-06 18:21:59 +03:00
_log.debug('Event change: $previous -> $action');
switch (action) {
2024-09-06 09:37:34 +03:00
case (NfcSetViewEvent a):
if (!visible && a.showIfHidden) {
_show(context, a.child);
} else {
2024-09-06 18:21:59 +03:00
_ref
2024-09-09 11:31:03 +03:00
.read(nfcOverlayWidgetProperties.notifier)
2024-09-06 18:21:59 +03:00
.update(child: a.child);
2024-09-06 09:37:34 +03:00
}
break;
2024-09-05 20:13:16 +03:00
case (NfcHideViewEvent e):
2024-09-06 17:58:30 +03:00
_hide(context, e.delay);
break;
}
});
}
void _show(BuildContext context, Widget child) async {
2024-09-09 11:31:03 +03:00
final notifier = _ref.read(nfcOverlayWidgetProperties.notifier);
2024-09-06 18:21:59 +03:00
notifier.update(child: child);
2024-09-06 09:37:34 +03:00
if (!visible) {
visible = true;
final result = await showModalBottomSheet(
context: context,
builder: (BuildContext context) {
2024-09-09 11:31:03 +03:00
return const NfcOverlayWidget();
});
if (result == null) {
// the modal sheet was cancelled by Back button, close button or dismiss
2024-09-09 14:13:36 +03:00
_ref.read(nfcOverlay.notifier).onCancel();
}
2024-09-06 09:37:34 +03:00
visible = false;
}
}
2024-09-05 20:13:16 +03:00
void _hide(BuildContext context, Duration timeout) {
Future.delayed(timeout, () {
_ref.read(withContextProvider)((context) async {
2024-09-06 09:37:34 +03:00
if (visible) {
2024-09-05 20:13:16 +03:00
Navigator.of(context).pop('HIDDEN');
2024-09-06 09:37:34 +03:00
visible = false;
2024-09-05 20:13:16 +03:00
}
});
});
}
2024-09-06 09:37:34 +03:00
2024-09-06 18:21:59 +03:00
bool get visible =>
2024-09-09 11:31:03 +03:00
_ref.read(nfcOverlayWidgetProperties.select((s) => s.visible));
2024-09-06 17:58:30 +03:00
2024-09-09 11:31:03 +03:00
set visible(bool visible) =>
_ref.read(nfcOverlayWidgetProperties.notifier).update(visible: visible);
}