Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Hoàng Văn Đạt
mypoint_flutter_app
Commits
b75a9279
Commit
b75a9279
authored
Sep 23, 2025
by
DatHV
Browse files
update config, build.
parent
36ac8d24
Changes
42
Hide whitespace changes
Inline
Side-by-side
keystores/eCom.jks
deleted
100644 → 0
View file @
36ac8d24
File deleted
keystores/mypoint.jks
deleted
100644 → 0
View file @
36ac8d24
File deleted
lib/app_config.dart
deleted
100644 → 0
View file @
36ac8d24
class
AppConfig
{
final
String
name
;
final
String
baseUrl
;
final
String
t3Token
;
final
bool
enableLogging
;
const
AppConfig
({
required
this
.
name
,
required
this
.
baseUrl
,
required
this
.
t3Token
,
required
this
.
enableLogging
,
});
static
late
AppConfig
current
;
}
lib/base/base_response_model.dart
View file @
b75a9279
...
...
@@ -15,7 +15,7 @@ class BaseResponseModel<T> {
bool
get
isSuccess
{
final
_code
=
code
??
0
;
if
(
_code
>=
200
&&
_code
<
299
)
return
true
;
return
status
==
"success
"
;
return
status
?.
toUpperCase
()
==
"SUCCESS
"
;
}
const
BaseResponseModel
({
this
.
code
,
this
.
status
,
this
.
errorMessage
,
this
.
errorCode
,
this
.
message
,
this
.
data
});
...
...
lib/base/base_screen.dart
View file @
b75a9279
...
...
@@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/base/app_loading.dart'
;
import
'package:mypoint_flutter_app/networking/app_navigator.dart'
;
import
'../networking/dio_http_service.dart'
;
import
'../resources/base_color.dart'
;
import
'../widgets/alert/custom_alert_dialog.dart'
;
...
...
@@ -52,6 +53,7 @@ abstract class BaseState<Screen extends BaseScreen> extends State<Screen> {
bool
showCloseButton
=
true
,
VoidCallback
?
onConfirmed
,
})
{
if
(
AppNavigator
.
isShowingDialog
)
return
;
Get
.
dialog
(
CustomAlertDialog
(
showCloseButton:
showCloseButton
,
...
...
lib/configs/api_paths.dart
View file @
b75a9279
class
APIPaths
{
//sandbox
static
const
String
baseUrl
=
"https://api.sandbox.mypoint.com.vn/8854/gup2start/rest"
;
//
static const String baseUrl = "https://api.sandbox.mypoint.com.vn/8854/gup2start/rest";
static
const
String
checkUpdate
=
"/version-management-service/api/v1.0/check-customer-software-update"
;
static
const
String
getOnboardingInfo
=
"/resource/api/v2.0/intro-screen"
;
static
const
String
checkPhoneNumber
=
"/user/api/v2.0/account/users/checkPhoneNumber"
;
...
...
lib/env_loader.dart
View file @
b75a9279
import
'dart:convert'
;
import
'
package:flutter/services.
dart'
show
rootBundle
,
MethodChannel
;
import
'dart
:io
'
show
Platform
;
import
'package:flutter/foundation.dart'
;
import
'
app_config.dart'
;
import
'
package:flutter/services.dart'
show
rootBundle
,
MethodChannel
;
Future
<
void
>
loadEnv
()
async
{
String
flavor
=
'dev'
;
// default flavor
String
baseUrl
=
'https://api.sandbox.mypoint.com.vn/8854/gup2start/rest'
;
String
t3Token
=
'dev-xxx'
;
bool
enableLogging
=
true
;
// Try to get config from BuildConfig if available
try
{
const
MethodChannel
channel
=
MethodChannel
(
'com.icom.mypoint/config'
);
final
Map
<
dynamic
,
dynamic
>
config
=
await
channel
.
invokeMethod
(
'getConfig'
);
flavor
=
config
[
'flavor'
]
??
'dev'
;
baseUrl
=
config
[
'baseUrl'
]
??
baseUrl
;
t3Token
=
config
[
'libToken'
]
??
t3Token
;
enableLogging
=
config
[
'enableLogging'
]
??
enableLogging
;
}
catch
(
e
)
{
class
AppConfig
{
final
String
flavor
;
final
String
baseUrl
;
final
String
t3Token
;
final
bool
enableLogging
;
AppConfig
({
required
this
.
flavor
,
required
this
.
baseUrl
,
required
this
.
t3Token
,
required
this
.
enableLogging
,
});
factory
AppConfig
.
fromMap
(
Map
<
String
,
dynamic
>
map
)
{
final
flavor
=
(
map
[
'flavor'
]
as
String
?)?.
trim
();
final
baseUrl
=
(
map
[
'baseUrl'
]
as
String
?)?.
trim
();
final
token
=
(
map
[
't3Token'
]
as
String
?)?.
trim
();
final
enable
=
map
[
'enableLogging'
];
if
((
flavor
??
''
).
isEmpty
)
throw
const
FormatException
(
"env thiếu 'flavor'"
);
if
((
baseUrl
??
''
).
isEmpty
)
throw
const
FormatException
(
"env thiếu 'baseUrl'"
);
// if ((token ?? '').isEmpty) throw const FormatException("env thiếu 'libToken'");
if
(
kDebugMode
)
{
print
(
'
Could not get c
onfig f
rom BuildConfig, using default:
$
e
'
);
print
(
'
AppC
onfig
:
f
lavor=
$flavor
, baseUrl=
$baseUrl
, t3Token=
${token ?? ''}
, enableLogging=
$enabl
e
'
);
}
return
AppConfig
(
flavor:
flavor
!,
baseUrl:
baseUrl
!,
t3Token:
token
??
''
,
enableLogging:
enable
is
bool
?
enable
:
true
,
);
}
AppConfig
.
current
=
AppConfig
(
name:
flavor
,
baseUrl:
baseUrl
,
t3Token:
t3Token
,
enableLogging:
enableLogging
,
);
static
late
AppConfig
current
;
}
Future
<
void
>
loadEnv
()
async
{
Map
<
String
,
dynamic
>?
cfg
;
if
(
Platform
.
isIOS
)
{
cfg
=
await
_tryLoadAsset
(
'assets/config/env.json'
);
cfg
??=
await
_tryLoadFromMethodChannel
();
}
else
if
(
Platform
.
isAndroid
)
{
cfg
=
await
_tryLoadFromMethodChannel
();
cfg
??=
await
_tryLoadAsset
(
'assets/config/env.json'
);
}
else
{
cfg
=
await
_tryLoadAsset
(
'assets/config/env.json'
);
}
if
(
cfg
==
null
)
{
throw
Exception
(
'Không tải được cấu hình môi trường (env).'
);
}
AppConfig
.
current
=
AppConfig
.
fromMap
(
cfg
);
if
(
kDebugMode
)
{
print
(
'✅ AppConfig loaded: flavor=
${AppConfig.current.flavor}
'
);
}
}
Future
<
Map
<
String
,
dynamic
>?>
_tryLoadAsset
(
String
path
)
async
{
try
{
final
s
=
await
rootBundle
.
loadString
(
path
);
return
jsonDecode
(
s
)
as
Map
<
String
,
dynamic
>;
}
catch
(
_
)
{
return
null
;
}
}
Future
<
Map
<
String
,
dynamic
>?>
_tryLoadFromMethodChannel
()
async
{
try
{
const
channel
=
MethodChannel
(
'com.icom.mypoint/config'
);
final
dynamic
result
=
await
channel
.
invokeMethod
(
'getConfig'
);
if
(
result
is
String
)
{
final
json
=
jsonDecode
(
result
)
as
Map
<
String
,
dynamic
>;
return
json
;
}
else
if
(
result
is
Map
)
{
final
map
=
Map
<
String
,
dynamic
>.
from
(
result
as
Map
);
return
map
;
}
}
catch
(
_
)
{}
return
null
;
}
\ No newline at end of file
lib/networking/app_navigator.dart
View file @
b75a9279
...
...
@@ -14,6 +14,7 @@ class AppNavigator {
static
bool
_networkDialogShown
=
false
;
static
bool
_errorDialogShown
=
false
;
static
bool
get
isShowingDialog
=>
_authDialogShown
||
_networkDialogShown
||
_errorDialogShown
;
static
BuildContext
?
get
_ctx
=>
key
.
currentContext
;
static
Future
<
void
>
showAuthAlertAndGoLogin
(
String
message
)
async
{
...
...
lib/networking/dio_http_service.dart
View file @
b75a9279
import
'package:dio/dio.dart'
;
import
'package:flutter/foundation.dart'
;
import
'dart:io'
;
import
'../
app_config
.dart'
;
import
'../
env_loader
.dart'
;
import
'interceptor/auth_interceptor.dart'
;
import
'interceptor/exception_interceptor.dart'
;
import
'interceptor/logger_interceptor.dart'
;
...
...
lib/networking/interceptor/auth_interceptor.dart
View file @
b75a9279
...
...
@@ -5,12 +5,14 @@ import 'package:mypoint_flutter_app/preference/data_preference.dart';
class
AuthInterceptor
extends
Interceptor
{
bool
_isHandlingAuth
=
false
;
static
const
_kAuthHandledKey
=
'__auth_handled__'
;
@override
void
onResponse
(
Response
response
,
ResponseInterceptorHandler
handler
)
{
Future
<
void
>
onResponse
(
Response
response
,
ResponseInterceptorHandler
handler
)
async
{
final
data
=
response
.
data
;
if
(
_isTokenInvalid
(
data
))
{
_handleAuthError
(
data
);
response
.
requestOptions
.
extra
[
_kAuthHandledKey
]
=
true
;
await
_handleAuthError
(
data
);
handler
.
reject
(
DioException
(
requestOptions:
response
.
requestOptions
...
...
@@ -28,8 +30,10 @@ class AuthInterceptor extends Interceptor {
@override
Future
<
void
>
onError
(
DioException
err
,
ErrorInterceptorHandler
handler
)
async
{
final
alreadyHandled
=
err
.
requestOptions
.
extra
[
_kAuthHandledKey
]
==
true
;
final
data
=
err
.
response
?.
data
;
final
statusCode
=
err
.
response
?.
statusCode
;
if
(
alreadyHandled
)
return
;
if
(
statusCode
==
401
||
_isTokenInvalid
(
data
))
{
await
_handleAuthError
(
data
);
return
handler
.
reject
(
err
);
...
...
lib/permission/biometric_manager.dart
View file @
b75a9279
import
'dart:io'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:get/get.dart'
;
import
'package:local_auth/local_auth.dart'
;
import
'../resources/base_color.dart'
;
...
...
@@ -12,8 +15,24 @@ enum BiometricTypeEnum {
}
class
BiometricManager
{
BiometricManager
.
_
();
static
final
BiometricManager
_instance
=
BiometricManager
.
_
();
factory
BiometricManager
()
=>
_instance
;
final
LocalAuthentication
_localAuth
=
LocalAuthentication
();
Future
<
bool
>
isDeviceSupported
()
async
{
try
{
final
supported
=
await
_localAuth
.
isDeviceSupported
();
return
supported
;
}
on
PlatformException
catch
(
e
)
{
debugPrint
(
'[Bio] isDeviceSupported error:
${e.code}
${e.message}
'
);
return
false
;
}
catch
(
e
)
{
debugPrint
(
'[Bio] isDeviceSupported unexpected:
$e
'
);
return
false
;
}
}
/// Kiểm tra xem thiết bị hỗ trợ loại sinh trắc học nào: faceID, fingerprint, none
Future
<
BiometricTypeEnum
>
checkDeviceBiometric
()
async
{
try
{
...
...
lib/preference/point/point_manager.dart
View file @
b75a9279
...
...
@@ -12,7 +12,7 @@ class UserPointManager extends RestfulApiViewModel {
final
RxInt
_userPoint
=
0
.
obs
;
HeaderHomeModel
?
_headerInfo
;
get
point
=>
_userPoint
.
value
;
int
get
point
=>
_userPoint
.
value
;
Future
<
int
?>
fetchUserPoint
()
async
{
if
(!
DataPreference
.
instance
.
logged
)
return
null
;
...
...
lib/screen/delete_account/delete_account_dialog.dart
View file @
b75a9279
...
...
@@ -2,7 +2,9 @@
import
'package:flutter/material.dart'
;
import
'package:flutter/gestures.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/extensions/num_extension.dart'
;
import
'package:mypoint_flutter_app/preference/data_preference.dart'
;
import
'package:mypoint_flutter_app/resources/base_color.dart'
;
import
'../../preference/point/point_manager.dart'
;
import
'../../resources/button_style.dart'
;
import
'../../resources/text_style.dart'
;
...
...
@@ -37,13 +39,13 @@ class _DeleteAccountDialogState extends State<DeleteAccountDialog> {
@override
Widget
build
(
BuildContext
context
)
{
final
int
userPoints
=
UserPointManager
().
point
;
return
Padding
(
padding:
const
EdgeInsets
.
fromLTRB
(
8
,
0
,
8
,
32
),
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
crossAxisAlignment:
CrossAxisAlignment
.
center
,
children:
[
const
SizedBox
(
height:
16
),
Image
.
asset
(
'assets/images/ic_pipi_03.png'
,
height:
220
),
const
SizedBox
(
height:
16
),
Text
(
"Bạn có chắc chắn muốn xoá tài khoản?"
,
style:
AppTextStyle
.
title
,
textAlign:
TextAlign
.
center
),
...
...
@@ -54,8 +56,8 @@ class _DeleteAccountDialogState extends State<DeleteAccountDialog> {
style:
AppTextStyle
.
content
,
children:
[
const
TextSpan
(
text:
"Toàn bộ "
),
TextSpan
(
text:
"
$
userPoints
điểm "
,
style:
AppTextStyle
.
boldContent
),
const
TextSpan
(
text:
"và "
),
TextSpan
(
text:
userPoints
.
money
(
CurrencyUnit
.
point
)
,
style:
AppTextStyle
.
boldContent
),
const
TextSpan
(
text:
"
và "
),
WidgetSpan
(
child:
GestureDetector
(
onTap:
_onUnUsedVoucherPressed
,
...
...
@@ -84,9 +86,9 @@ class _DeleteAccountDialogState extends State<DeleteAccountDialog> {
checkboxTheme:
CheckboxThemeData
(
fillColor:
MaterialStateProperty
.
resolveWith
<
Color
>((
states
)
{
if
(
states
.
contains
(
MaterialState
.
selected
))
{
return
Color
s
.
red
;
// ✅ Checked: màu đỏ
return
Base
Color
.
primary500
;
// ✅ Checked: màu đỏ
}
return
Colors
.
white
;
// ❌ Unchecked: ô trắng
return
Colors
.
white
;
}),
checkColor:
MaterialStateProperty
.
all
(
Colors
.
white
),
// ✅ Tick màu trắng
side:
const
BorderSide
(
color:
Colors
.
grey
),
...
...
@@ -119,7 +121,7 @@ class _DeleteAccountDialogState extends State<DeleteAccountDialog> {
const
SizedBox
(
height:
16
),
SizedBox
(
width:
double
.
infinity
,
height:
4
0
,
height:
4
8
,
child:
ElevatedButton
(
onPressed:
_viewModel
.
agreed
.
value
?
_onConfirmDelete
:
null
,
style:
AppButtonStyle
.
secondary
,
...
...
@@ -129,7 +131,7 @@ class _DeleteAccountDialogState extends State<DeleteAccountDialog> {
const
SizedBox
(
height:
8
),
SizedBox
(
width:
double
.
infinity
,
height:
4
0
,
height:
4
8
,
child:
ElevatedButton
(
onPressed:
()
=>
Get
.
back
(),
style:
AppButtonStyle
.
primary
,
...
...
@@ -151,11 +153,12 @@ class _DeleteAccountDialogState extends State<DeleteAccountDialog> {
}
void
_onUnUsedVoucherPressed
()
{
print
(
"Đi đến màn hình ưu đãi chưa sử dụng"
);
// TODO:
Get.toNamed(
'/unused-voucher'); hoặc mở webview
Get
.
back
(
);
Get
.
toNamed
(
myVoucherListScreen
);
}
void
_onTermConditionPressed
()
{
Get
.
back
();
Get
.
toNamed
(
campaignDetailScreen
,
arguments:
{
"type"
:
DetailPageRuleType
.
policyDeleteAccount
});
}
}
lib/screen/login/login_screen.dart
View file @
b75a9279
...
...
@@ -243,20 +243,19 @@ class _LoginScreenState extends BaseState<LoginScreen> with BasicState {
Widget
_buildBiometricSection
(
LoginViewModel
vm
)
{
return
Obx
(()
{
// Nếu thiết bị không hỗ trợ => ẩn
// if (vm.biometricType.value == BiometricTypeEnum.none) {
// return const SizedBox.shrink();
// }
// Hiển thị 1 icon tuỳ loại
IconData
icon
=
Icons
.
fingerprint
;
String
label
=
"Vân tay"
;
if
(!
vm
.
isSupportedBiometric
.
value
)
{
return
const
SizedBox
.
shrink
();
}
String
icon
=
'assets/images/ic_fingerprint.png'
;
String
label
=
"vân tay"
;
if
(
vm
.
biometricType
.
value
==
BiometricTypeEnum
.
faceId
)
{
icon
=
Icons
.
face
;
icon
=
'assets/images/ic_face.png'
;
label
=
"Face ID"
;
}
return
Column
(
children:
[
IconButton
(
icon:
I
con
(
icon
,
size:
36
),
icon:
I
mage
.
asset
(
icon
,
width:
40
,
height:
40
),
onPressed:
()
=>
vm
.
onBiometricLoginPressed
(
phoneNumber
),
),
Text
(
"Đăng nhập bằng
$label
"
),
...
...
lib/screen/login/login_viewmodel.dart
View file @
b75a9279
...
...
@@ -16,11 +16,10 @@ import '../main_tab_screen/main_tab_screen.dart';
enum
LoginState
{
idle
,
typing
,
error
}
class
LoginViewModel
extends
RestfulApiViewModel
{
final
BiometricManager
_biometricManager
=
BiometricManager
();
var
loginState
=
LoginState
.
idle
.
obs
;
var
isPasswordVisible
=
false
.
obs
;
var
password
=
""
.
obs
;
var
isSupportedBiometric
=
false
.
obs
;
var
biometricType
=
BiometricTypeEnum
.
none
.
obs
;
void
Function
(
String
message
)?
onShowAlertError
;
...
...
@@ -31,16 +30,12 @@ class LoginViewModel extends RestfulApiViewModel {
@override
void
onInit
()
{
super
.
onInit
();
_initBiometric
();
}
Future
<
void
>
_initBiometric
()
async
{
final
type
=
await
_biometricManager
.
checkDeviceBiometric
();
biometricType
.
value
=
type
;
freshBiometric
();
}
Future
<
bool
>
canUseBiometrics
()
async
{
return
_biometricManager
.
canCheckBiometrics
();
Future
<
void
>
freshBiometric
()
async
{
isSupportedBiometric
.
value
=
await
BiometricManager
().
isDeviceSupported
();
biometricType
.
value
=
await
BiometricManager
().
checkDeviceBiometric
();
}
void
onPasswordChanged
(
String
value
)
{
...
...
@@ -128,8 +123,8 @@ class LoginViewModel extends RestfulApiViewModel {
/// Xác thực đăng nhập bằng sinh trắc
Future
<
void
>
onBiometricLoginPressed
(
String
phone
)
async
{
final
canUse
=
await
canUse
Biometric
s
();
if
(!
canUse
||
biometricType
.
value
==
BiometricTypeEnum
.
none
)
{
final
isSupported
=
await
Biometric
Manager
().
isDeviceSupported
();
if
(!
isSupported
)
{
onShowAlertError
?.
call
(
"Thiết bị không hỗ trợ sinh trắc học"
);
return
;
}
...
...
lib/screen/onboarding/onboarding_viewmodel.dart
View file @
b75a9279
...
...
@@ -10,7 +10,7 @@ class OnboardingViewModel extends RestfulApiViewModel {
var
info
=
BaseResponseModel
<
OnboardingInfoModel
>().
obs
;
var
checkPhoneRes
=
BaseResponseModel
<
CheckPhoneResponseModel
>().
obs
;
var
phoneNumber
=
""
.
obs
;
var
isChecked
=
fals
e
.
obs
;
var
isChecked
=
tru
e
.
obs
;
bool
get
isButtonEnabled
=>
isChecked
.
value
&&
phoneNumber
.
value
.
isPhoneValid
();
String
get
content
=>
info
?.
value
?.
data
?.
content
??
""
;
...
...
lib/screen/otp/delete_account_otp_repository.dart
View file @
b75a9279
...
...
@@ -27,9 +27,10 @@ class DeleteAccountOtpRepository extends RestfulApiViewModel implements IOtpRepo
return
client
.
verifyDeleteAccount
(
otpCode
).
then
((
value
)
{
hideLoading
();
if
(
value
.
isSuccess
)
{
showToastMessage
(
"Xóa tài khoản thành công"
);
DataPreference
.
instance
.
clearBioToken
(
phoneNumber
);
DataPreference
.
instance
.
clearData
();
Get
.
offAllNamed
(
onboardingScreen
);
showToastMessage
(
"Xóa tài khoản thành công"
);
}
return
value
;
});
...
...
lib/screen/personal/personal_screen.dart
View file @
b75a9279
...
...
@@ -323,16 +323,10 @@ class _PersonalScreenState extends BaseState<PersonalScreen> with BasicState, Po
}
void
_safeBackToLogin
()
{
bool
found
=
false
;
Navigator
.
popUntil
(
Get
.
context
!,
(
route
)
{
final
matched
=
route
.
settings
.
name
==
loginScreen
;
if
(
matched
)
found
=
true
;
return
matched
;
});
final
phone
=
DataPreference
.
instance
.
phoneNumberUsedForLoginScreen
;
final
displayName
=
DataPreference
.
instance
.
displayName
;
print
(
"Safe back to login screen with phone:
$phone
, displayName:
$displayName
, found:
$found
"
);
if
(
phone
!=
null
&&
found
)
{
print
(
"Safe back to login screen with phone:
$phone
, displayName:
$displayName
"
);
if
(
phone
!=
null
)
{
Get
.
offAllNamed
(
loginScreen
,
arguments:
{
"phone"
:
phone
,
'fullName'
:
displayName
});
}
else
{
DataPreference
.
instance
.
clearData
();
...
...
lib/screen/setting/setting_viewmodel.dart
View file @
b75a9279
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_client_all_request.dart'
;
import
'../../networking/restful_api_viewmodel.dart'
;
...
...
@@ -21,28 +22,28 @@ class SettingViewModel extends RestfulApiViewModel {
Future
<
bool
>
toggleBiometric
(
bool
enable
)
async
{
final
phone
=
DataPreference
.
instance
.
phone
;
if
(
phone
==
null
)
return
biometricEnabled
;
final
canCheckBiometrics
=
BiometricManager
().
canCheckBiometrics
();
if
(!(
await
canCheckBiometrics
))
{
return
biometricEnabled
;
}
final
didAuthenticate
=
BiometricManager
().
authenticateB
iometric
()
;
if
(!(
await
didAuthenticate
))
return
b
iometric
Enabled
;
showLoading
();
if
(
enable
)
{
client
.
registerBiometric
()
.
then
((
value
)
{
try
{
final
supported
=
await
BiometricManager
().
isDeviceSupported
();
if
(!
supported
)
return
biometricEnabled
;
final
canCheck
=
await
BiometricManager
().
canCheckBiometrics
();
if
(!
canCheck
)
return
b
iometric
Enabled
;
final
didAuth
=
await
BiometricManager
().
authenticateB
iometric
()
;
if
(!
didAuth
)
return
biometricEnabled
;
showLoading
();
if
(
enable
)
{
final
value
=
await
client
.
registerBiometric
()
;
final
token
=
value
.
data
?.
bioToken
??
""
;
DataPreference
.
instance
.
saveBioToken
(
token
);
hideLoading
();
await
DataPreference
.
instance
.
saveBioToken
(
token
);
return
true
;
});
}
else
{
client
.
unRegisterBiometric
().
then
((
value
)
{
DataPreference
.
instance
.
clearBioToken
(
phone
!);
hideLoading
();
}
else
{
await
client
.
unRegisterBiometric
();
await
DataPreference
.
instance
.
clearBioToken
(
phone
);
return
false
;
});
}
}
catch
(
_
)
{
return
biometricEnabled
;
}
finally
{
hideLoading
();
}
return
enable
;
}
}
lib/screen/support/support_screen.dart
View file @
b75a9279
...
...
@@ -75,7 +75,7 @@ class _SupportScreenState extends State<SupportScreen> {
),
child:
Row
(
children:
[
Icon
(
_getIcon
(
item
.
type
),
color:
Base
Color
.
primary500
,
size:
24
),
Icon
(
_getIcon
(
item
.
type
),
color:
Color
s
.
black54
,
size:
24
),
const
SizedBox
(
width:
10
),
Expanded
(
child:
Text
(
item
.
title
,
style:
const
TextStyle
(
fontSize:
16
)),
...
...
Prev
1
2
3
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment