Files
gopeed/ui/flutter/lib/shared/widgets/gopeed_app_mark.dart
2026-09-05 19:53:41 +08:00

130 lines
3.5 KiB
Dart

import 'package:flutter/widgets.dart';
import '../theme/app_palette.dart';
class GopeedAppMark extends StatelessWidget {
const GopeedAppMark({super.key, this.size = 24});
final double size;
@override
Widget build(BuildContext context) {
final palette = AppPalette.of(context);
return Semantics(
label: 'Gopeed',
image: true,
child: SizedBox.square(
dimension: size,
child: CustomPaint(
painter: _GopeedAppMarkPainter(
background: palette.primaryActionBg,
foreground: palette.primaryActionForeground,
),
),
),
);
}
}
class _GopeedAppMarkPainter extends CustomPainter {
const _GopeedAppMarkPainter({required this.background, required this.foreground});
final Color background;
final Color foreground;
@override
void paint(Canvas canvas, Size size) {
final side = size.shortestSide;
final bounds = Rect.fromCenter(center: size.center(Offset.zero), width: side, height: side).deflate(side * 0.02);
final circle = Path()..addOval(bounds);
final backgroundPaint = Paint()
..color = background
..isAntiAlias = true;
final foregroundPaint = Paint()
..color = foreground
..isAntiAlias = true;
canvas.drawPath(circle, backgroundPaint);
canvas.save();
canvas.clipPath(circle, doAntiAlias: true);
Offset point(double x, double y) {
return Offset(bounds.left + bounds.width * x, bounds.top + bounds.height * y);
}
final cloud = Path()
..moveTo(point(-0.02, 0.83).dx, point(-0.02, 0.83).dy)
..cubicTo(
point(0.04, 0.78).dx,
point(0.04, 0.78).dy,
point(0.09, 0.75).dx,
point(0.09, 0.75).dy,
point(0.15, 0.73).dx,
point(0.15, 0.73).dy,
)
..cubicTo(
point(0.12, 0.66).dx,
point(0.12, 0.66).dy,
point(0.13, 0.60).dx,
point(0.13, 0.60).dy,
point(0.20, 0.57).dx,
point(0.20, 0.57).dy,
)
..cubicTo(
point(0.27, 0.54).dx,
point(0.27, 0.54).dy,
point(0.31, 0.58).dx,
point(0.31, 0.58).dy,
point(0.35, 0.62).dx,
point(0.35, 0.62).dy,
)
..cubicTo(
point(0.46, 0.42).dx,
point(0.46, 0.42).dy,
point(0.66, 0.40).dx,
point(0.66, 0.40).dy,
point(0.78, 0.50).dx,
point(0.78, 0.50).dy,
)
..cubicTo(
point(0.86, 0.57).dx,
point(0.86, 0.57).dy,
point(0.87, 0.68).dx,
point(0.87, 0.68).dy,
point(0.86, 0.75).dx,
point(0.86, 0.75).dy,
)
..cubicTo(
point(0.92, 0.76).dx,
point(0.92, 0.76).dy,
point(0.98, 0.79).dx,
point(0.98, 0.79).dy,
point(1.03, 0.84).dx,
point(1.03, 0.84).dy,
);
canvas.drawPath(
cloud,
Paint()
..color = foreground
..style = PaintingStyle.stroke
..strokeWidth = side * 0.05
..strokeCap = StrokeCap.round
..strokeJoin = StrokeJoin.round
..isAntiAlias = true,
);
final arrow = Path()
..addRect(Rect.fromPoints(point(0.41, 0.66), point(0.59, 0.86)))
..moveTo(point(0.31, 0.85).dx, point(0.31, 0.85).dy)
..lineTo(point(0.69, 0.85).dx, point(0.69, 0.85).dy)
..lineTo(point(0.50, 1.02).dx, point(0.50, 1.02).dy)
..close();
canvas.drawPath(arrow, foregroundPaint);
canvas.restore();
}
@override
bool shouldRepaint(_GopeedAppMarkPainter oldDelegate) {
return background != oldDelegate.background || foreground != oldDelegate.foreground;
}
}