Preserve Flutter mirror-os codebase
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
import 'dart:math' as math;
|
||||
import 'package:flutter/material.dart';
|
||||
import '../theme.dart';
|
||||
|
||||
class ProgressRing extends StatelessWidget {
|
||||
final double percent;
|
||||
final double size;
|
||||
final double strokeWidth;
|
||||
final Color? color;
|
||||
final Color? backgroundColor;
|
||||
|
||||
const ProgressRing({
|
||||
super.key,
|
||||
required this.percent,
|
||||
this.size = 36,
|
||||
this.strokeWidth = 3,
|
||||
this.color,
|
||||
this.backgroundColor,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final effectiveColor = percent >= 95
|
||||
? MirrorTheme.success
|
||||
: (color ?? MirrorTheme.accent);
|
||||
|
||||
return SizedBox(
|
||||
width: size,
|
||||
height: size,
|
||||
child: CustomPaint(
|
||||
painter: _ProgressRingPainter(
|
||||
percent: percent.clamp(0, 100),
|
||||
strokeWidth: strokeWidth,
|
||||
color: effectiveColor,
|
||||
backgroundColor: backgroundColor ?? MirrorTheme.surfaceLight,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ProgressRingPainter extends CustomPainter {
|
||||
final double percent;
|
||||
final double strokeWidth;
|
||||
final Color color;
|
||||
final Color backgroundColor;
|
||||
|
||||
_ProgressRingPainter({
|
||||
required this.percent,
|
||||
required this.strokeWidth,
|
||||
required this.color,
|
||||
required this.backgroundColor,
|
||||
});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final center = Offset(size.width / 2, size.height / 2);
|
||||
final radius = (size.width - strokeWidth) / 2;
|
||||
|
||||
final bgPaint = Paint()
|
||||
..color = backgroundColor
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = strokeWidth;
|
||||
|
||||
final fgPaint = Paint()
|
||||
..color = color
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = strokeWidth
|
||||
..strokeCap = StrokeCap.round;
|
||||
|
||||
canvas.drawCircle(center, radius, bgPaint);
|
||||
|
||||
final sweepAngle = (percent / 100) * 2 * math.pi;
|
||||
canvas.drawArc(
|
||||
Rect.fromCircle(center: center, radius: radius),
|
||||
-math.pi / 2,
|
||||
sweepAngle,
|
||||
false,
|
||||
fgPaint,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(_ProgressRingPainter oldDelegate) =>
|
||||
oldDelegate.percent != percent || oldDelegate.color != color;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../theme.dart';
|
||||
|
||||
class TimerDisplay extends StatelessWidget {
|
||||
final int seconds;
|
||||
final String? label;
|
||||
final TextStyle? style;
|
||||
|
||||
const TimerDisplay({
|
||||
super.key,
|
||||
required this.seconds,
|
||||
this.label,
|
||||
this.style,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final minutes = seconds ~/ 60;
|
||||
final secs = seconds % 60;
|
||||
final timeText = minutes > 0
|
||||
? '$minutes:${secs.toString().padLeft(2, '0')}'
|
||||
: '$secs';
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (label != null)
|
||||
Text(
|
||||
label!,
|
||||
style: Theme.of(context).textTheme.labelLarge?.copyWith(
|
||||
color: MirrorTheme.accent,
|
||||
letterSpacing: 8,
|
||||
),
|
||||
),
|
||||
if (label != null) const SizedBox(height: 40),
|
||||
Text(
|
||||
timeText,
|
||||
style: style ?? Theme.of(context).textTheme.displayLarge?.copyWith(
|
||||
color: MirrorTheme.accent,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user