Archived
285 lines
11 KiB
Dart
Executable File
285 lines
11 KiB
Dart
Executable File
import 'dart:math';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
|
|
void main() {
|
|
runApp(const MyApp());
|
|
}
|
|
|
|
class MyApp extends StatefulWidget {
|
|
const MyApp({super.key});
|
|
|
|
@override
|
|
State<MyApp> createState() => _MyAppState();
|
|
}
|
|
|
|
class _MyAppState extends State<MyApp> {
|
|
TextEditingController categoryController = TextEditingController();
|
|
TextEditingController changeDataController = TextEditingController();
|
|
ScrollController scrollController = ScrollController();
|
|
String resultStr = "";
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MaterialApp(
|
|
home: Scaffold(
|
|
appBar: AppBar(title: Text("密码生成器")),
|
|
body: Container(
|
|
padding: EdgeInsets.only(left: 10, right: 10),
|
|
child: ListView(
|
|
scrollDirection: Axis.vertical,
|
|
controller: scrollController,
|
|
children: [
|
|
DefaultTextStyle(
|
|
style: TextStyle(color: Colors.black, fontSize: 20),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
"C (communication)",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 25,
|
|
color: Colors.green,
|
|
),
|
|
),
|
|
Text("社交类: 该类软件包含以文本,语音,图片,音视频等方式进行社交,典型如微信,qq,电子邮箱 "),
|
|
SizedBox(height: 20),
|
|
Text(
|
|
"T (technology)",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 25,
|
|
color: Colors.green,
|
|
),
|
|
),
|
|
Text(
|
|
"科技/技术类: 该类软件包含以提供计算机技术等其他工程类技术支持/论坛为主的服务,典型如csdn,华为 ",
|
|
),
|
|
SizedBox(height: 20),
|
|
Text(
|
|
"S (shopping)",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 25,
|
|
color: Colors.green,
|
|
),
|
|
),
|
|
Text("购物/外卖类: 该类软件包含各种以线上购买实体商品为主的服务,典型如淘宝,京东 "),
|
|
SizedBox(height: 20),
|
|
Text(
|
|
"EDU (education)",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 25,
|
|
color: Colors.green,
|
|
),
|
|
),
|
|
Text("教育/学习类: 该类软件专注于提供教育,学术,辅导等的支持/资料,典型如扇贝英语,作业帮 "),
|
|
SizedBox(height: 20),
|
|
Text(
|
|
"E (entertainment)",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 25,
|
|
color: Colors.green,
|
|
),
|
|
),
|
|
Text("游戏/娱乐类: 该类软件专注于以提供电子游戏,休闲娱乐为主的服务,典型如王者荣耀,抖音 "),
|
|
SizedBox(height: 20),
|
|
Text(
|
|
"O (other)",
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 25,
|
|
color: Colors.green,
|
|
),
|
|
),
|
|
Text("其他: 当一个服务不属于以上任何类别,那么归属于此类,典型如processon,工商银行 "),
|
|
],
|
|
),
|
|
SizedBox(height: 20),
|
|
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
Expanded(flex: 2, child: Text("Category:")),
|
|
Expanded(
|
|
flex: 3,
|
|
child: SizedBox(
|
|
width: 200,
|
|
height: 50,
|
|
child: TextField(controller: categoryController),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 20),
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.end,
|
|
children: [
|
|
Expanded(flex: 2, child: Text("Change date: ")),
|
|
Expanded(
|
|
flex: 3,
|
|
child: SizedBox(
|
|
width: 200,
|
|
height: 50,
|
|
child: TextField(controller: changeDataController),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 20),
|
|
Center(
|
|
child: GestureDetector(
|
|
onTap: () {
|
|
setState(() {
|
|
resultStr = genPasswd();
|
|
});
|
|
WidgetsBinding.instance.addPostFrameCallback((val) {
|
|
scrollController.jumpTo(
|
|
scrollController.position.maxScrollExtent,
|
|
);
|
|
});
|
|
},
|
|
child: Container(
|
|
width: MediaQuery.of(context).size.width / 2,
|
|
height: 50,
|
|
alignment: Alignment.center,
|
|
decoration: BoxDecoration(
|
|
color: Color(0xFF8447D5),
|
|
borderRadius: BorderRadiusGeometry.circular(20),
|
|
),
|
|
child: Text(
|
|
"generate password",
|
|
style: TextStyle(fontSize: 18, color: Colors.white),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
|
|
resultStr.isEmpty
|
|
? SizedBox()
|
|
: Center(
|
|
child: Builder(
|
|
builder: (BuildContext context) {
|
|
return GestureDetector(
|
|
onLongPress: () {
|
|
Clipboard.setData(
|
|
ClipboardData(text: resultStr),
|
|
).then((val) {
|
|
double offsetTop =
|
|
MediaQuery.of(context).size.height -
|
|
200;
|
|
ScaffoldMessenger.of(
|
|
context,
|
|
).showSnackBar(
|
|
SnackBar(
|
|
backgroundColor: Color(0xE4616161),
|
|
behavior: SnackBarBehavior.floating,
|
|
margin: EdgeInsets.only(
|
|
bottom: offsetTop,
|
|
left: 100,
|
|
right: 100
|
|
),
|
|
content: Center(
|
|
child: Text("saved to clipboard"),
|
|
),
|
|
),
|
|
);
|
|
});
|
|
},
|
|
child: Container(
|
|
margin: EdgeInsets.only(top: 10),
|
|
child: Text(
|
|
resultStr,
|
|
style: TextStyle(
|
|
fontSize: 30,
|
|
fontWeight: FontWeight.w900,
|
|
letterSpacing: 2,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
String genRandomString(int length) {
|
|
String re = "";
|
|
Random random = Random();
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
int de = random.nextInt(2) + 1;
|
|
|
|
switch (de) {
|
|
case 1:
|
|
int lowerCase = random.nextInt(122 - 97 + 1) + 97;
|
|
re += String.fromCharCode(lowerCase);
|
|
break;
|
|
case 2:
|
|
int upperCase = random.nextInt(90 - 65 + 1) + 65;
|
|
re += String.fromCharCode(upperCase);
|
|
break;
|
|
default:
|
|
print("Unexpected value: $de");
|
|
break;
|
|
}
|
|
}
|
|
return re;
|
|
}
|
|
|
|
String genLowerLetter(int length) {
|
|
String re = "";
|
|
Random random = Random();
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
int lowerCase = random.nextInt(122 - 97 + 1) + 97;
|
|
re += String.fromCharCode(lowerCase);
|
|
}
|
|
return re;
|
|
}
|
|
|
|
String genPasswd() {
|
|
String categoryText = categoryController.text;
|
|
String dateText = changeDataController.text;
|
|
if (categoryText.isEmpty || dateText.isEmpty) {
|
|
return "Please done the form";
|
|
}
|
|
|
|
// verify if the field valid
|
|
// ================== START ==================
|
|
const categoryList = ["C", "T", "S", "EDU", "E", "O"];
|
|
if (!categoryList.contains(categoryText)) {
|
|
return "Category: input not valid";
|
|
}
|
|
|
|
if (dateText.length != 4) {
|
|
return "Date: the length must be 4";
|
|
}
|
|
var dateList = dateText.split('');
|
|
for (var i = 0; i < dateList.length; i++) {
|
|
if (!(dateList[i].codeUnitAt(0) >= 48 &&
|
|
dateList[i].codeUnitAt(0) <= 57)) {
|
|
return "Date: all digit must be a number";
|
|
}
|
|
}
|
|
// ================== END ==================
|
|
|
|
return "${categoryText}${dateText}${genLowerLetter(2)}_${genRandomString(8)}";
|
|
}
|
|
}
|