together_mobile/lib/components/common_widgets.dart

262 lines
6.5 KiB
Dart
Raw Normal View History

2023-06-21 17:44:28 +08:00
import 'package:flutter/material.dart';
2024-04-09 17:23:28 +08:00
import '/common/constants.dart';
import '/request/signup_signin.dart';
2023-06-21 17:44:28 +08:00
class SignTextField extends StatefulWidget {
const SignTextField({
super.key,
this.color = kPrimaryColor,
this.obscureText = false,
required this.type,
2023-07-04 11:51:11 +08:00
this.isSignup = true,
2023-06-21 17:44:28 +08:00
required this.labelText,
required this.controller,
required this.isError,
});
final Color color;
final bool obscureText;
final String type;
2023-07-04 11:51:11 +08:00
final bool isSignup;
2023-06-21 17:44:28 +08:00
final String labelText;
final TextEditingController controller;
final void Function(String, bool) isError;
@override
State<SignTextField> createState() => _SignTextFieldState();
}
class _SignTextFieldState extends State<SignTextField> {
int _length = 0;
String? _errorText;
2023-07-04 11:51:11 +08:00
FocusNode? _node;
@override
void initState() {
super.initState();
if (widget.isSignup) {
_node = FocusNode();
_node!.addListener(_handleFocusChange);
}
}
void _handleFocusChange() async {
if (!widget.isSignup) {
return;
}
switch (widget.type) {
case 'username' || 'email':
if (!_node!.hasFocus) {
if (widget.controller.text.isNotEmpty && _errorText == null) {
Map<String, dynamic> res =
2023-07-04 11:51:11 +08:00
await hasAccountExisted(widget.type, widget.controller.text);
if (widget.type == 'username') {
setState(() {
res['code'] == 10100
? _errorText = null
: _errorText = '用户名已存在';
2023-07-04 11:51:11 +08:00
});
} else {
setState(() {
res['code'] == 10100
? _errorText = null
: _errorText = '邮箱已被使用';
2023-07-04 11:51:11 +08:00
});
}
}
}
default:
null;
}
}
@override
void dispose() {
if (widget.isSignup) {
_node!.removeListener(_handleFocusChange);
_node!.dispose();
}
super.dispose();
}
2023-06-21 17:44:28 +08:00
@override
Widget build(BuildContext context) {
return TextField(
onChanged: (String newValue) {
setState(() {
_length = newValue.characters.length;
});
setErrorText();
widget.isError(
2023-07-04 11:51:11 +08:00
widget.type,
(_errorText == null && widget.controller.text.isEmpty) ||
_errorText != null,
);
2023-06-21 17:44:28 +08:00
},
controller: widget.controller,
2023-07-04 11:51:11 +08:00
focusNode: _node,
2023-06-21 17:44:28 +08:00
obscureText: widget.obscureText,
cursorColor: widget.color,
textAlignVertical: TextAlignVertical.bottom,
keyboardType: initTextInputType(),
decoration: InputDecoration(
errorText: _errorText,
labelText: widget.labelText,
counterText: '$_length 字符',
floatingLabelStyle: TextStyle(color: widget.color),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: widget.color),
),
),
);
}
TextInputType initTextInputType() {
switch (widget.type) {
case 'email':
return TextInputType.emailAddress;
case 'code':
return TextInputType.number;
case _:
return TextInputType.visiblePassword;
}
}
void setErrorText() {
if (widget.controller.text.isEmpty) {
setState(() {
_errorText = null;
});
}
switch (widget.type) {
case 'username':
if (widget.controller.text.contains(RegExp(r'\W+'))) {
setState(() {
_errorText = '用户名只允许字母, 数字和下划线';
});
} else if (_length < 5 || _length > 20) {
setState(() {
_errorText = '用户名需为8-20个字符';
});
} else {
setState(() {
_errorText = null;
});
}
break;
2023-07-04 11:51:11 +08:00
case 'password':
2023-06-21 17:44:28 +08:00
if (widget.controller.text.contains(RegExp(r'\s'))) {
setState(() {
_errorText = '密码不能包含空格';
});
} else if (_length < 8 || _length > 30) {
setState(() {
_errorText = '密码需为8-30个字符';
});
} else {
setState(() {
_errorText = null;
});
}
break;
case 'email':
var exp = RegExp(
r'^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$');
if (!exp.hasMatch(widget.controller.text)) {
setState(() {
_errorText = '邮箱格式错误';
});
} else {
setState(() {
_errorText = null;
});
}
case 'code':
if (!RegExp(r'\d{6}').hasMatch(widget.controller.text)) {
setState(() {
_errorText = '6为数字';
});
} else if (widget.controller.text.characters.length != 6) {
_errorText = '6位数字';
} else {
setState(() {
_errorText = null;
});
}
}
}
}
class CommonTextField extends StatelessWidget {
const CommonTextField({
super.key,
this.color = kPrimaryColor,
this.obscureText = false,
required this.labelText,
required this.controller,
});
final Color color;
final bool obscureText;
final String labelText;
final TextEditingController controller;
@override
Widget build(BuildContext context) {
return TextField(
controller: controller,
obscureText: obscureText,
cursorColor: kSecondaryColor,
textAlignVertical: TextAlignVertical.bottom,
decoration: InputDecoration(
helperText: '5-10位',
errorText: 'xxx',
labelText: labelText,
floatingLabelStyle: const TextStyle(color: kSecondaryColor),
focusedBorder:
UnderlineInputBorder(borderSide: BorderSide(color: color))),
);
}
2023-06-21 17:44:28 +08:00
}
class CommonElevatedButton extends StatelessWidget {
const CommonElevatedButton({
super.key,
required this.onPressed,
required this.text,
this.color = kPrimaryColor,
});
final VoidCallback onPressed;
final String text;
final Color color;
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: color,
elevation: 0,
fixedSize: const Size(150, 20),
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12))),
child: Text(
text,
style: const TextStyle(
fontSize: 20.0,
letterSpacing: 10,
color: kContentColorDark,
),
),
);
}
2023-06-21 17:44:28 +08:00
}