mirror of
https://github.com/qinglong-app/qinglong_app.git
synced 2025-10-09 16:48:19 +08:00
update task page
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:back_button_interceptor/back_button_interceptor.dart';
|
import 'package:back_button_interceptor/back_button_interceptor.dart';
|
||||||
@@ -28,23 +27,23 @@ class CommonDialog extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
margin: EdgeInsets.only(top: 15.0),
|
margin: const EdgeInsets.only(top: 15.0),
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
minHeight: 40,
|
minHeight: 40,
|
||||||
),
|
),
|
||||||
child: IconTheme(
|
child: IconTheme(
|
||||||
data: IconThemeData(
|
data: const IconThemeData(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
size: 40.0,
|
size: 40.0,
|
||||||
),
|
),
|
||||||
child: LoadingIcon()),
|
child: LoadingIcon()),
|
||||||
),
|
),
|
||||||
SizedBox(
|
const SizedBox(
|
||||||
height: 15,
|
height: 15,
|
||||||
),
|
),
|
||||||
if (text != null)
|
if (text != null)
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
left: 15,
|
left: 15,
|
||||||
right: 15,
|
right: 15,
|
||||||
bottom: 15,
|
bottom: 15,
|
||||||
@@ -53,7 +52,7 @@ class CommonDialog extends StatelessWidget {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: TextStyle(color: Colors.white, fontSize: 14),
|
style: const TextStyle(color: Colors.white, fontSize: 14),
|
||||||
child: Text(text!),
|
child: Text(text!),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -83,7 +82,7 @@ class LoadingIconState extends State<LoadingIcon> with SingleTickerProviderState
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_controller = new AnimationController(vsync: this, duration: Duration(milliseconds: 1000))..repeat();
|
_controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 1000))..repeat();
|
||||||
_doubleAnimation = Tween(begin: 0.0, end: 360.0).animate(_controller!)
|
_doubleAnimation = Tween(begin: 0.0, end: 360.0).animate(_controller!)
|
||||||
..addListener(() {
|
..addListener(() {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
@@ -113,12 +112,14 @@ typedef HideCallback = Future Function();
|
|||||||
|
|
||||||
int backButtonIndex = 2;
|
int backButtonIndex = 2;
|
||||||
|
|
||||||
|
OverlayEntry? overlay;
|
||||||
|
|
||||||
HideCallback showCommonDialog(
|
HideCallback showCommonDialog(
|
||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
String? text,
|
String? text,
|
||||||
bool backButtonClose = false,
|
bool backButtonClose = false,
|
||||||
CommonDialogState commonDialogState = CommonDialogState.LOADING,
|
CommonDialogState commonDialogState = CommonDialogState.LOADING,
|
||||||
}) {
|
}) {
|
||||||
Completer<VoidCallback> result = Completer<VoidCallback>();
|
Completer<VoidCallback> result = Completer<VoidCallback>();
|
||||||
var backButtonName = 'QL_Toast$backButtonIndex';
|
var backButtonName = 'QL_Toast$backButtonIndex';
|
||||||
BackButtonInterceptor.add((stopDefaultButtonEvent, _) {
|
BackButtonInterceptor.add((stopDefaultButtonEvent, _) {
|
||||||
@@ -131,7 +132,11 @@ HideCallback showCommonDialog(
|
|||||||
}, zIndex: backButtonIndex, name: backButtonName);
|
}, zIndex: backButtonIndex, name: backButtonName);
|
||||||
backButtonIndex++;
|
backButtonIndex++;
|
||||||
|
|
||||||
var overlay = OverlayEntry(
|
if (overlay != null) {
|
||||||
|
overlay?.remove();
|
||||||
|
overlay = null;
|
||||||
|
}
|
||||||
|
overlay = OverlayEntry(
|
||||||
maintainState: true,
|
maintainState: true,
|
||||||
builder: (_) => WillPopScope(
|
builder: (_) => WillPopScope(
|
||||||
onWillPop: () async {
|
onWillPop: () async {
|
||||||
@@ -145,10 +150,12 @@ HideCallback showCommonDialog(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
result.complete(() {
|
result.complete(() {
|
||||||
overlay.remove();
|
overlay?.remove();
|
||||||
BackButtonInterceptor.removeByName(backButtonName);
|
BackButtonInterceptor.removeByName(backButtonName);
|
||||||
});
|
});
|
||||||
Overlay.of(context)?.insert(overlay);
|
if (overlay != null) {
|
||||||
|
Overlay.of(context)?.insert(overlay!);
|
||||||
|
}
|
||||||
|
|
||||||
return () async {
|
return () async {
|
||||||
var hide = await result.future;
|
var hide = await result.future;
|
||||||
@@ -193,4 +200,4 @@ HideCallback loadingDialog(BuildContext context, {String? text}) {
|
|||||||
commonDialogState: CommonDialogState.LOADING,
|
commonDialogState: CommonDialogState.LOADING,
|
||||||
backButtonClose: true,
|
backButtonClose: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class MyApp extends ConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: (){
|
onTap: () {
|
||||||
FocusScope.of(context).requestFocus(FocusNode());
|
FocusScope.of(context).requestFocus(FocusNode());
|
||||||
},
|
},
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
@@ -41,7 +41,8 @@ class MyApp extends ConsumerWidget {
|
|||||||
onGenerateRoute: (setting) {
|
onGenerateRoute: (setting) {
|
||||||
return Routes.generateRoute(setting);
|
return Routes.generateRoute(setting);
|
||||||
},
|
},
|
||||||
home: ref.read<UserInfoViewModel>(userInfoProvider).userInfoBean != null ? const HomePage() : LoginPage(),
|
// home: ref.read<UserInfoViewModel>(userInfoProvider).userInfoBean != null ? const HomePage() : LoginPage(),
|
||||||
|
home: HomePage(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
ref.read(themeProvider).changeTheme();
|
ref.read(themeProvider).changeTheme();
|
||||||
},
|
},
|
||||||
child: Center(child: Text("改变主题")),
|
child: const Center(child: Text("改变主题")),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ class LoginPage extends StatefulWidget {
|
|||||||
class _LoginPageState extends State<LoginPage> {
|
class _LoginPageState extends State<LoginPage> {
|
||||||
final TextEditingController _userNameController = TextEditingController();
|
final TextEditingController _userNameController = TextEditingController();
|
||||||
final TextEditingController _passwordController = TextEditingController();
|
final TextEditingController _passwordController = TextEditingController();
|
||||||
HideCallback? _hideCallback;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -24,21 +23,9 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
body: Consumer(builder: (context, ref, child) {
|
body: Consumer(builder: (context, ref, child) {
|
||||||
var model = ref.watch<LoginViewModel>(loginProvider);
|
var model = ref.watch<LoginViewModel>(loginProvider);
|
||||||
|
|
||||||
if (model.isLoading) {
|
|
||||||
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
|
||||||
_hideCallback ??= loadingDialog(context, text: "登录中...");
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (_hideCallback != null) {
|
|
||||||
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
|
||||||
_hideCallback!();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (model.loginSuccess) {
|
if (model.loginSuccess) {
|
||||||
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
|
||||||
Navigator.of(context).pushNamed(Routes.route_HomePage);
|
Navigator.of(context).popAndPushNamed(Routes.route_HomePage);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
@@ -130,16 +117,19 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: MediaQuery.of(context).size.width - 30,
|
width: MediaQuery.of(context).size.width - 30,
|
||||||
child: CupertinoButton(
|
child: CupertinoButton(
|
||||||
color: (_userNameController.text.isNotEmpty && _passwordController.text.isNotEmpty)
|
color: (_userNameController.text.isNotEmpty && _passwordController.text.isNotEmpty && !model.isLoading)
|
||||||
? Theme.of(context).primaryColor
|
? Theme.of(context).primaryColor
|
||||||
: Theme.of(context).primaryColor.withOpacity(0.3),
|
: Theme.of(context).primaryColor.withOpacity(0.3),
|
||||||
child: const Text(
|
child: model.isLoading
|
||||||
"登录",
|
? const CupertinoActivityIndicator()
|
||||||
style: TextStyle(
|
: const Text(
|
||||||
fontSize: 16,
|
"登录",
|
||||||
),
|
style: TextStyle(
|
||||||
),
|
fontSize: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
if (model.isLoading) return;
|
||||||
Utils.hideKeyBoard(context);
|
Utils.hideKeyBoard(context);
|
||||||
model.login(_userNameController.text, _passwordController.text);
|
model.login(_userNameController.text, _passwordController.text);
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||||
import 'package:qinglong_app/base/base_state_widget.dart';
|
import 'package:qinglong_app/base/base_state_widget.dart';
|
||||||
import 'package:qinglong_app/module/task/task_viewmodel.dart';
|
import 'package:qinglong_app/module/task/task_viewmodel.dart';
|
||||||
|
|
||||||
@@ -15,13 +17,24 @@ class _TaskPageState extends State<TaskPage> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BaseStateWidget<TaskViewModel>(
|
return BaseStateWidget<TaskViewModel>(
|
||||||
builder: (context, model, child) {
|
builder: (context, model, child) {
|
||||||
return ListView.builder(
|
return RefreshIndicator(
|
||||||
itemBuilder: (context, index) {
|
onRefresh: () async {
|
||||||
return ListTile(
|
return Future.delayed(Duration(seconds: 1), () {});
|
||||||
title: Text(model.list[index]),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
itemCount: model.list.length,
|
child: ListView.separated(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
vertical: 15,
|
||||||
|
),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return TaskItemCell();
|
||||||
|
},
|
||||||
|
itemCount: model.list.length,
|
||||||
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
|
return SizedBox(
|
||||||
|
height: 10,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
model: taskProvider,
|
model: taskProvider,
|
||||||
@@ -31,3 +44,94 @@ class _TaskPageState extends State<TaskPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TaskItemCell extends StatelessWidget {
|
||||||
|
const TaskItemCell({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Slidable(
|
||||||
|
key: const ValueKey(0),
|
||||||
|
startActionPane: ActionPane(
|
||||||
|
motion: const ScrollMotion(),
|
||||||
|
extentRatio: 0.3,
|
||||||
|
dragDismissible: false,
|
||||||
|
children: [
|
||||||
|
SlidableAction(
|
||||||
|
flex: 1,
|
||||||
|
icon: CupertinoIcons.memories,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
backgroundColor: Color(0xFF0F77FE),
|
||||||
|
onPressed: (BuildContext context) {},
|
||||||
|
),
|
||||||
|
SlidableAction(
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: Colors.green,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
icon: CupertinoIcons.clock_fill,
|
||||||
|
onPressed: (BuildContext context) {},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
endActionPane: ActionPane(
|
||||||
|
motion: ScrollMotion(),
|
||||||
|
extentRatio: 0.15,
|
||||||
|
children: [
|
||||||
|
SlidableAction(
|
||||||
|
backgroundColor: Colors.cyan,
|
||||||
|
flex: 1,
|
||||||
|
onPressed: (_) {},
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
icon: CupertinoIcons.ellipsis,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 15,
|
||||||
|
vertical: 5,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: const [
|
||||||
|
Text(
|
||||||
|
"东东农场",
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
fontSize: 18,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 5,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 15,
|
||||||
|
height: 15,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
Text("2020/12/12 12:23"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 5,
|
||||||
|
),
|
||||||
|
const Text(
|
||||||
|
"12/12/12",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -97,6 +97,13 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.3"
|
version: "1.0.3"
|
||||||
|
flutter_slidable:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_slidable
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "1.2.0"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ dependencies:
|
|||||||
shared_preferences: ^2.0.12
|
shared_preferences: ^2.0.12
|
||||||
synchronized: ^3.0.0
|
synchronized: ^3.0.0
|
||||||
back_button_interceptor: ^5.0.2
|
back_button_interceptor: ^5.0.2
|
||||||
|
flutter_slidable: ^1.2.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user