fix(mobile): disable iOS smart quotes/dashes in email/password inputs (#30767)

* fix(mobile): disable iOS smart quotes/dashes in email/password inputs

* Remove enum prefixes
This commit is contained in:
Adam Gastineau 2026-08-14 12:21:39 -07:00 committed by GitHub
parent 652ef8a427
commit 190a939af7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 95 additions and 3 deletions

View file

@ -132,6 +132,8 @@ class HeaderKeyValueSettings extends StatelessWidget {
border: const OutlineInputBorder(),
),
autocorrect: false,
smartDashesType: .disabled,
smartQuotesType: .disabled,
onChanged: (headerKey) {
header.key = headerKey;
},
@ -160,6 +162,8 @@ class HeaderKeyValueSettings extends StatelessWidget {
border: const OutlineInputBorder(),
),
autocorrect: false,
smartDashesType: .disabled,
smartQuotesType: .disabled,
onChanged: (headerValue) {
header.value = headerValue;
},

View file

@ -493,14 +493,12 @@ class LoginForm extends HookConsumerWidget {
builder: (context, form) => Column(
spacing: ImmichSpacing.md,
children: [
ImmichTextInput(
ImmichEmailInput(
controller: emailController,
label: context.t.email,
hintText: context.t.login_form_email_hint,
validator: _validateEmail,
keyboardAction: TextInputAction.next,
keyboardType: TextInputType.emailAddress,
autofillHints: const [AutofillHints.email],
onSubmit: (_) => passwordFocusNode.requestFocus(),
),
ImmichPasswordInput(

View file

@ -1,6 +1,7 @@
export 'src/color_override.dart';
export 'src/components/close_button.dart';
export 'src/components/column_button.dart';
export 'src/components/email_input.dart';
export 'src/components/form.dart';
export 'src/components/formatted_text.dart';
export 'src/components/icon_button.dart';

View file

@ -0,0 +1,26 @@
import 'package:flutter/services.dart';
import 'package:immich_ui/src/components/text_input.dart';
/// An ImmichTextInput customized for receiving email addresses
class ImmichEmailInput extends ImmichTextInput {
const ImmichEmailInput({
super.key,
super.controller,
super.focusNode,
super.label,
super.hintText,
super.validator,
super.onSubmit,
super.keyboardAction,
super.suffixIcon,
super.enabled,
super.autofocus,
super.autovalidateMode,
}) : super(
keyboardType: .emailAddress,
autofillHints: const [AutofillHints.email],
autocorrect: false,
smartDashesType: .disabled,
smartQuotesType: .disabled,
);
}

View file

@ -47,6 +47,9 @@ class _ImmichPasswordInputState extends State<ImmichPasswordInput> {
onSubmit: widget.onSubmit,
keyboardAction: widget.keyboardAction,
obscureText: !_visible,
autocorrect: false,
smartDashesType: .disabled,
smartQuotesType: .disabled,
suffixIcon: IconButton(
onPressed: _toggleVisibility,
icon: Icon(_visible ? Icons.visibility_off_rounded : Icons.visibility_rounded),

View file

@ -0,0 +1,28 @@
import 'package:flutter/material.dart';
import 'package:immich_ui/src/components/email_input.dart';
import 'package:immich_ui/src/previews.dart';
@ImmichPreview(group: 'EmailInput', name: 'Basic')
Widget previewEmailInput() => const _PreviewEmailInput();
class _PreviewEmailInput extends StatefulWidget {
const _PreviewEmailInput();
@override
State<_PreviewEmailInput> createState() => _PreviewEmailInputState();
}
class _PreviewEmailInputState extends State<_PreviewEmailInput> {
final _controller = TextEditingController();
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ImmichEmailInput(label: 'Email', hintText: 'user@immich.app', controller: _controller);
}
}

View file

@ -0,0 +1,32 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:immich_ui/src/components/email_input.dart';
import 'package:immich_ui/src/components/password_input.dart';
import 'test_utils.dart';
void main() {
EditableText editable(WidgetTester tester) => tester.widget<EditableText>(find.byType(EditableText));
testWidgets('ImmichEmailInput disables smart punctuation', (tester) async {
await tester.pumpTestWidget(const ImmichEmailInput());
expect(editable(tester).smartDashesType, SmartDashesType.disabled);
expect(editable(tester).smartQuotesType, SmartQuotesType.disabled);
});
testWidgets('ImmichPasswordInput disables smart punctuation', (tester) async {
await tester.pumpTestWidget(const ImmichPasswordInput());
expect(editable(tester).obscureText, isTrue);
expect(editable(tester).smartDashesType, SmartDashesType.disabled);
expect(editable(tester).smartQuotesType, SmartQuotesType.disabled);
await tester.tap(find.byIcon(Icons.visibility_rounded));
await tester.pump();
expect(editable(tester).obscureText, isFalse);
expect(editable(tester).smartDashesType, SmartDashesType.disabled);
expect(editable(tester).smartQuotesType, SmartQuotesType.disabled);
});
}