Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

完善登录处理 #65

Merged
merged 4 commits into from
Aug 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/lang/zh-CN/

## [Unreleased]

### Changed

- 优化表单验证
- 完善主页面的显示

## [0.5.4] - 2020-08-07

### Added
Expand Down
18 changes: 18 additions & 0 deletions lib/blocs/app_preferences/app_preferences_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:convert';

import 'package:bloc/bloc.dart';
import 'package:enum_to_string/enum_to_string.dart';
Expand All @@ -7,6 +8,7 @@ import 'package:flutter/foundation.dart';
import 'package:logging/logging.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:smart_home/models/app_tab.dart';
import 'package:smart_home/models/user.dart';

part 'app_preferences_event.dart';
part 'app_preferences_state.dart';
Expand All @@ -31,13 +33,18 @@ class AppPreferencesBloc
String blogAdminUrl = prefs.getString('blogAdminUrl');
AppTab defaultPage = EnumToString.fromString(
AppTab.values, prefs.getString('defaultPage'));
String loginUserJsonString = prefs.getString('loginUser');
User loginUser = loginUserJsonString != null
? User.fromJson(jsonDecode(loginUserJsonString))
: null;
yield state.copyWith(
initialized: true,
apiUrl: apiUrl,
refreshInterval: refreshInterval,
blogUrl: blogUrl,
blogAdminUrl: blogAdminUrl,
defaultPage: defaultPage,
loginUser: loginUser,
);
} catch (e) {
_log.severe('启动失败,无法获取配置');
Expand Down Expand Up @@ -85,5 +92,16 @@ class AppPreferencesBloc
_log.severe('设置默认主页失败');
}
}
if (event is LoginUserChanged) {
try {
final SharedPreferences prefs = await _prefs;
prefs.setString('loginUser', jsonEncode(event.loginUser.toJson()));
yield state.copyWith(
loginUser: event.loginUser,
);
} catch (e) {
_log.severe('设置登录用户失败');
}
}
}
}
15 changes: 15 additions & 0 deletions lib/blocs/app_preferences/app_preferences_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,18 @@ class DefaultPageChanged extends AppPreferencesEvent {
String toString() =>
'DefaultPageChanged { defaultPage: ${defaultPage.name} }';
}

/// 更改登录用户
class LoginUserChanged extends AppPreferencesEvent {
final User loginUser;

LoginUserChanged({
@required this.loginUser,
});

@override
List<Object> get props => [loginUser];

@override
String toString() => 'LoginUserChanged { loginUser: ${loginUser.username} }';
}
6 changes: 6 additions & 0 deletions lib/blocs/app_preferences/app_preferences_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class AppPreferencesState extends Equatable {
final String blogUrl;
final String blogAdminUrl;
final AppTab defaultPage;
final User loginUser;

const AppPreferencesState({
@required this.initialized,
Expand All @@ -15,6 +16,7 @@ class AppPreferencesState extends Equatable {
@required this.blogUrl,
@required this.blogAdminUrl,
@required this.defaultPage,
@required this.loginUser,
});

factory AppPreferencesState.initial() {
Expand All @@ -25,6 +27,7 @@ class AppPreferencesState extends Equatable {
blogUrl: null,
blogAdminUrl: null,
defaultPage: AppTab.storage,
loginUser: null,
);
}

Expand All @@ -35,6 +38,7 @@ class AppPreferencesState extends Equatable {
String blogUrl,
String blogAdminUrl,
AppTab defaultPage,
User loginUser,
}) {
return AppPreferencesState(
initialized: initialized ?? this.initialized,
Expand All @@ -43,6 +47,7 @@ class AppPreferencesState extends Equatable {
blogUrl: blogUrl ?? this.blogUrl,
blogAdminUrl: blogAdminUrl ?? this.blogAdminUrl,
defaultPage: defaultPage ?? this.defaultPage,
loginUser: loginUser ?? this.loginUser,
);
}

Expand All @@ -54,5 +59,6 @@ class AppPreferencesState extends Equatable {
blogUrl,
blogAdminUrl,
defaultPage,
loginUser,
];
}
12 changes: 11 additions & 1 deletion lib/blocs/authentication/authentication_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/foundation.dart';
import 'package:smart_home/blocs/app_preferences/app_preferences_bloc.dart';
import 'package:smart_home/models/models.dart';
import 'package:smart_home/repositories/user_repository.dart';

Expand All @@ -10,9 +11,11 @@ part 'authentication_state.dart';
class AuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState> {
final UserRepository userRepository;
final AppPreferencesBloc appPreferencesBloc;

AuthenticationBloc({
@required this.userRepository,
@required this.appPreferencesBloc,
}) : super(AuthenticationInitial());

@override
Expand All @@ -32,7 +35,13 @@ class AuthenticationBloc
try {
// 检查是否登录
if (await userRepository.isLogin) {
yield AuthenticationSuccess(await userRepository.currentUser());
if (appPreferencesBloc.state.loginUser != null) {
yield AuthenticationSuccess(appPreferencesBloc.state.loginUser);
} else {
User user = await userRepository.currentUser();
appPreferencesBloc.add(LoginUserChanged(loginUser: user));
yield AuthenticationSuccess(user);
}
} else {
yield AuthenticationFailure('未登录,请登录账户');
}
Expand All @@ -49,6 +58,7 @@ class AuthenticationBloc
await userRepository.authenticate(event.username, event.password);
if (result) {
User user = await userRepository.currentUser();
appPreferencesBloc.add(LoginUserChanged(loginUser: user));
yield AuthenticationSuccess(user);
} else {
yield AuthenticationFailure('用户名或密码错误');
Expand Down
1 change: 1 addition & 0 deletions lib/pages/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class HomePage extends StatelessWidget {
return BlocProvider(
create: (context) => AuthenticationBloc(
userRepository: RepositoryProvider.of<UserRepository>(context),
appPreferencesBloc: RepositoryProvider.of<AppPreferencesBloc>(context),
)..add(AuthenticationStarted()),
child: BlocConsumer<AuthenticationBloc, AuthenticationState>(
listener: (context, state) {
Expand Down
100 changes: 52 additions & 48 deletions lib/pages/login_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -168,58 +168,62 @@ class _LoginFormState extends State<LoginForm> {

return BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (context, state) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/icon/icon.png',
width: 100.0,
height: 100.0,
semanticLabel: 'icon',
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Form(
child: AutofillGroup(
child: Column(
children: [
TextFormField(
enableSuggestions: false,
decoration: InputDecoration(labelText: '用户名'),
controller: _usernameController,
autofillHints: <String>[AutofillHints.username],
),
TextFormField(
enableSuggestions: false,
decoration: InputDecoration(labelText: '密码'),
controller: _passwordController,
obscureText: true,
autofillHints: <String>[AutofillHints.password],
return Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/icon/icon.png',
width: 100.0,
height: 100.0,
semanticLabel: 'icon',
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Form(
child: AutofillGroup(
child: Column(
children: [
TextFormField(
enableSuggestions: false,
decoration: InputDecoration(labelText: '用户名'),
controller: _usernameController,
autofillHints: <String>[AutofillHints.username],
),
TextFormField(
enableSuggestions: false,
decoration: InputDecoration(labelText: '密码'),
controller: _passwordController,
obscureText: true,
autofillHints: <String>[AutofillHints.password],
),
],
),
],
),
),
),
),
),
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
onPressed: state is! AuthenticationInProgress
? _onLoginButtonPressed
: null,
child: Text('登录'),
),
FlatButton(
onPressed: widget.onTapBack,
child: Text('返回'),
),
Container(
child: state is AuthenticationInProgress
? CircularProgressIndicator()
: null,
RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
),
onPressed: state is! AuthenticationInProgress
? _onLoginButtonPressed
: null,
child: Text('登录'),
),
FlatButton(
onPressed: widget.onTapBack,
child: Text('返回'),
),
Container(
child: state is AuthenticationInProgress
? CircularProgressIndicator()
: null,
),
],
),
],
),
);
},
);
Expand Down
12 changes: 4 additions & 8 deletions lib/repositories/user_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ class UserRepository {

/// 登出
Future logout() async {
await _clearRefreshToken();
final SharedPreferences prefs = await _prefs;
await prefs.remove('refreshToken');
await prefs.remove('loginUser');
_log.fine('clear refresh token');
}

/// 刷新 Token
Expand Down Expand Up @@ -95,13 +98,6 @@ class UserRepository {
}
}

/// 清除 Refresh Token
Future _clearRefreshToken() async {
final SharedPreferences prefs = await _prefs;
await prefs.remove('refreshToken');
_log.fine('clear refresh token');
}

Future _setRefreshToken(String refreshToken) async {
final SharedPreferences prefs = await _prefs;
await prefs.setString('refreshToken', refreshToken);
Expand Down
28 changes: 28 additions & 0 deletions lib/widgets/drawer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,34 @@ class MyDrawer extends StatelessWidget {
);
},
),
ListTile(
title: Text('登出'),
onTap: () {
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text('登出'),
content: Text('确认登出账户?'),
actions: <Widget>[
FlatButton(
child: Text('否'),
onPressed: () {
Navigator.of(context).pop();
},
),
FlatButton(
child: Text('是'),
onPressed: () {
BlocProvider.of<AuthenticationBloc>(context)
.add(AuthenticationLogout());
Navigator.pop(context);
},
),
],
),
);
},
),
],
);
},
Expand Down