mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-31 10:37:11 -04: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>
		
			
				
	
	
		
			101 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			101 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'package:flutter/material.dart';
 | |
| import 'package:immich_mobile/extensions/build_context_extensions.dart';
 | |
| import 'package:pinput/pinput.dart';
 | |
| 
 | |
| class PinInput extends StatelessWidget {
 | |
|   final Function(String)? onCompleted;
 | |
|   final Function(String)? onChanged;
 | |
|   final int? length;
 | |
|   final bool? obscureText;
 | |
|   final bool? autoFocus;
 | |
|   final bool? hasError;
 | |
|   final String? label;
 | |
|   final TextEditingController? controller;
 | |
| 
 | |
|   const PinInput({
 | |
|     super.key,
 | |
|     this.onCompleted,
 | |
|     this.onChanged,
 | |
|     this.length,
 | |
|     this.obscureText,
 | |
|     this.autoFocus,
 | |
|     this.hasError,
 | |
|     this.label,
 | |
|     this.controller,
 | |
|   });
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     getPinSize() {
 | |
|       final minimumPadding = 18.0;
 | |
|       final gapWidth = 3.0;
 | |
|       final screenWidth = context.width;
 | |
|       final pinWidth = (screenWidth - (minimumPadding * 2) - (gapWidth * 5)) / (length ?? 6);
 | |
| 
 | |
|       if (pinWidth > 60) {
 | |
|         return const Size(60, 64);
 | |
|       }
 | |
| 
 | |
|       final pinHeight = pinWidth / (60 / 64);
 | |
|       return Size(pinWidth, pinHeight);
 | |
|     }
 | |
| 
 | |
|     final defaultPinTheme = PinTheme(
 | |
|       width: getPinSize().width,
 | |
|       height: getPinSize().height,
 | |
|       textStyle: TextStyle(fontSize: 24, color: context.colorScheme.onSurface, fontFamily: 'Overpass Mono'),
 | |
|       decoration: BoxDecoration(
 | |
|         borderRadius: const BorderRadius.all(Radius.circular(19)),
 | |
|         border: Border.all(color: context.colorScheme.surfaceBright),
 | |
|         color: context.colorScheme.surfaceContainerHigh,
 | |
|       ),
 | |
|     );
 | |
| 
 | |
|     return Column(
 | |
|       crossAxisAlignment: CrossAxisAlignment.start,
 | |
|       children: [
 | |
|         if (label != null) ...[
 | |
|           Text(
 | |
|             label!,
 | |
|             style: context.textTheme.displayLarge?.copyWith(color: context.colorScheme.onSurface.withAlpha(200)),
 | |
|           ),
 | |
|           const SizedBox(height: 4),
 | |
|         ],
 | |
|         Pinput(
 | |
|           controller: controller,
 | |
|           forceErrorState: hasError ?? false,
 | |
|           autofocus: autoFocus ?? false,
 | |
|           obscureText: obscureText ?? false,
 | |
|           obscuringWidget: Icon(Icons.vpn_key_rounded, color: context.primaryColor, size: 20),
 | |
|           separatorBuilder: (index) => const SizedBox(height: 64, width: 3),
 | |
|           cursor: Column(
 | |
|             mainAxisAlignment: MainAxisAlignment.end,
 | |
|             children: [
 | |
|               Container(margin: const EdgeInsets.only(bottom: 9), width: 18, height: 2, color: context.primaryColor),
 | |
|             ],
 | |
|           ),
 | |
|           defaultPinTheme: defaultPinTheme,
 | |
|           focusedPinTheme: defaultPinTheme.copyWith(
 | |
|             decoration: BoxDecoration(
 | |
|               borderRadius: const BorderRadius.all(Radius.circular(19)),
 | |
|               border: Border.all(color: context.primaryColor.withValues(alpha: 0.5), width: 2),
 | |
|               color: context.colorScheme.surfaceContainerHigh,
 | |
|             ),
 | |
|           ),
 | |
|           errorPinTheme: defaultPinTheme.copyWith(
 | |
|             decoration: BoxDecoration(
 | |
|               color: context.colorScheme.error.withAlpha(15),
 | |
|               borderRadius: const BorderRadius.all(Radius.circular(19)),
 | |
|               border: Border.all(color: context.colorScheme.error.withAlpha(100), width: 2),
 | |
|             ),
 | |
|           ),
 | |
|           pinputAutovalidateMode: PinputAutovalidateMode.onSubmit,
 | |
|           length: length ?? 6,
 | |
|           onChanged: onChanged,
 | |
|           onCompleted: onCompleted,
 | |
|         ),
 | |
|       ],
 | |
|     );
 | |
|   }
 | |
| }
 |