- Add purple checkmark icon matching login screen style - Generate Android adaptive icons with proper foreground/background - Update iOS app icons - Include icon generator tool for future updates
119 lines
3.7 KiB
Dart
119 lines
3.7 KiB
Dart
import 'dart:io';
|
|
import 'dart:math';
|
|
import 'package:image/image.dart' as img;
|
|
|
|
/// Generates app icon PNG files for Agenda Tasks
|
|
/// Run with: cd tool && dart pub get && dart run generate_icon.dart
|
|
void main() async {
|
|
print('Generating app icons...');
|
|
|
|
// Generate main icon (1024x1024)
|
|
final mainIcon = generateIcon(1024, withBackground: true);
|
|
final mainPng = img.encodePng(mainIcon);
|
|
await File('../assets/icon/app_icon.png').writeAsBytes(mainPng);
|
|
print('Created: assets/icon/app_icon.png (${mainPng.length} bytes)');
|
|
|
|
// Generate adaptive icon foreground (1024x1024)
|
|
final foregroundIcon = generateIcon(1024, withBackground: false);
|
|
final fgPng = img.encodePng(foregroundIcon);
|
|
await File('../assets/icon/app_icon_foreground.png').writeAsBytes(fgPng);
|
|
print('Created: assets/icon/app_icon_foreground.png (${fgPng.length} bytes)');
|
|
|
|
print('Done! Now run from project root: flutter pub run flutter_launcher_icons');
|
|
}
|
|
|
|
/// Generate an icon with a checkmark design
|
|
img.Image generateIcon(int size, {required bool withBackground}) {
|
|
final image = img.Image(width: size, height: size);
|
|
|
|
final center = size / 2;
|
|
final radius = size * 0.42;
|
|
|
|
// Colors - Material Purple
|
|
final purple = img.ColorRgba8(103, 80, 164, 255); // #6750A4
|
|
final white = img.ColorRgba8(255, 255, 255, 255);
|
|
final transparent = img.ColorRgba8(0, 0, 0, 0);
|
|
|
|
// Checkmark stroke width
|
|
final checkStroke = size * 0.09;
|
|
|
|
// Checkmark points - classic check shape
|
|
// Point 1: Start of short leg (left side)
|
|
final p1x = center - radius * 0.40;
|
|
final p1y = center + radius * 0.05;
|
|
|
|
// Point 2: Corner/bottom of check
|
|
final p2x = center - radius * 0.05;
|
|
final p2y = center + radius * 0.40;
|
|
|
|
// Point 3: End of long leg (top right)
|
|
final p3x = center + radius * 0.50;
|
|
final p3y = center - radius * 0.35;
|
|
|
|
// Fill image
|
|
for (int y = 0; y < size; y++) {
|
|
for (int x = 0; x < size; x++) {
|
|
final dx = x - center;
|
|
final dy = y - center;
|
|
final distance = sqrt(dx * dx + dy * dy);
|
|
|
|
img.Color pixelColor = transparent;
|
|
|
|
if (withBackground) {
|
|
// Draw filled purple circle
|
|
if (distance <= radius) {
|
|
pixelColor = purple;
|
|
}
|
|
|
|
// Draw white checkmark on top
|
|
final dist1 = distanceToSegment(x.toDouble(), y.toDouble(), p1x, p1y, p2x, p2y);
|
|
final dist2 = distanceToSegment(x.toDouble(), y.toDouble(), p2x, p2y, p3x, p3y);
|
|
|
|
if (dist1 <= checkStroke || dist2 <= checkStroke) {
|
|
pixelColor = white;
|
|
}
|
|
} else {
|
|
// Foreground only - purple circle outline and checkmark
|
|
final ringOuter = radius;
|
|
final ringInner = radius * 0.88;
|
|
|
|
// Circle outline
|
|
if (distance <= ringOuter && distance >= ringInner) {
|
|
pixelColor = purple;
|
|
}
|
|
|
|
// Purple checkmark
|
|
final dist1 = distanceToSegment(x.toDouble(), y.toDouble(), p1x, p1y, p2x, p2y);
|
|
final dist2 = distanceToSegment(x.toDouble(), y.toDouble(), p2x, p2y, p3x, p3y);
|
|
|
|
if (dist1 <= checkStroke || dist2 <= checkStroke) {
|
|
pixelColor = purple;
|
|
}
|
|
}
|
|
|
|
image.setPixel(x, y, pixelColor);
|
|
}
|
|
}
|
|
|
|
return image;
|
|
}
|
|
|
|
/// Calculate distance from point (px, py) to line segment (x1,y1)-(x2,y2)
|
|
double distanceToSegment(double px, double py, double x1, double y1, double x2, double y2) {
|
|
final dx = x2 - x1;
|
|
final dy = y2 - y1;
|
|
final lengthSq = dx * dx + dy * dy;
|
|
|
|
if (lengthSq == 0) {
|
|
return sqrt((px - x1) * (px - x1) + (py - y1) * (py - y1));
|
|
}
|
|
|
|
var t = ((px - x1) * dx + (py - y1) * dy) / lengthSq;
|
|
t = t.clamp(0.0, 1.0);
|
|
|
|
final nearestX = x1 + t * dx;
|
|
final nearestY = y1 + t * dy;
|
|
|
|
return sqrt((px - nearestX) * (px - nearestX) + (py - nearestY) * (py - nearestY));
|
|
}
|