anchor.diff:    @override
     Future<OathCode> calculate(OathCredential credential,
         {bool update = true}) async {
  +    // Prompt for touch if needed
  +    UserInteractionController? controller;
  +    Timer? touchTimer;
  +    if (_currentDevice?.transport == Transport.usb) {
  +      void triggerTouchPrompt() async {
  +        controller = await _withContext(
  +          (context) async => promptUserInteraction(
  +            context,
  +            icon: const Icon(Icons.touch_app),
  +            title: 'Touch Required',
  +            description: 'Touch the button on your YubiKey now.',
  +          ),
  +        );
  +      }
  +
  +      if (credential.touchRequired) {
  +        triggerTouchPrompt();
  +      } else if (credential.oathType == OathType.hotp) {
  +        touchTimer =
  +            Timer(const Duration(milliseconds: 500), triggerTouchPrompt);
  +      }
  +    }
  +
       try {
         var resultJson = await _api.calculate(credential.id);
         var result = jsonDecode(resultJson);
  
positive.code:         throw CancellationException();
        }
        rethrow;
      }
    }
  
  
negative.code: );
  
  class _AndroidCredentialListNotifier extends OathCredentialListNotifier {
    final WithContext _withContext;
    final DeviceNode? _currentDevice;
    final OathApi _api;
    Timer? _timer;
  
    _AndroidCredentialListNotifier(
        this._withContext, this._currentDevice, this._api, List<OathPair>? pairs)
        : super() {
      state = pairs;
      _scheduleRefresh();
  