yubioath-flutter/lib/android/views/nfc/nfc_activity_icon.dart
2023-09-26 13:23:36 +02:00

137 lines
3.6 KiB
Dart

/*
* Copyright (C) 2023 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 'dart:math';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:yubico_authenticator/android/state.dart';
import 'package:yubico_authenticator/app/views/horizontal_shake.dart';
import '../../../theme.dart';
/// Default icon for [NfcActivityWidget]
class NfcActivityIcon extends StatelessWidget {
final NfcActivity nfcActivity;
const NfcActivityIcon(this.nfcActivity, {super.key});
@override
Widget build(BuildContext context) => switch (nfcActivity) {
NfcActivity.ready => const HorizontalShake(
startupDelay: Duration(seconds: 4),
child: _NfcIconWithOpacity(0.8)),
NfcActivity.processingStarted => Stack(
fit: StackFit.loose,
children: [
ImageFiltered(
imageFilter: ImageFilter.blur(
sigmaX: 7.0,
sigmaY: 7.0,
tileMode: TileMode.decal,
),
child: const Opacity(
opacity: 0.6,
child: _NfcIcon(
color: accentGreen,
),
),
),
const _NfcIcon(),
],
),
NfcActivity.processingInterrupted =>
const _NfcIconWrapper(Icons.warning_amber_rounded),
_ => const _NfcIcon(),
};
}
class _NfcIconWithOpacity extends StatelessWidget {
final double opacity;
const _NfcIconWithOpacity(this.opacity);
@override
Widget build(BuildContext context) => Opacity(
opacity: opacity,
child: const _NfcIcon(),
);
}
class _NfcIconWrapper extends StatelessWidget {
final IconData _iconData;
const _NfcIconWrapper(this._iconData);
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (BuildContext buildContext, BoxConstraints constraints) =>
Icon(
_iconData,
size: constraints.biggest.width,
));
}
}
class _NfcIcon extends StatelessWidget {
final Color? color;
const _NfcIcon({this.color});
@override
Widget build(BuildContext context) {
final theme = IconTheme.of(context);
return LayoutBuilder(
builder: (BuildContext buildContext, BoxConstraints constraints) =>
CustomPaint(
size: Size.copy(constraints.biggest),
painter: _NfcIconPainter(color ?? theme.color ?? Colors.black),
),
);
}
}
class _NfcIconPainter extends CustomPainter {
final Color color;
_NfcIconPainter(this.color);
@override
void paint(Canvas canvas, Size size) {
final step = size.width / 4;
const sweep = pi / 4;
final paint = Paint()
..color = color
..style = PaintingStyle.stroke
..strokeCap = StrokeCap.round
..strokeWidth = step / 2;
final rect =
Offset(size.width * -1.7, 0) & Size(size.width * 2, size.height);
for (var i = 0; i < 3; i++) {
canvas.drawArc(rect.inflate(i * step), -sweep / 2, sweep, false, paint);
}
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return false;
}
}