chore: bump dart sdk to 3.8 (#20355)

* 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>
This commit is contained in:
shenlong 2025-07-29 00:34:03 +05:30 committed by GitHub
parent 9b3718120b
commit e52b9d15b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
643 changed files with 32561 additions and 35292 deletions

View file

@ -33,25 +33,13 @@ class ChangePasswordForm extends HookConsumerWidget {
children: [
Text(
'change_password'.tr(),
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: context.primaryColor,
),
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold, color: context.primaryColor),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 24.0),
child: Text(
'change_password_form_description'.tr(
namedArgs: {
'name': authState.name,
},
),
style: TextStyle(
fontSize: 14,
color: context.colorScheme.onSurface,
fontWeight: FontWeight.w600,
),
'change_password_form_description'.tr(namedArgs: {'name': authState.name}),
style: TextStyle(fontSize: 14, color: context.colorScheme.onSurface, fontWeight: FontWeight.w600),
),
),
Form(
@ -70,8 +58,9 @@ class ChangePasswordForm extends HookConsumerWidget {
passwordController: passwordController,
onPressed: () async {
if (formKey.currentState!.validate()) {
var isSuccess =
await ref.read(authProvider.notifier).changePassword(passwordController.value.text);
var isSuccess = await ref
.read(authProvider.notifier)
.changePassword(passwordController.value.text);
if (isSuccess) {
await ref.read(authProvider.notifier).logout();
@ -139,11 +128,7 @@ class ConfirmPasswordInput extends StatelessWidget {
final TextEditingController originalController;
final TextEditingController confirmController;
const ConfirmPasswordInput({
super.key,
required this.originalController,
required this.confirmController,
});
const ConfirmPasswordInput({super.key, required this.originalController, required this.confirmController});
String? _validateInput(String? email) {
if (confirmController.value != originalController.value) {
@ -171,11 +156,7 @@ class ConfirmPasswordInput extends StatelessWidget {
class ChangePasswordButton extends ConsumerWidget {
final TextEditingController passwordController;
final VoidCallback onPressed;
const ChangePasswordButton({
super.key,
required this.passwordController,
required this.onPressed,
});
const ChangePasswordButton({super.key, required this.passwordController, required this.onPressed});
@override
Widget build(BuildContext context, WidgetRef ref) {
@ -185,10 +166,7 @@ class ChangePasswordButton extends ConsumerWidget {
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 25),
),
onPressed: onPressed,
child: Text(
'change_password'.tr(),
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
),
child: Text('change_password'.tr(), style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
);
}
}

View file

@ -6,12 +6,7 @@ class EmailInput extends StatelessWidget {
final FocusNode? focusNode;
final Function()? onSubmit;
const EmailInput({
super.key,
required this.controller,
this.focusNode,
this.onSubmit,
});
const EmailInput({super.key, required this.controller, this.focusNode, this.onSubmit});
String? _validateInput(String? email) {
if (email == null || email == '') return null;
@ -32,10 +27,7 @@ class EmailInput extends StatelessWidget {
labelText: 'email'.tr(),
border: const OutlineInputBorder(),
hintText: 'login_form_email_hint'.tr(),
hintStyle: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 14,
),
hintStyle: const TextStyle(fontWeight: FontWeight.normal, fontSize: 14),
),
validator: _validateInput,
autovalidateMode: AutovalidateMode.always,

View file

@ -7,15 +7,7 @@ class LoadingIcon extends StatelessWidget {
Widget build(BuildContext context) {
return const Padding(
padding: EdgeInsets.only(top: 18.0),
child: SizedBox(
width: 24,
height: 24,
child: FittedBox(
child: CircularProgressIndicator(
strokeWidth: 2,
),
),
),
child: SizedBox(width: 24, height: 24, child: FittedBox(child: CircularProgressIndicator(strokeWidth: 2))),
);
}
}

View file

@ -5,23 +5,15 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
class LoginButton extends ConsumerWidget {
final Function() onPressed;
const LoginButton({
super.key,
required this.onPressed,
});
const LoginButton({super.key, required this.onPressed});
@override
Widget build(BuildContext context, WidgetRef ref) {
return ElevatedButton.icon(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
),
style: ElevatedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12)),
onPressed: onPressed,
icon: const Icon(Icons.login_rounded),
label: const Text(
"login",
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
).tr(),
label: const Text("login", style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)).tr(),
);
}
}

View file

@ -54,9 +54,7 @@ class LoginForm extends HookConsumerWidget {
final isOauthEnable = useState<bool>(false);
final isPasswordLoginEnable = useState<bool>(false);
final oAuthButtonLabel = useState<String>('OAuth');
final logoAnimationController = useAnimationController(
duration: const Duration(seconds: 60),
)..repeat();
final logoAnimationController = useAnimationController(duration: const Duration(seconds: 60))..repeat();
final serverInfo = ref.watch(serverInfoProvider);
final warningMessage = useState<String?>(null);
final loginFormKey = GlobalKey<FormState>();
@ -90,11 +88,7 @@ class LoginForm extends HookConsumerWidget {
// Guard empty URL
if (serverUrl.isEmpty) {
ImmichToast.show(
context: context,
msg: "login_form_server_empty".tr(),
toastType: ToastType.error,
);
ImmichToast.show(context: context, msg: "login_form_server_empty".tr(), toastType: ToastType.error);
}
try {
@ -148,16 +142,13 @@ class LoginForm extends HookConsumerWidget {
isLoadingServer.value = false;
}
useEffect(
() {
final serverUrl = getServerUrl();
if (serverUrl != null) {
serverEndpointController.text = serverUrl;
}
return null;
},
[],
);
useEffect(() {
final serverUrl = getServerUrl();
if (serverUrl != null) {
serverEndpointController.text = serverUrl;
}
return null;
}, []);
populateTestLoginInfo() {
emailController.text = 'demo@immich.app';
@ -180,10 +171,7 @@ class LoginForm extends HookConsumerWidget {
invalidateAllApiRepositoryProviders(ref);
try {
final result = await ref.read(authProvider.notifier).login(
emailController.text,
passwordController.text,
);
final result = await ref.read(authProvider.notifier).login(emailController.text, passwordController.text);
if (result.shouldChangePassword && !result.isAdmin) {
context.pushRoute(const ChangePasswordRoute());
@ -212,12 +200,7 @@ class LoginForm extends HookConsumerWidget {
String generateRandomString(int length) {
const chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890';
final random = Random.secure();
return String.fromCharCodes(
Iterable.generate(
length,
(_) => chars.codeUnitAt(random.nextInt(chars.length)),
),
);
return String.fromCharCodes(Iterable.generate(length, (_) => chars.codeUnitAt(random.nextInt(chars.length))));
}
List<int> randomBytes(int length) {
@ -273,23 +256,17 @@ class LoginForm extends HookConsumerWidget {
if (oAuthServerUrl != null) {
try {
final loginResponseDto = await oAuthService.oAuthLogin(
oAuthServerUrl,
state,
codeVerifier,
);
final loginResponseDto = await oAuthService.oAuthLogin(oAuthServerUrl, state, codeVerifier);
if (loginResponseDto == null) {
return;
}
log.info(
"Finished OAuth login with response: ${loginResponseDto.userEmail}",
);
log.info("Finished OAuth login with response: ${loginResponseDto.userEmail}");
final isSuccess = await ref.watch(authProvider.notifier).saveAuthInfo(
accessToken: loginResponseDto.accessToken,
);
final isSuccess = await ref
.watch(authProvider.notifier)
.saveAuthInfo(accessToken: loginResponseDto.accessToken);
if (isSuccess) {
isLoading.value = false;
@ -374,10 +351,7 @@ class LoginForm extends HookConsumerWidget {
),
onPressed: isLoadingServer.value ? null : getServerAuthSettings,
icon: const Icon(Icons.arrow_forward_rounded),
label: const Text(
'next',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
).tr(),
label: const Text('next', style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold)).tr(),
),
),
],
@ -401,17 +375,10 @@ class LoginForm extends HookConsumerWidget {
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: context.isDarkTheme ? Colors.red.shade700 : Colors.red.shade100,
borderRadius: const BorderRadius.all(
Radius.circular(8),
),
border: Border.all(
color: context.isDarkTheme ? Colors.red.shade900 : Colors.red[200]!,
),
),
child: Text(
warningMessage.value!,
textAlign: TextAlign.center,
borderRadius: const BorderRadius.all(Radius.circular(8)),
border: Border.all(color: context.isDarkTheme ? Colors.red.shade900 : Colors.red[200]!),
),
child: Text(warningMessage.value!, textAlign: TextAlign.center),
),
);
}
@ -435,11 +402,7 @@ class LoginForm extends HookConsumerWidget {
onSubmit: passwordFocusNode.requestFocus,
),
const SizedBox(height: 8),
PasswordInput(
controller: passwordController,
focusNode: passwordFocusNode,
onSubmit: login,
),
PasswordInput(controller: passwordController, focusNode: passwordFocusNode, onSubmit: login),
],
// Note: This used to have an AnimatedSwitcher, but was removed
@ -455,12 +418,8 @@ class LoginForm extends HookConsumerWidget {
if (isOauthEnable.value) ...[
if (isPasswordLoginEnable.value)
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
),
child: Divider(
color: context.isDarkTheme ? Colors.white : Colors.black,
),
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Divider(color: context.isDarkTheme ? Colors.white : Colors.black),
),
OAuthLoginButton(
serverEndpointController: serverEndpointController,
@ -471,10 +430,7 @@ class LoginForm extends HookConsumerWidget {
],
],
),
if (!isOauthEnable.value && !isPasswordLoginEnable.value)
Center(
child: const Text('login_disabled').tr(),
),
if (!isOauthEnable.value && !isPasswordLoginEnable.value) Center(child: const Text('login_disabled').tr()),
const SizedBox(height: 12),
TextButton.icon(
icon: const Icon(Icons.arrow_back),
@ -498,9 +454,7 @@ class LoginForm extends HookConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: constraints.maxHeight / 5,
),
SizedBox(height: constraints.maxHeight / 5),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
@ -510,24 +464,16 @@ class LoginForm extends HookConsumerWidget {
onLongPress: () => populateTestLoginInfo1(),
child: RotationTransition(
turns: logoAnimationController,
child: const ImmichLogo(
heroTag: 'logo',
),
child: const ImmichLogo(heroTag: 'logo'),
),
),
const Padding(
padding: EdgeInsets.only(top: 8.0, bottom: 16),
child: ImmichTitleText(),
),
const Padding(padding: EdgeInsets.only(top: 8.0, bottom: 16), child: ImmichTitleText()),
],
),
// Note: This used to have an AnimatedSwitcher, but was removed
// because of https://github.com/flutter/flutter/issues/120874
Form(
key: loginFormKey,
child: serverSelectionOrLogin,
),
Form(key: loginFormKey, child: serverSelectionOrLogin),
],
),
),

View file

@ -25,10 +25,7 @@ class OAuthLoginButton extends ConsumerWidget {
),
onPressed: onPressed,
icon: const Icon(Icons.pin_rounded),
label: Text(
buttonLabel,
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
),
label: Text(buttonLabel, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold)),
);
}
}

