mirror of
https://github.com/immich-app/immich
synced 2026-08-15 13:03:57 +00:00
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:
parent
652ef8a427
commit
190a939af7
7 changed files with 95 additions and 3 deletions
|
|
@ -132,6 +132,8 @@ class HeaderKeyValueSettings extends StatelessWidget {
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
),
|
),
|
||||||
autocorrect: false,
|
autocorrect: false,
|
||||||
|
smartDashesType: .disabled,
|
||||||
|
smartQuotesType: .disabled,
|
||||||
onChanged: (headerKey) {
|
onChanged: (headerKey) {
|
||||||
header.key = headerKey;
|
header.key = headerKey;
|
||||||
},
|
},
|
||||||
|
|
@ -160,6 +162,8 @@ class HeaderKeyValueSettings extends StatelessWidget {
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
),
|
),
|
||||||
autocorrect: false,
|
autocorrect: false,
|
||||||
|
smartDashesType: .disabled,
|
||||||
|
smartQuotesType: .disabled,
|
||||||
onChanged: (headerValue) {
|
onChanged: (headerValue) {
|
||||||
header.value = headerValue;
|
header.value = headerValue;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -493,14 +493,12 @@ class LoginForm extends HookConsumerWidget {
|
||||||
builder: (context, form) => Column(
|
builder: (context, form) => Column(
|
||||||
spacing: ImmichSpacing.md,
|
spacing: ImmichSpacing.md,
|
||||||
children: [
|
children: [
|
||||||
ImmichTextInput(
|
ImmichEmailInput(
|
||||||
controller: emailController,
|
controller: emailController,
|
||||||
label: context.t.email,
|
label: context.t.email,
|
||||||
hintText: context.t.login_form_email_hint,
|
hintText: context.t.login_form_email_hint,
|
||||||
validator: _validateEmail,
|
validator: _validateEmail,
|
||||||
keyboardAction: TextInputAction.next,
|
keyboardAction: TextInputAction.next,
|
||||||
keyboardType: TextInputType.emailAddress,
|
|
||||||
autofillHints: const [AutofillHints.email],
|
|
||||||
onSubmit: (_) => passwordFocusNode.requestFocus(),
|
onSubmit: (_) => passwordFocusNode.requestFocus(),
|
||||||
),
|
),
|
||||||
ImmichPasswordInput(
|
ImmichPasswordInput(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
export 'src/color_override.dart';
|
export 'src/color_override.dart';
|
||||||
export 'src/components/close_button.dart';
|
export 'src/components/close_button.dart';
|
||||||
export 'src/components/column_button.dart';
|
export 'src/components/column_button.dart';
|
||||||
|
export 'src/components/email_input.dart';
|
||||||
export 'src/components/form.dart';
|
export 'src/components/form.dart';
|
||||||
export 'src/components/formatted_text.dart';
|
export 'src/components/formatted_text.dart';
|
||||||
export 'src/components/icon_button.dart';
|
export 'src/components/icon_button.dart';
|
||||||
|
|
|
||||||
26
mobile/packages/ui/lib/src/components/email_input.dart
Normal file
26
mobile/packages/ui/lib/src/components/email_input.dart
Normal 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -47,6 +47,9 @@ class _ImmichPasswordInputState extends State<ImmichPasswordInput> {
|
||||||
onSubmit: widget.onSubmit,
|
onSubmit: widget.onSubmit,
|
||||||
keyboardAction: widget.keyboardAction,
|
keyboardAction: widget.keyboardAction,
|
||||||
obscureText: !_visible,
|
obscureText: !_visible,
|
||||||
|
autocorrect: false,
|
||||||
|
smartDashesType: .disabled,
|
||||||
|
smartQuotesType: .disabled,
|
||||||
suffixIcon: IconButton(
|
suffixIcon: IconButton(
|
||||||
onPressed: _toggleVisibility,
|
onPressed: _toggleVisibility,
|
||||||
icon: Icon(_visible ? Icons.visibility_off_rounded : Icons.visibility_rounded),
|
icon: Icon(_visible ? Icons.visibility_off_rounded : Icons.visibility_rounded),
|
||||||
|
|
|
||||||
28
mobile/packages/ui/lib/src/previews/email_input.dart
Normal file
28
mobile/packages/ui/lib/src/previews/email_input.dart
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
32
mobile/packages/ui/test/smart_punctuation_test.dart
Normal file
32
mobile/packages/ui/test/smart_punctuation_test.dart
Normal 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);
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue