mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-04 03:27:09 -05:00 
			
		
		
		
	* chore: bump dart sdk to 3.8 * chore: make build * make pigeon * chore: format files --------- Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
		
			
				
	
	
		
			103 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			103 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
import 'package:flutter/material.dart';
 | 
						|
import 'package:flutter_hooks/flutter_hooks.dart';
 | 
						|
import 'package:immich_mobile/widgets/common/immich_logo.dart';
 | 
						|
 | 
						|
class ImmichLoadingIndicator extends HookWidget {
 | 
						|
  final double? borderRadius;
 | 
						|
 | 
						|
  const ImmichLoadingIndicator({super.key, this.borderRadius});
 | 
						|
 | 
						|
  @override
 | 
						|
  Widget build(BuildContext context) {
 | 
						|
    final logoAnimationController = useAnimationController(duration: const Duration(seconds: 6))
 | 
						|
      ..reverse()
 | 
						|
      ..repeat();
 | 
						|
 | 
						|
    final borderAnimationController = useAnimationController(duration: const Duration(seconds: 6))..repeat();
 | 
						|
 | 
						|
    return Container(
 | 
						|
      height: 80,
 | 
						|
      width: 80,
 | 
						|
      decoration: BoxDecoration(
 | 
						|
        color: Colors.transparent,
 | 
						|
        borderRadius: BorderRadius.circular(borderRadius ?? 50),
 | 
						|
        backgroundBlendMode: BlendMode.luminosity,
 | 
						|
      ),
 | 
						|
      child: AnimatedBuilder(
 | 
						|
        animation: borderAnimationController,
 | 
						|
        builder: (context, child) {
 | 
						|
          return CustomPaint(
 | 
						|
            painter: GradientBorderPainter(animation: borderAnimationController.value, strokeWidth: 3),
 | 
						|
            child: child,
 | 
						|
          );
 | 
						|
        },
 | 
						|
        child: Padding(
 | 
						|
          padding: const EdgeInsets.all(15),
 | 
						|
          child: RotationTransition(
 | 
						|
            turns: logoAnimationController,
 | 
						|
            child: const ImmichLogo(heroTag: 'logo'),
 | 
						|
          ),
 | 
						|
        ),
 | 
						|
      ),
 | 
						|
    );
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class GradientBorderPainter extends CustomPainter {
 | 
						|
  final double animation;
 | 
						|
  final double strokeWidth;
 | 
						|
  final double opacity = 0.7;
 | 
						|
  final colors = [
 | 
						|
    const Color(0xFFFA2921),
 | 
						|
    const Color(0xFFED79B5),
 | 
						|
    const Color(0xFFFFB400),
 | 
						|
    const Color(0xFF1E83F7),
 | 
						|
    const Color(0xFF18C249),
 | 
						|
  ];
 | 
						|
 | 
						|
  GradientBorderPainter({required this.animation, required this.strokeWidth});
 | 
						|
 | 
						|
  @override
 | 
						|
  void paint(Canvas canvas, Size size) {
 | 
						|
    final center = Offset(size.width / 2, size.height / 2);
 | 
						|
    final radius = min(size.width, size.height) / 2 - strokeWidth / 2;
 | 
						|
 | 
						|
    // Create a sweep gradient that covers the entire circle
 | 
						|
    final Rect rect = Rect.fromCircle(center: center, radius: radius);
 | 
						|
 | 
						|
    // Create a paint with the gradient
 | 
						|
    final paint = Paint()
 | 
						|
      ..style = PaintingStyle.stroke
 | 
						|
      ..strokeWidth = strokeWidth;
 | 
						|
 | 
						|
    // Create a gradient that smoothly transitions between colors
 | 
						|
    final shader = SweepGradient(
 | 
						|
      // Use a fixed starting point and let matrix transformation handle rotation
 | 
						|
      startAngle: 0,
 | 
						|
      endAngle: 2 * 3.14159,
 | 
						|
      colors: [
 | 
						|
        // Repeat colors to ensure smooth transitions
 | 
						|
        ...colors.map((c) => c.withValues(alpha: opacity)),
 | 
						|
        colors.first.withValues(alpha: opacity),
 | 
						|
      ],
 | 
						|
      // Add evenly distributed stops
 | 
						|
      stops: List.generate(colors.length + 1, (index) => index / colors.length),
 | 
						|
      tileMode: TileMode.clamp,
 | 
						|
      // Use transformations to rotate the gradient
 | 
						|
      transform: GradientRotation(-animation * 2 * 3.14159),
 | 
						|
    ).createShader(rect);
 | 
						|
 | 
						|
    paint.shader = shader;
 | 
						|
 | 
						|
    // Draw the circular border
 | 
						|
    canvas.drawCircle(center, radius, paint);
 | 
						|
  }
 | 
						|
 | 
						|
  @override
 | 
						|
  bool shouldRepaint(GradientBorderPainter oldDelegate) {
 | 
						|
    return animation != oldDelegate.animation;
 | 
						|
  }
 | 
						|
 | 
						|
  double min(double a, double b) => a < b ? a : b;
 | 
						|
}
 |