View file

@ -8,12 +8,7 @@ class PasswordInput extends HookConsumerWidget {
final FocusNode? focusNode;
final Function()? onSubmit;
const PasswordInput({
super.key,
required this.controller,
this.focusNode,
this.onSubmit,
});
const PasswordInput({super.key, required this.controller, this.focusNode, this.onSubmit});
@override
Widget build(BuildContext context, WidgetRef ref) {
@ -26,15 +21,10 @@ class PasswordInput extends HookConsumerWidget {
labelText: 'password'.tr(),
border: const OutlineInputBorder(),
hintText: 'login_form_password_hint'.tr(),
hintStyle: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 14,
),
hintStyle: const TextStyle(fontWeight: FontWeight.normal, fontSize: 14),
suffixIcon: IconButton(
onPressed: () => isPasswordVisible.value = !isPasswordVisible.value,
icon: Icon(
isPasswordVisible.value ? Icons.visibility_off_sharp : Icons.visibility_sharp,
),
icon: Icon(isPasswordVisible.value ? Icons.visibility_off_sharp : Icons.visibility_sharp),
),
),
autofillHints: const [AutofillHints.password],

View file

@ -7,12 +7,7 @@ class ServerEndpointInput extends StatelessWidget {
final FocusNode focusNode;
final Function()? onSubmit;
const ServerEndpointInput({
super.key,
required this.controller,
required this.focusNode,
this.onSubmit,
});
const ServerEndpointInput({super.key, required this.controller, required this.focusNode, this.onSubmit});
String? _validateInput(String? url) {
if (url == null || url.isEmpty) return null;

View file

@ -43,11 +43,7 @@ class PinInput extends StatelessWidget {
final defaultPinTheme = PinTheme(
width: getPinSize().width,
height: getPinSize().height,
textStyle: TextStyle(
fontSize: 24,
color: context.colorScheme.onSurface,
fontFamily: 'Overpass Mono',
),
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),
@ -70,34 +66,19 @@ class PinInput extends StatelessWidget {
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,
),
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,
),
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,
),
border: Border.all(color: context.primaryColor.withValues(alpha: 0.5), width: 2),
color: context.colorScheme.surfaceContainerHigh,
),
),
@ -105,10 +86,7 @@ class PinInput extends StatelessWidget {
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,
),
border: Border.all(color: context.colorScheme.error.withAlpha(100), width: 2),
),
),
pinputAutovalidateMode: PinputAutovalidateMode.onSubmit,

