mirror of
https://github.com/flutter/samples.git
synced 2025-11-14 11:28:36 +00:00
Compass app (#2446)
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import '../../../utils/result.dart';
|
||||
|
||||
abstract class AuthRepository extends ChangeNotifier {
|
||||
/// Returns true when the user is logged in
|
||||
/// Returns [Future] because it will load a stored auth state the first time.
|
||||
Future<bool> get isAuthenticated;
|
||||
|
||||
/// Perform login
|
||||
Future<Result<void>> login({
|
||||
required String email,
|
||||
required String password,
|
||||
});
|
||||
|
||||
/// Perform logout
|
||||
Future<Result<void>> logout();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import '../../../utils/result.dart';
|
||||
import 'auth_repository.dart';
|
||||
|
||||
class AuthRepositoryDev extends AuthRepository {
|
||||
/// User is always authenticated in dev scenarios
|
||||
@override
|
||||
Future<bool> get isAuthenticated => Future.value(true);
|
||||
|
||||
/// Login is always successful in dev scenarios
|
||||
@override
|
||||
Future<Result<void>> login({
|
||||
required String email,
|
||||
required String password,
|
||||
}) async {
|
||||
return Result.ok(null);
|
||||
}
|
||||
|
||||
/// Logout is always successful in dev scenarios
|
||||
@override
|
||||
Future<Result<void>> logout() async {
|
||||
return Result.ok(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
// Copyright 2024 The Flutter team. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
import '../../../utils/result.dart';
|
||||
import '../../services/api/api_client.dart';
|
||||
import '../../services/api/auth_api_client.dart';
|
||||
import '../../services/api/model/login_request/login_request.dart';
|
||||
import '../../services/api/model/login_response/login_response.dart';
|
||||
import '../../services/shared_preferences_service.dart';
|
||||
import 'auth_repository.dart';
|
||||
|
||||
class AuthRepositoryRemote extends AuthRepository {
|
||||
AuthRepositoryRemote({
|
||||
required ApiClient apiClient,
|
||||
required AuthApiClient authApiClient,
|
||||
required SharedPreferencesService sharedPreferencesService,
|
||||
}) : _apiClient = apiClient,
|
||||
_authApiClient = authApiClient,
|
||||
_sharedPreferencesService = sharedPreferencesService {
|
||||
_apiClient.authHeaderProvider = _authHeaderProvider;
|
||||
}
|
||||
|
||||
final AuthApiClient _authApiClient;
|
||||
final ApiClient _apiClient;
|
||||
final SharedPreferencesService _sharedPreferencesService;
|
||||
|
||||
bool? _isAuthenticated;
|
||||
String? _authToken;
|
||||
final _log = Logger('AuthRepositoryRemote');
|
||||
|
||||
/// Fetch token from shared preferences
|
||||
Future<void> _fetch() async {
|
||||
final result = await _sharedPreferencesService.fetchToken();
|
||||
switch (result) {
|
||||
case Ok<String?>():
|
||||
_authToken = result.value;
|
||||
_isAuthenticated = result.value != null;
|
||||
case Error<String?>():
|
||||
_log.severe(
|
||||
'Failed to fech Token from SharedPreferences',
|
||||
result.error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> get isAuthenticated async {
|
||||
// Status is cached
|
||||
if (_isAuthenticated != null) {
|
||||
return _isAuthenticated!;
|
||||
}
|
||||
// No status cached, fetch from storage
|
||||
await _fetch();
|
||||
return _isAuthenticated ?? false;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> login({
|
||||
required String email,
|
||||
required String password,
|
||||
}) async {
|
||||
try {
|
||||
final result = await _authApiClient.login(
|
||||
LoginRequest(
|
||||
email: email,
|
||||
password: password,
|
||||
),
|
||||
);
|
||||
switch (result) {
|
||||
case Ok<LoginResponse>():
|
||||
_log.info('User logged int');
|
||||
// Set auth status
|
||||
_isAuthenticated = true;
|
||||
_authToken = result.value.token;
|
||||
// Store in Shared preferences
|
||||
return await _sharedPreferencesService.saveToken(result.value.token);
|
||||
case Error<LoginResponse>():
|
||||
_log.warning('Error logging in: ${result.error}');
|
||||
return Result.error(result.error);
|
||||
}
|
||||
} finally {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<void>> logout() async {
|
||||
_log.info('User logged out');
|
||||
try {
|
||||
// Clear stored auth token
|
||||
final result = await _sharedPreferencesService.saveToken(null);
|
||||
if (result is Error<void>) {
|
||||
_log.severe('Failed to clear stored auth token');
|
||||
}
|
||||
|
||||
// Clear token in ApiClient
|
||||
_authToken = null;
|
||||
|
||||
// Clear authenticated status
|
||||
_isAuthenticated = false;
|
||||
return result;
|
||||
} finally {
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
String? _authHeaderProvider() =>
|
||||
_authToken != null ? 'Bearer $_authToken' : null;
|
||||
}
|
||||
Reference in New Issue
Block a user