mirror of
https://github.com/qinglong-app/qinglong_app.git
synced 2025-10-09 16:48:19 +08:00
add login
This commit is contained in:
@@ -24,9 +24,13 @@ class _BaseStateWidgetState<T extends BaseViewModel> extends ConsumerState<BaseS
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (widget.onReady != null) {
|
||||
widget.onReady!(ref.read<T>(widget.model));
|
||||
}
|
||||
WidgetsBinding.instance?.addPostFrameCallback(
|
||||
(timeStamp) {
|
||||
if (widget.onReady != null) {
|
||||
widget.onReady!(ref.read<T>(widget.model));
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class BaseViewModel extends ChangeNotifier {
|
||||
|
||||
class ViewModel extends ChangeNotifier{}
|
||||
|
||||
|
||||
class BaseViewModel extends ViewModel {
|
||||
PageState currentState = PageState.START;
|
||||
|
||||
void loading({bool notify = false}) {
|
||||
|
||||
196
lib/base/common_dialog.dart
Normal file
196
lib/base/common_dialog.dart
Normal file
@@ -0,0 +1,196 @@
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:back_button_interceptor/back_button_interceptor.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// @author newtab on 2021/7/16
|
||||
///常用loading,fail,success对话框
|
||||
class CommonDialog extends StatelessWidget {
|
||||
final String? text;
|
||||
final CommonDialogState? commonDialogState;
|
||||
|
||||
const CommonDialog({Key? key, this.text, this.commonDialogState}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget result = Material(
|
||||
color: Colors.transparent,
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(color: Color.fromRGBO(17, 17, 17, 0.7), borderRadius: BorderRadius.circular(5)),
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: MediaQuery.of(context).size.width / 2,
|
||||
minWidth: 122,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 15.0),
|
||||
constraints: BoxConstraints(
|
||||
minHeight: 40,
|
||||
),
|
||||
child: IconTheme(
|
||||
data: IconThemeData(
|
||||
color: Colors.white,
|
||||
size: 40.0,
|
||||
),
|
||||
child: LoadingIcon()),
|
||||
),
|
||||
SizedBox(
|
||||
height: 15,
|
||||
),
|
||||
if (text != null)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 15,
|
||||
right: 15,
|
||||
bottom: 15,
|
||||
),
|
||||
child: DefaultTextStyle(
|
||||
textAlign: TextAlign.center,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(color: Colors.white, fontSize: 14),
|
||||
child: Text(text!),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
class LoadingIcon extends StatefulWidget {
|
||||
final double size;
|
||||
|
||||
LoadingIcon({this.size = 50.0});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => LoadingIconState();
|
||||
}
|
||||
|
||||
class LoadingIconState extends State<LoadingIcon> with SingleTickerProviderStateMixin {
|
||||
AnimationController? _controller;
|
||||
Animation<double>? _doubleAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = new AnimationController(vsync: this, duration: Duration(milliseconds: 1000))..repeat();
|
||||
_doubleAnimation = Tween(begin: 0.0, end: 360.0).animate(_controller!)
|
||||
..addListener(() {
|
||||
setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Transform.rotate(
|
||||
angle: _doubleAnimation!.value ~/ 30 * 30.0 * 0.0174533, child: Image.asset("assets/images/loading.png", width: widget.size, height: widget.size));
|
||||
}
|
||||
}
|
||||
|
||||
enum CommonDialogState {
|
||||
LOADING,
|
||||
SUCCESS,
|
||||
FAILED,
|
||||
}
|
||||
|
||||
typedef HideCallback = Future Function();
|
||||
|
||||
int backButtonIndex = 2;
|
||||
|
||||
HideCallback showCommonDialog(
|
||||
BuildContext context, {
|
||||
String? text,
|
||||
bool backButtonClose = false,
|
||||
CommonDialogState commonDialogState = CommonDialogState.LOADING,
|
||||
}) {
|
||||
Completer<VoidCallback> result = Completer<VoidCallback>();
|
||||
var backButtonName = 'QL_Toast$backButtonIndex';
|
||||
BackButtonInterceptor.add((stopDefaultButtonEvent, _) {
|
||||
if (backButtonClose) {
|
||||
result.future.then((hide) {
|
||||
hide();
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}, zIndex: backButtonIndex, name: backButtonName);
|
||||
backButtonIndex++;
|
||||
|
||||
var overlay = OverlayEntry(
|
||||
maintainState: true,
|
||||
builder: (_) => WillPopScope(
|
||||
onWillPop: () async {
|
||||
var hide = await result.future;
|
||||
hide();
|
||||
return false;
|
||||
},
|
||||
child: CommonDialog(
|
||||
text: text,
|
||||
),
|
||||
),
|
||||
);
|
||||
result.complete(() {
|
||||
overlay.remove();
|
||||
BackButtonInterceptor.removeByName(backButtonName);
|
||||
});
|
||||
Overlay.of(context)?.insert(overlay);
|
||||
|
||||
return () async {
|
||||
var hide = await result.future;
|
||||
hide();
|
||||
};
|
||||
}
|
||||
|
||||
Future successDialog(BuildContext context, String text) {
|
||||
HideCallback hideCallback = showCommonDialog(
|
||||
context,
|
||||
text: text,
|
||||
commonDialogState: CommonDialogState.SUCCESS,
|
||||
backButtonClose: true,
|
||||
);
|
||||
return Future.delayed(
|
||||
Duration(
|
||||
milliseconds: 1000,
|
||||
), () {
|
||||
hideCallback();
|
||||
});
|
||||
}
|
||||
|
||||
Future failDialog(BuildContext context, String text) {
|
||||
HideCallback hideCallback = showCommonDialog(
|
||||
context,
|
||||
text: text,
|
||||
commonDialogState: CommonDialogState.FAILED,
|
||||
backButtonClose: true,
|
||||
);
|
||||
return Future.delayed(
|
||||
Duration(
|
||||
milliseconds: 1000,
|
||||
), () {
|
||||
hideCallback();
|
||||
});
|
||||
}
|
||||
|
||||
HideCallback loadingDialog(BuildContext context, {String? text}) {
|
||||
return showCommonDialog(
|
||||
context,
|
||||
text: text,
|
||||
commonDialogState: CommonDialogState.LOADING,
|
||||
backButtonClose: true,
|
||||
);
|
||||
}
|
||||
16
lib/base/routes.dart
Normal file
16
lib/base/routes.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:qinglong_app/module/home/home_page.dart';
|
||||
|
||||
class Routes {
|
||||
static const String route_HomePage = "/home/homepage";
|
||||
|
||||
static Route<dynamic>? generateRoute(RouteSettings settings) {
|
||||
switch (settings.name) {
|
||||
case route_HomePage:
|
||||
return CupertinoPageRoute(builder: (context) => const HomePage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
1
lib/base/sp_const.dart
Normal file
1
lib/base/sp_const.dart
Normal file
@@ -0,0 +1 @@
|
||||
String sp_UserINfo = "userinfo";
|
||||
@@ -16,5 +16,9 @@ class ThemeViewModel extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
ThemeData darkTheme = ThemeData.dark().copyWith();
|
||||
ThemeData lightTheme = ThemeData.light().copyWith();
|
||||
ThemeData darkTheme = ThemeData.dark().copyWith(
|
||||
primaryColor: Color(0xffffffff),
|
||||
);
|
||||
ThemeData lightTheme = ThemeData.light().copyWith(
|
||||
primaryColor: Color(0xFF0F77FE),
|
||||
);
|
||||
|
||||
46
lib/base/userinfo_viewmodel.dart
Normal file
46
lib/base/userinfo_viewmodel.dart
Normal file
@@ -0,0 +1,46 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:qinglong_app/base/base_viewmodel.dart';
|
||||
import 'package:qinglong_app/utils/sp_utils.dart';
|
||||
|
||||
import 'sp_const.dart';
|
||||
|
||||
var userInfoProvider = ChangeNotifierProvider((ref) => UserInfoViewModel());
|
||||
|
||||
class UserInfoViewModel extends ViewModel {
|
||||
UserInfoBean? _userInfoBean;
|
||||
|
||||
UserInfoViewModel() {
|
||||
String userInfoJson = SpUtil.getString(sp_UserINfo);
|
||||
if (userInfoJson.isNotEmpty) {
|
||||
_userInfoBean = UserInfoBean.fromJson(jsonDecode(userInfoJson));
|
||||
}
|
||||
}
|
||||
|
||||
void updateUserInfoBean(UserInfoBean userInfoBean) {
|
||||
_userInfoBean = userInfoBean;
|
||||
SpUtil.putString(sp_UserINfo, jsonEncode(userInfoBean));
|
||||
}
|
||||
|
||||
UserInfoBean? get userInfoBean => _userInfoBean;
|
||||
}
|
||||
|
||||
class UserInfoBean {
|
||||
String? name;
|
||||
int? age;
|
||||
|
||||
UserInfoBean({this.name, this.age});
|
||||
|
||||
UserInfoBean.fromJson(Map<String, dynamic> json) {
|
||||
name = json['name'];
|
||||
age = json['age'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['name'] = this.name;
|
||||
data['age'] = this.age;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user