View file

@ -9,10 +9,7 @@ import 'package:immich_mobile/widgets/forms/pin_input.dart';
class PinRegistrationForm extends HookConsumerWidget {
final Function() onDone;
const PinRegistrationForm({
super.key,
required this.onDone,
});
const PinRegistrationForm({super.key, required this.onDone});
@override
Widget build(BuildContext context, WidgetRef ref) {
@ -40,35 +37,25 @@ class PinRegistrationForm extends HookConsumerWidget {
}
try {
await ref.read(authProvider.notifier).setupPinCode(
newPinCodeController.text,
);
await ref.read(authProvider.notifier).setupPinCode(newPinCodeController.text);
onDone();
} catch (error) {
hasError.value = true;
context.showSnackBar(
SnackBar(content: Text(error.toString())),
);
context.showSnackBar(SnackBar(content: Text(error.toString())));
}
}
return Form(
child: Column(
children: [
Icon(
Icons.pin_outlined,
size: 64,
color: context.primaryColor,
),
Icon(Icons.pin_outlined, size: 64, color: context.primaryColor),
const SizedBox(height: 32),
SizedBox(
width: context.width * 0.7,
child: Text(
'setup_pin_code'.tr(),
style: context.textTheme.labelLarge!.copyWith(
fontSize: 24,
),
style: context.textTheme.labelLarge!.copyWith(fontSize: 24),
textAlign: TextAlign.center,
),
),
@ -76,9 +63,7 @@ class PinRegistrationForm extends HookConsumerWidget {
width: context.width * 0.8,
child: Text(
'new_pin_code_subtitle'.tr(),
style: context.textTheme.bodyLarge!.copyWith(
fontSize: 16,
),
style: context.textTheme.bodyLarge!.copyWith(fontSize: 16),
textAlign: TextAlign.center,
),
),
@ -113,10 +98,7 @@ class PinRegistrationForm extends HookConsumerWidget {
child: Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: createNewPinCode,
child: Text('create'.tr()),
),
child: ElevatedButton(onPressed: createNewPinCode, child: Text('create'.tr())),
),
],
),

View file

@ -49,11 +49,7 @@ class PinVerificationForm extends HookConsumerWidget {
AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
child: isVerified.value
? Icon(
successIcon ?? Icons.lock_open_rounded,
size: 64,
color: Colors.green[300],
)
? Icon(successIcon ?? Icons.lock_open_rounded, size: 64, color: Colors.green[300])
: Icon(
icon ?? Icons.lock_outline_rounded,
size: 64,
@ -65,9 +61,7 @@ class PinVerificationForm extends HookConsumerWidget {
width: context.width * 0.7,
child: Text(
description ?? 'enter_your_pin_code_subtitle'.tr(),
style: context.textTheme.labelLarge!.copyWith(
fontSize: 18,
),
style: context.textTheme.labelLarge!.copyWith(fontSize: 18),
textAlign: TextAlign.center,
),
),