Skip to content

Commit e8c1c17

Browse files
authored
bfix: Fix textfield cursor position when typed fast.
2 parents fd886fc + 75f3db8 commit e8c1c17

18 files changed

Lines changed: 194 additions & 224 deletions

File tree

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ buildscript {
66
}
77

88
dependencies {
9-
classpath 'com.android.tools.build:gradle:4.1.0'
9+
classpath 'com.android.tools.build:gradle:7.0.2'
1010
classpath 'com.google.gms:google-services:4.3.8'
1111
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.7.1'
1212
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

android/gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip

lib/presentation/components/inputs/form_input.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ class FormInput extends StatelessWidget {
1818
this.maxLines = 1,
1919
this.obscureText = false,
2020
this.onChanged,
21+
this.onSubmitted,
22+
this.onEditingComplete,
2123
this.prefix,
2224
Key? key,
2325
}) : assert(
@@ -34,10 +36,12 @@ class FormInput extends StatelessWidget {
3436
final String title;
3537
final String? errorText;
3638
final Function(String)? onChanged;
39+
final Function(String)? onSubmitted;
3740
final TextInputAction action;
3841
final TextInputType? keyboard;
3942
final TextEditingController? controller;
4043
final Widget? prefix;
44+
final Function()? onEditingComplete;
4145

4246
@override
4347
Widget build(BuildContext context) {
@@ -65,6 +69,8 @@ class FormInput extends StatelessWidget {
6569
controller: enabled ? controller : null,
6670
prefix: prefix,
6771
errorText: errorText,
72+
onEditingComplete: onEditingComplete,
73+
onSubmitted: onSubmitted,
6874
),
6975
],
7076
);

lib/presentation/components/inputs/text_input.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class TextInput extends StatelessWidget {
2323
this.fillColor,
2424
this.border,
2525
this.onSubmitted,
26+
this.onEditingComplete,
2627
this.prefixIconConstraints,
2728
this.validator,
2829
Key? key,
@@ -49,6 +50,7 @@ class TextInput extends StatelessWidget {
4950
final InputBorder? border;
5051
final BoxConstraints? prefixIconConstraints;
5152
final String? Function(String?)? validator;
53+
final Function()? onEditingComplete;
5254

5355
@override
5456
Widget build(BuildContext context) {
@@ -83,6 +85,7 @@ class TextInput extends StatelessWidget {
8385
onChanged: onChanged,
8486
style: AppStyles.h6.copyWith(color: AppColors.grey3),
8587
textInputAction: action,
88+
onEditingComplete: onEditingComplete,
8689
onFieldSubmitted: onSubmitted,
8790
);
8891
}

lib/presentation/contests/widgets/contest_card.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,12 +290,12 @@ extension on Ongoing {
290290
String get platformName => PlatformUtil.getName(platform);
291291
String get icon => PlatformUtil.getIcon(platform);
292292
String get time =>
293-
'Ends on ${DateFormat('dd, MMMM yyyy hh:mm a').format(endTime)}';
293+
'Ends on ${DateFormat('dd MMMM, yyyy hh:mm a').format(endTime)}';
294294
}
295295

296296
extension on Upcoming {
297297
String get platformName => PlatformUtil.getName(platform);
298298
String get icon => PlatformUtil.getIcon(platform);
299299
String get time =>
300-
'Starts on ${DateFormat('dd, MMMM yyyy hh:mm a').format(startTime)}';
300+
'Starts on ${DateFormat('dd MMMM, yyyy hh:mm a').format(startTime)}';
301301
}

lib/presentation/login/bloc/login_bloc.dart

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
2929
if (!state.isFormFilled()) return;
3030

3131
emit(state.copyWith(
32-
isPasswordFocused: false,
33-
isUsernameFocused: false,
3432
status: const Status.loading(),
3533
));
3634

@@ -84,18 +82,10 @@ class LoginBloc extends Bloc<LoginEvent, LoginState> {
8482
}
8583

8684
void _updatePasswordInput(PasswordInput event, Emitter<LoginState> emit) {
87-
emit(state.copyWith(
88-
isPasswordFocused: true,
89-
isUsernameFocused: false,
90-
password: event.value,
91-
));
85+
emit(state.copyWith(password: event.value));
9286
}
9387

9488
void _updateUsernameInput(UsernameInput event, Emitter<LoginState> emit) {
95-
emit(state.copyWith(
96-
isUsernameFocused: true,
97-
isPasswordFocused: false,
98-
username: event.value,
99-
));
89+
emit(state.copyWith(username: event.value));
10090
}
10191
}

lib/presentation/login/bloc/login_state.dart

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,6 @@ part of 'login_bloc.dart';
66
class LoginState with _$LoginState {
77
/// State class for [LoginBloc].
88
const factory LoginState({
9-
/// Whether the username field is in focus.
10-
@Default(false) bool isUsernameFocused,
11-
12-
/// Whether the password field is in focus.
13-
@Default(false) bool isPasswordFocused,
14-
159
/// Whether the password field should be obscured.
1610
@Default(true) bool obscurePassword,
1711

lib/presentation/login/widgets/background_decoration.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ class BackgroundDecoration extends StatelessWidget {
1515
Positioned(
1616
top: 0,
1717
left: 0,
18-
child: SvgPicture.asset(
18+
child: svg.SvgPicture.asset(
1919
AppAssets.circle1,
2020
width: 170.r,
2121
),
2222
),
2323
Positioned(
2424
top: 80.r,
2525
right: 0,
26-
child: SvgPicture.asset(
26+
child: svg.SvgPicture.asset(
2727
AppAssets.triangle,
2828
width: 140.r,
2929
),

lib/presentation/login/widgets/login_widgets.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import 'package:flutter/gestures.dart';
22
import 'package:flutter/material.dart';
33
import 'package:flutter_bloc/flutter_bloc.dart';
44
import 'package:flutter_screenutil/flutter_screenutil.dart';
5-
import 'package:flutter_svg/flutter_svg.dart';
5+
import 'package:flutter_svg/flutter_svg.dart' as svg;
6+
import 'package:flutter_svg_provider/flutter_svg_provider.dart';
67
import 'package:get/get.dart';
78

89
import '../../../data/constants/assets.dart';

lib/presentation/login/widgets/text_fields.dart

Lines changed: 38 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7,45 +7,35 @@ class PasswordField extends StatelessWidget {
77

88
@override
99
Widget build(BuildContext context) {
10-
// [BlocSelector] is not used because widget depends on both
11-
// [state.isPasswordFocused] and [state.obscurePassword].
12-
return BlocBuilder<LoginBloc, LoginState>(
13-
builder: (context, state) {
14-
return Stack(
15-
alignment: Alignment.centerRight,
16-
children: <Widget>[
17-
TextInput(
18-
action: TextInputAction.done,
19-
hint: 'Password',
20-
keyboard: TextInputType.visiblePassword,
21-
obscureText: state.obscurePassword,
22-
onChanged: (value) =>
23-
context.read<LoginBloc>().add(PasswordInput(value)),
24-
prefix: Padding(
25-
padding: EdgeInsets.symmetric(
26-
horizontal: 8.r,
27-
vertical: 10.r,
28-
),
29-
child: SvgPicture.asset(
30-
AppAssets.lock,
31-
// TODO(BURG3R5): Deal with Focus transfer.
32-
color: (state.isPasswordFocused)
33-
? AppColors.primary
34-
: AppColors.grey1,
35-
),
36-
),
10+
return BlocSelector<LoginBloc, LoginState, bool>(
11+
selector: (state) => state.obscurePassword,
12+
builder: (context, obscurePassword) {
13+
return TextInput(
14+
action: TextInputAction.done,
15+
hint: 'Password',
16+
keyboard: TextInputType.visiblePassword,
17+
obscureText: obscurePassword,
18+
onChanged: (value) =>
19+
context.read<LoginBloc>().add(PasswordInput(value)),
20+
prefix: Padding(
21+
padding: EdgeInsets.symmetric(
22+
horizontal: 8.r,
23+
vertical: 10.r,
24+
),
25+
// TODO(BURG3R5): Deal with Focus transfer.
26+
child: const ImageIcon(
27+
Svg(AppAssets.lock),
3728
),
38-
IconButton(
39-
icon: SvgPicture.asset(
40-
(state.obscurePassword) ? AppAssets.eyeOff : AppAssets.eyeOn,
41-
color: state.isPasswordFocused
42-
? AppColors.primary
43-
: AppColors.grey1,
29+
),
30+
suffix: IconButton(
31+
icon: ImageIcon(
32+
Svg(
33+
obscurePassword ? AppAssets.eyeOff : AppAssets.eyeOn,
4434
),
45-
onPressed: () =>
46-
context.read<LoginBloc>().add(const ToggleObscure()),
4735
),
48-
],
36+
onPressed: () =>
37+
context.read<LoginBloc>().add(const ToggleObscure()),
38+
),
4939
);
5040
},
5141
);
@@ -59,25 +49,18 @@ class UsernameField extends StatelessWidget {
5949

6050
@override
6151
Widget build(BuildContext context) {
62-
return BlocSelector<LoginBloc, LoginState, bool>(
63-
selector: (state) => state.isUsernameFocused,
64-
builder: (context, isUsernameFocused) {
65-
return TextInput(
66-
hint: 'Username',
67-
onChanged: (value) =>
68-
context.read<LoginBloc>().add(UsernameInput(value)),
69-
prefix: Padding(
70-
padding: EdgeInsets.symmetric(
71-
horizontal: 8.r,
72-
vertical: 10.r,
73-
),
74-
child: SvgPicture.asset(
75-
AppAssets.person,
76-
color: isUsernameFocused ? AppColors.primary : AppColors.grey1,
77-
),
78-
),
79-
);
80-
},
52+
return TextInput(
53+
hint: 'Username',
54+
onChanged: (value) => context.read<LoginBloc>().add(UsernameInput(value)),
55+
prefix: Padding(
56+
padding: EdgeInsets.symmetric(
57+
horizontal: 8.r,
58+
vertical: 10.r,
59+
),
60+
child: const ImageIcon(
61+
Svg(AppAssets.person),
62+
),
63+
),
8164
);
8265
}
8366
}

0 commit comments

Comments
 (0)