update login with device info
This commit is contained in:
parent
842b7a5041
commit
a0610459bf
@ -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();
|
||||
}
|
||||
|
||||
64
lib/common/service/device_info_service.dart
Normal file
64
lib/common/service/device_info_service.dart
Normal file
@ -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();
|
||||
|
||||
@ -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 {}
|
||||
|
||||
@ -6,20 +6,24 @@ import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import connectivity_plus
|
||||
import device_info_plus
|
||||
import firebase_core
|
||||
import firebase_crashlytics
|
||||
import firebase_messaging
|
||||
import flutter_local_notifications
|
||||
import package_info_plus
|
||||
import path_provider_foundation
|
||||
import shared_preferences_foundation
|
||||
import sqflite_darwin
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
||||
FLTFirebaseCrashlyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCrashlyticsPlugin"))
|
||||
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
|
||||
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
|
||||
|
||||
48
pubspec.lock
48
pubspec.lock
@ -337,6 +337,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.11"
|
||||
device_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: device_info_plus
|
||||
sha256: "98f28b42168cc509abc92f88518882fd58061ea372d7999aecc424345c7bff6a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.5.0"
|
||||
device_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus_platform_interface
|
||||
sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.3"
|
||||
dio:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -880,6 +896,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.0"
|
||||
package_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.3.1"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
path:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -1421,6 +1453,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.15.0"
|
||||
win32_registry:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32_registry
|
||||
sha256: "6f1b564492d0147b330dd794fee8f512cec4977957f310f9951b5f9d83618dae"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
win_ble:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@ -31,6 +31,8 @@ dependencies:
|
||||
firebase_crashlytics: ^5.0.3
|
||||
firebase_messaging: ^16.0.3
|
||||
flutter_local_notifications: ^18.0.1
|
||||
device_info_plus: ^11.4.0
|
||||
package_info_plus: ^8.3.0
|
||||
another_flushbar: ^1.12.32
|
||||
flutter_spinkit: ^5.2.2
|
||||
bloc: ^9.1.0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user