2024-08-28 17:27:46 +03:00
|
|
|
/*
|
|
|
|
* 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-08-28 17:27:46 +03:00
|
|
|
|
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-08-28 17:27:46 +03:00
|
|
|
|
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-08-28 17:27:46 +03:00
|
|
|
|
2024-09-06 18:21:59 +03:00
|
|
|
class _NfcEventNotifierListener {
|
2024-08-28 17:27:46 +03:00
|
|
|
final ProviderRef _ref;
|
2024-08-30 14:36:03 +03:00
|
|
|
ProviderSubscription<NfcEvent>? listener;
|
2024-08-28 17:27:46 +03:00
|
|
|
|
2024-09-06 18:21:59 +03:00
|
|
|
_NfcEventNotifierListener(this._ref);
|
2024-08-28 17:27:46 +03:00
|
|
|
|
|
|
|
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');
|
2024-08-28 17:27:46 +03:00
|
|
|
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
|
|
|
}
|
2024-08-28 17:27:46 +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);
|
2024-08-28 17:27:46 +03:00
|
|
|
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;
|
2024-08-28 17:27:46 +03:00
|
|
|
final result = await showModalBottomSheet(
|
|
|
|
context: context,
|
|
|
|
builder: (BuildContext context) {
|
2024-09-09 11:31:03 +03:00
|
|
|
return const NfcOverlayWidget();
|
2024-08-28 17:27:46 +03:00
|
|
|
});
|
|
|
|
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-08-28 17:27:46 +03:00
|
|
|
}
|
2024-09-06 09:37:34 +03:00
|
|
|
visible = false;
|
2024-08-28 17:27:46 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-08-28 17:27:46 +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);
|
2024-08-28 17:27:46 +03:00
|
|
|
}
|