update login with device info
This commit is contained in:
@@ -5,6 +5,8 @@ import 'package:dartz/dartz.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
|
||||
import '../../../common/service/device_info_service.dart';
|
||||
import '../../../common/service/fcm_service.dart';
|
||||
import '../../../domain/auth/auth.dart';
|
||||
|
||||
part 'login_form_event.dart';
|
||||
@@ -14,7 +16,14 @@ part 'login_form_bloc.freezed.dart';
|
||||
@injectable
|
||||
class LoginFormBloc extends Bloc<LoginFormEvent, LoginFormState> {
|
||||
final IAuthRepository _authRepository;
|
||||
LoginFormBloc(this._authRepository) : super(LoginFormState.initial()) {
|
||||
final FcmService _fcmService;
|
||||
final DeviceInfoService _deviceInfoService;
|
||||
|
||||
LoginFormBloc(
|
||||
this._authRepository,
|
||||
this._fcmService,
|
||||
this._deviceInfoService,
|
||||
) : super(LoginFormState.initial()) {
|
||||
on<LoginFormEvent>(_onLoginFormEvent);
|
||||
}
|
||||
|
||||
@@ -43,9 +52,14 @@ class LoginFormBloc extends Bloc<LoginFormEvent, LoginFormState> {
|
||||
);
|
||||
|
||||
if (emailValid && passwordValid) {
|
||||
final fcmToken = await _fcmService.getToken() ?? '';
|
||||
final devicePayload = await _deviceInfoService.getDevicePayload();
|
||||
|
||||
failureOrLogin = await _authRepository.login(
|
||||
email: state.email,
|
||||
password: state.password,
|
||||
fcmToken: fcmToken,
|
||||
devicePayload: devicePayload,
|
||||
);
|
||||
|
||||
emit(
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
|
||||
@module
|
||||
abstract class FirebaseDi {
|
||||
@@ -10,4 +12,10 @@ abstract class FirebaseDi {
|
||||
@lazySingleton
|
||||
FlutterLocalNotificationsPlugin get localNotifications =>
|
||||
FlutterLocalNotificationsPlugin();
|
||||
|
||||
@lazySingleton
|
||||
DeviceInfoPlugin get deviceInfo => DeviceInfoPlugin();
|
||||
|
||||
@preResolve
|
||||
Future<PackageInfo> get packageInfo => PackageInfo.fromPlatform();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
|
||||
@lazySingleton
|
||||
class DeviceInfoService {
|
||||
DeviceInfoService(this._deviceInfo, this._packageInfo);
|
||||
|
||||
final DeviceInfoPlugin _deviceInfo;
|
||||
final PackageInfo _packageInfo;
|
||||
|
||||
String get appVersion => '${_packageInfo.version}+${_packageInfo.buildNumber}';
|
||||
|
||||
Future<Map<String, String>> getDevicePayload() async {
|
||||
final info = await _getDeviceInfo();
|
||||
return {
|
||||
'device_id': info['device_id'] ?? '',
|
||||
'device_name': info['device_name'] ?? '',
|
||||
'device_type': info['device_type'] ?? 'mobile',
|
||||
'platform': _getPlatform(),
|
||||
'app_version': appVersion,
|
||||
'os_version': info['os_version'] ?? '',
|
||||
};
|
||||
}
|
||||
|
||||
String _getPlatform() {
|
||||
if (Platform.isAndroid) return 'android';
|
||||
if (Platform.isIOS) return 'ios';
|
||||
return 'web';
|
||||
}
|
||||
|
||||
Future<Map<String, String>> _getDeviceInfo() async {
|
||||
if (Platform.isAndroid) {
|
||||
final android = await _deviceInfo.androidInfo;
|
||||
return {
|
||||
'device_id': android.id,
|
||||
'device_name': '${android.manufacturer} ${android.model}',
|
||||
'device_type': _resolveDeviceType(android.model),
|
||||
'os_version': 'Android ${android.version.release} (SDK ${android.version.sdkInt})',
|
||||
};
|
||||
} else if (Platform.isIOS) {
|
||||
final ios = await _deviceInfo.iosInfo;
|
||||
return {
|
||||
'device_id': ios.identifierForVendor ?? '',
|
||||
'device_name': ios.name,
|
||||
'device_type': _resolveDeviceType(ios.model),
|
||||
'os_version': '${ios.systemName} ${ios.systemVersion}',
|
||||
};
|
||||
}
|
||||
return {'device_type': 'desktop'};
|
||||
}
|
||||
|
||||
/// Deteksi device_type berdasarkan nama model
|
||||
/// Nilai valid: mobile | tablet | desktop
|
||||
String _resolveDeviceType(String model) {
|
||||
final lower = model.toLowerCase();
|
||||
if (lower.contains('tablet') || lower.contains('tab') || lower.contains('ipad')) {
|
||||
return 'tablet';
|
||||
}
|
||||
return 'mobile';
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ abstract class IAuthRepository {
|
||||
Future<Either<AuthFailure, Login>> login({
|
||||
required String email,
|
||||
required String password,
|
||||
required Map<String, String> devicePayload,
|
||||
required String fcmToken,
|
||||
});
|
||||
Future<Either<AuthFailure, Unit>> logout();
|
||||
Future<bool> hasToken();
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ abstract class Env {
|
||||
@dev
|
||||
class DevEnv implements Env {
|
||||
@override
|
||||
String get baseUrl => 'https://api-pos.apskel.id';
|
||||
String get baseUrl => 'http://192.168.1.13:4000';
|
||||
|
||||
@override
|
||||
String get dbName => "apskel_pos_dev.db"; // example value
|
||||
|
||||
@@ -21,11 +21,18 @@ class AuthRemoteDataProvider {
|
||||
Future<DC<AuthFailure, LoginDto>> login({
|
||||
required String email,
|
||||
required String password,
|
||||
required Map<String, String> devicePayload,
|
||||
required String fcmToken,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _apiClient.post(
|
||||
ApiPath.login,
|
||||
data: {'email': email, 'password': password},
|
||||
data: {
|
||||
'email': email,
|
||||
'password': password,
|
||||
'fcm_token': fcmToken,
|
||||
...devicePayload,
|
||||
},
|
||||
);
|
||||
|
||||
if (response.data['code'] == 401) {
|
||||
|
||||
@@ -19,11 +19,15 @@ class AuthRepository implements IAuthRepository {
|
||||
Future<Either<AuthFailure, Login>> login({
|
||||
required String email,
|
||||
required String password,
|
||||
required Map<String, String> devicePayload,
|
||||
required String fcmToken,
|
||||
}) async {
|
||||
try {
|
||||
final result = await _dataProvider.login(
|
||||
email: email,
|
||||
password: password,
|
||||
devicePayload: devicePayload,
|
||||
fcmToken: fcmToken,
|
||||
);
|
||||
|
||||
if (result.hasError) {
|
||||
|
||||
@@ -85,6 +85,8 @@ import 'package:apskel_pos_flutter_v2/common/di/di_shared_preferences.dart'
|
||||
as _i135;
|
||||
import 'package:apskel_pos_flutter_v2/common/network/network_client.dart'
|
||||
as _i171;
|
||||
import 'package:apskel_pos_flutter_v2/common/service/device_info_service.dart'
|
||||
as _i288;
|
||||
import 'package:apskel_pos_flutter_v2/common/service/fcm_service.dart' as _i312;
|
||||
import 'package:apskel_pos_flutter_v2/domain/analytic/analytic.dart' as _i346;
|
||||
import 'package:apskel_pos_flutter_v2/domain/auth/auth.dart' as _i776;
|
||||
@@ -149,12 +151,14 @@ import 'package:apskel_pos_flutter_v2/infrastructure/table/repositories/table_re
|
||||
import 'package:apskel_pos_flutter_v2/presentation/router/app_router.dart'
|
||||
as _i800;
|
||||
import 'package:connectivity_plus/connectivity_plus.dart' as _i895;
|
||||
import 'package:device_info_plus/device_info_plus.dart' as _i833;
|
||||
import 'package:dio/dio.dart' as _i361;
|
||||
import 'package:firebase_messaging/firebase_messaging.dart' as _i892;
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart'
|
||||
as _i163;
|
||||
import 'package:get_it/get_it.dart' as _i174;
|
||||
import 'package:injectable/injectable.dart' as _i526;
|
||||
import 'package:package_info_plus/package_info_plus.dart' as _i655;
|
||||
import 'package:shared_preferences/shared_preferences.dart' as _i460;
|
||||
|
||||
const String _dev = 'dev';
|
||||
@@ -167,16 +171,20 @@ extension GetItInjectableX on _i174.GetIt {
|
||||
_i526.EnvironmentFilter? environmentFilter,
|
||||
}) async {
|
||||
final gh = _i526.GetItHelper(this, environment, environmentFilter);
|
||||
final firebaseDi = _$FirebaseDi();
|
||||
final sharedPreferencesDi = _$SharedPreferencesDi();
|
||||
final databaseDi = _$DatabaseDi();
|
||||
final autoRouteDi = _$AutoRouteDi();
|
||||
final connectivityDi = _$ConnectivityDi();
|
||||
final dioDi = _$DioDi();
|
||||
final firebaseDi = _$FirebaseDi();
|
||||
gh.factory<_i13.CheckoutFormBloc>(() => _i13.CheckoutFormBloc());
|
||||
gh.factory<_i96.PrinterBloc>(() => _i96.PrinterBloc());
|
||||
gh.factory<_i257.ReportBloc>(() => _i257.ReportBloc());
|
||||
gh.factory<_i334.SplitBillFormBloc>(() => _i334.SplitBillFormBloc());
|
||||
await gh.factoryAsync<_i655.PackageInfo>(
|
||||
() => firebaseDi.packageInfo,
|
||||
preResolve: true,
|
||||
);
|
||||
await gh.factoryAsync<_i460.SharedPreferences>(
|
||||
() => sharedPreferencesDi.prefs,
|
||||
preResolve: true,
|
||||
@@ -189,6 +197,13 @@ extension GetItInjectableX on _i174.GetIt {
|
||||
gh.lazySingleton<_i163.FlutterLocalNotificationsPlugin>(
|
||||
() => firebaseDi.localNotifications,
|
||||
);
|
||||
gh.lazySingleton<_i833.DeviceInfoPlugin>(() => firebaseDi.deviceInfo);
|
||||
gh.lazySingleton<_i288.DeviceInfoService>(
|
||||
() => _i288.DeviceInfoService(
|
||||
gh<_i833.DeviceInfoPlugin>(),
|
||||
gh<_i655.PackageInfo>(),
|
||||
),
|
||||
);
|
||||
gh.lazySingleton<_i171.NetworkClient>(
|
||||
() => _i171.NetworkClient(gh<_i895.Connectivity>()),
|
||||
);
|
||||
@@ -276,6 +291,13 @@ extension GetItInjectableX on _i174.GetIt {
|
||||
gh<_i708.CategoryLocalDataProvider>(),
|
||||
),
|
||||
);
|
||||
gh.factory<_i46.LoginFormBloc>(
|
||||
() => _i46.LoginFormBloc(
|
||||
gh<_i776.IAuthRepository>(),
|
||||
gh<_i312.FcmService>(),
|
||||
gh<_i288.DeviceInfoService>(),
|
||||
),
|
||||
);
|
||||
gh.factory<_i983.ITableRepository>(
|
||||
() => _i824.TableRepository(
|
||||
gh<_i95.TableRemoteDataProvider>(),
|
||||
@@ -308,9 +330,6 @@ extension GetItInjectableX on _i174.GetIt {
|
||||
gh<_i833.PaymentMethodRemoteDataProvider>(),
|
||||
),
|
||||
);
|
||||
gh.factory<_i46.LoginFormBloc>(
|
||||
() => _i46.LoginFormBloc(gh<_i776.IAuthRepository>()),
|
||||
);
|
||||
gh.factory<_i641.LogoutBloc>(
|
||||
() => _i641.LogoutBloc(gh<_i776.IAuthRepository>()),
|
||||
);
|
||||
@@ -404,6 +423,8 @@ extension GetItInjectableX on _i174.GetIt {
|
||||
}
|
||||
}
|
||||
|
||||
class _$FirebaseDi extends _i857.FirebaseDi {}
|
||||
|
||||
class _$SharedPreferencesDi extends _i135.SharedPreferencesDi {}
|
||||
|
||||
class _$DatabaseDi extends _i209.DatabaseDi {}
|
||||
@@ -413,5 +434,3 @@ class _$AutoRouteDi extends _i729.AutoRouteDi {}
|
||||
class _$ConnectivityDi extends _i807.ConnectivityDi {}
|
||||
|
||||
class _$DioDi extends _i86.DioDi {}
|
||||
|
||||
class _$FirebaseDi extends _i857.FirebaseDi {}
|
||||
|
||||
Reference in New Issue
Block a user