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
6b980613
Commit
6b980613
authored
Nov 14, 2025
by
DatHV
Browse files
update project structure
parent
bfff9e47
Changes
507
Expand all
Hide whitespace changes
Inline
Side-by-side
lib/network
ing
/interceptor/exception_interceptor.dart
→
lib/
core/
network/interceptor/exception_interceptor.dart
View file @
6b980613
import
'dart:async'
;
import
'package:dio/dio.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:mypoint_flutter_app/base/app_loading.dart'
;
import
'../../base/app_navigator.dart'
;
import
'../dio_http_service.dart'
;
import
'package:mypoint_flutter_app/shared/widgets/loading/app_loading.dart'
;
import
'../../../app/routing/app_navigator.dart'
;
import
'../error_mapper.dart'
;
import
'../dio_http_service.dart'
;
class
ExceptionInterceptor
extends
Interceptor
{
static
Completer
<
bool
>?
_currentRetryPrompt
;
...
...
lib/network
ing
/interceptor/logger_interceptor.dart
→
lib/
core/
network/interceptor/logger_interceptor.dart
View file @
6b980613
File moved
lib/network
ing
/interceptor/network_error_gate.dart
→
lib/
core/
network/interceptor/network_error_gate.dart
View file @
6b980613
File moved
lib/network
ing
/interceptor/request_interceptor.dart
→
lib/
core/
network/interceptor/request_interceptor.dart
View file @
6b980613
import
'dart:convert'
;
import
'dart:typed_data'
;
import
'package:dio/dio.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:mypoint_flutter_app/preference/data_preference.dart'
;
import
'package:mypoint_flutter_app/
shared/
preference
s
/data_preference.dart'
;
import
'package:uuid/uuid.dart'
;
class
RequestInterceptor
extends
Interceptor
{
...
...
lib/network
ing
/restful_api_client.dart
→
lib/
core/
network/restful_api_client.dart
View file @
6b980613
import
'dart:convert'
;
import
'package:dio/dio.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:mypoint_flutter_app/
base
/base_response_model.dart'
;
import
'../config
s
/callbacks.dart'
;
import
'../config
s
/constants.dart'
;
import
'package:mypoint_flutter_app/
shared/widgets/base_view
/base_response_model.dart'
;
import
'../
../app/
config/callbacks.dart'
;
import
'../
../app/
config/constants.dart'
;
enum
Method
{
GET
,
POST
,
PUT
,
DELETE
}
...
...
lib/network
ing
/restful_api_client_all_request.dart
→
lib/
core/
network/restful_api_client_all_request.dart
View file @
6b980613
This diff is collapsed.
Click to expand it.
lib/network
ing
/restful_api_viewmodel.dart
→
lib/
core/
network/restful_api_viewmodel.dart
View file @
6b980613
import
'dart:async'
;
import
'package:dio/dio.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_client.dart'
;
import
'../base/base_response_model.dart'
;
import
'../base/base_view_model.dart'
;
import
'../configs/constants.dart'
;
import
'../base/app_navigator.dart'
;
import
'package:mypoint_flutter_app/core/network/restful_api_client.dart'
;
import
'../../shared/widgets/base_view/base_response_model.dart'
;
import
'../../shared/widgets/base_view/base_view_model.dart'
;
import
'../../app/config/constants.dart'
;
import
'../../app/routing/app_navigator.dart'
;
import
'interceptor/network_error_gate.dart'
;
import
'dio_extra_keys.dart'
;
import
'dio_http_service.dart'
;
import
'error_mapper.dart'
;
import
'interceptor/network_error_gate.dart'
;
typedef
ApiCall
<
T
>
=
Future
<
BaseResponseModel
<
T
>>
Function
();
typedef
OnSuccess
<
T
>
=
...
...
@@ -33,9 +33,11 @@ class RestfulApiViewModel extends BaseViewModel {
OnComplete
?
onComplete
,
bool
showAppNavigatorDialog
=
false
,
bool
withLoading
=
true
,
bool
trackLoading
=
true
,
String
defaultError
=
ErrorCodes
.
commonError
,
})
async
{
if
(
withLoading
)
showLoading
();
if
(
trackLoading
)
beginTrackedLoading
();
BaseResponseModel
<
T
>?
res
;
try
{
res
=
await
request
();
...
...
@@ -86,6 +88,7 @@ class RestfulApiViewModel extends BaseViewModel {
}
}
finally
{
if
(
withLoading
)
hideLoading
();
if
(
trackLoading
)
endTrackedLoading
();
onComplete
?.
call
();
}
}
...
...
lib/
permission
/biometric_manager.dart
→
lib/
core/services
/biometric_manager.dart
View file @
6b980613
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'
;
import
'../widgets/alert/custom_alert_dialog.dart'
;
import
'../widgets/alert/data_alert_model.dart'
;
import
'../
theme
/base_color.dart'
;
import
'../
../shared/
widgets/alert/custom_alert_dialog.dart'
;
import
'../
../shared/
widgets/alert/data_alert_model.dart'
;
enum
BiometricTypeEnum
{
none
,
...
...
lib/
preferen
ce/contact_storage_service.dart
→
lib/
core/servi
ce
s
/contact_storage_service.dart
View file @
6b980613
File moved
lib/core/deep_link_service.dart
→
lib/core/
services/
deep_link_service.dart
View file @
6b980613
import
'dart:async'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter_branch_sdk/flutter_branch_sdk.dart'
;
import
'package:mypoint_flutter_app/extensions/string_extension.dart'
;
import
'package:mypoint_flutter_app/
core/utils/
extensions/string_extension.dart'
;
import
'package:uni_links/uni_links.dart'
;
import
'package:mypoint_flutter_app/
direc
tion
al
/directional_screen.dart'
;
import
'package:mypoint_flutter_app/
extension
s/crypto.dart'
as
mycrypto
;
import
'../
directional
/directional_action_type.dart'
;
import
'package:mypoint_flutter_app/
shared/naviga
tion/directional_screen.dart'
;
import
'package:mypoint_flutter_app/
core/util
s/crypto.dart'
as
mycrypto
;
import
'../
../app/routing
/directional_action_type.dart'
;
class
DeepLinkService
{
DeepLinkService
.
_internal
();
...
...
@@ -17,6 +17,7 @@ class DeepLinkService {
bool
_initialized
=
false
;
Future
<
void
>
initialize
()
async
{
if
(
kIsWeb
)
return
;
if
(
_initialized
)
return
;
_initialized
=
true
;
debugPrint
(
'🔗 Initializing DeepLinkService...'
);
...
...
@@ -57,6 +58,10 @@ class DeepLinkService {
}
catch
(
_
)
{}
}
bool
handleIncomingUri
(
String
uri
)
{
return
_routeFromUriString
(
uri
)
??
false
;
}
void
_listenLinkStream
()
{
try
{
_linkSub
=
linkStream
.
listen
((
uri
)
{
...
...
@@ -67,10 +72,10 @@ class DeepLinkService {
}
// Firebase Dynamic Links removed due to version constraints.
void
_routeFromUriString
(
String
uriStr
)
{
bool
?
_routeFromUriString
(
String
uriStr
)
{
debugPrint
(
'🔗 Deep link received:
$uriStr
'
);
final
uri
=
Uri
.
tryParse
(
uriStr
);
if
(
uri
==
null
)
return
;
if
(
uri
==
null
)
return
false
;
final
type
=
uri
.
queryParameters
[
Defines
.
actionType
]
??
uri
.
queryParameters
[
'action_type'
];
final
param
=
uri
.
queryParameters
[
Defines
.
actionParams
]
??
uri
.
queryParameters
[
'action_param'
];
...
...
@@ -91,13 +96,12 @@ class DeepLinkService {
direction
?.
extraData
=
{
'password'
:
param
,
};
direction
?.
begin
();
return
;
// Use if you need to attach to userInfo later
return
direction
?.
begin
();
// Use if you need to attach to userInfo later
}
}
}
final
screen
=
DirectionalScreen
.
build
(
clickActionType:
type
,
clickActionParam:
param
);
screen
?.
begin
();
return
screen
?.
begin
();
}
void
_handleBranchSession
(
Map
<
dynamic
,
dynamic
>
data
)
{
...
...
lib/co
nfig
s/device_info.dart
→
lib/co
re/service
s/device_info.dart
View file @
6b980613
File moved
lib/services/login_service.dart
→
lib/
core/
services/login_service.dart
View file @
6b980613
import
'package:flutter/foundation.dart'
;
import
'package:mypoint_flutter_app/
base
/base_response_model.dart'
;
import
'package:mypoint_flutter_app/config
s
/constants.dart'
;
import
'package:mypoint_flutter_app/network
ing
/restful_api_client_all_request.dart'
;
import
'package:mypoint_flutter_app/preference/data_preference.dart'
;
import
'package:mypoint_flutter_app/
shared/widgets/base_view
/base_response_model.dart'
;
import
'package:mypoint_flutter_app/
app/
config/constants.dart'
;
import
'package:mypoint_flutter_app/
core/
network/restful_api_client_all_request.dart'
;
import
'package:mypoint_flutter_app/
shared/
preference
s
/data_preference.dart'
;
import
'../firebase/push_token_service.dart'
;
import
'../model
/auth
/login_token_response_model.dart'
;
import
'../network
ing
/restful_api_viewmodel.dart'
;
import
'../
../features/login/
model/login_token_response_model.dart'
;
import
'../network/restful_api_viewmodel.dart'
;
/// Login result enum để handle các trạng thái khác nhau
enum
LoginResult
{
...
...
@@ -43,15 +43,12 @@ class LoginService extends RestfulApiViewModel {
try
{
// Step 1: Authenticate user
final
authResponse
=
await
client
.
login
(
phone
,
password
);
if
(!
authResponse
.
isSuccess
||
authResponse
.
data
==
null
)
{
debugPrint
(
'Login failed:
${authResponse.errorMessage}
'
);
return
_handleAuthError
(
authResponse
);
}
// Step 2: Save token
await
DataPreference
.
instance
.
saveLoginToken
(
authResponse
.
data
!);
// Step 3: Get user profile (critical step)
final
profileResult
=
await
_getUserProfileWithRetry
();
if
(
profileResult
.
result
!=
LoginResult
.
success
)
{
...
...
@@ -62,16 +59,13 @@ class LoginService extends RestfulApiViewModel {
message:
profileResult
.
message
??
Constants
.
commonError
,
);
}
// Step 4: Upload FCM token (non-critical, don't fail login if this fails)
await
_uploadFCMTokenSafely
();
return
LoginResponse
(
result:
LoginResult
.
success
);
}
catch
(
e
)
{
return
LoginResponse
(
result:
LoginResult
.
networkError
,
message:
'Đăng nhập thất bại:
${e.toString()}
'
,
message:
ErrorCodes
.
commonError
,
);
}
}
...
...
@@ -120,12 +114,10 @@ class LoginService extends RestfulApiViewModel {
for
(
int
attempt
=
1
;
attempt
<=
maxRetries
;
attempt
++)
{
try
{
final
response
=
await
client
.
getUserProfile
();
if
(
response
.
isSuccess
&&
response
.
data
!=
null
)
{
await
DataPreference
.
instance
.
saveUserProfile
(
response
.
data
!);
return
LoginResponse
(
result:
LoginResult
.
success
);
}
// If not last attempt, wait before retry
if
(
attempt
<
maxRetries
)
{
await
Future
.
delayed
(
Duration
(
seconds:
attempt
*
2
));
...
...
@@ -134,16 +126,16 @@ class LoginService extends RestfulApiViewModel {
if
(
attempt
==
maxRetries
)
{
return
LoginResponse
(
result:
LoginResult
.
networkError
,
message:
'Không thể tải thông tin người dùng:
${e.toString()}
'
,
message:
ErrorCodes
.
commonError
,
);
}
await
Future
.
delayed
(
Duration
(
seconds:
attempt
*
2
));
}
}
debugPrint
(
'Failed to fetch user profile after
$maxRetries
attempts'
);
return
LoginResponse
(
result:
LoginResult
.
networkError
,
message:
'Không thể tải thông tin người dùng sau
$maxRetries
lần thử'
,
message:
ErrorCodes
.
commonError
,
);
}
...
...
@@ -161,13 +153,10 @@ class LoginService extends RestfulApiViewModel {
Future
<
LoginResponse
>
biometricLogin
(
String
phone
)
async
{
try
{
final
response
=
await
client
.
loginWithBiometric
(
phone
);
if
(!
response
.
isSuccess
||
response
.
data
==
null
)
{
return
_handleAuthError
(
response
);
}
await
DataPreference
.
instance
.
saveLoginToken
(
response
.
data
!);
final
profileResult
=
await
_getUserProfileWithRetry
();
if
(
profileResult
.
result
!=
LoginResult
.
success
)
{
await
DataPreference
.
instance
.
clearLoginToken
();
...
...
@@ -176,14 +165,12 @@ class LoginService extends RestfulApiViewModel {
message:
profileResult
.
message
??
Constants
.
commonError
,
);
}
await
_uploadFCMTokenSafely
();
return
LoginResponse
(
result:
LoginResult
.
success
);
}
catch
(
e
)
{
return
LoginResponse
(
result:
LoginResult
.
networkError
,
message:
'Đăng nhập sinh trắc thất bại:
${e.toString()}
'
,
message:
ErrorCodes
.
commonError
,
);
}
}
...
...
lib/services/logout_service.dart
→
lib/
core/
services/logout_service.dart
View file @
6b980613
import
'package:flutter/foundation.dart'
;
import
'../networking/dio_http_service.dart'
;
import
'../networking/restful_api_client.dart'
;
import
'../networking/restful_api_client_all_request.dart'
;
import
'../preference/data_preference.dart'
;
import
'../network/dio_http_service.dart'
;
import
'../network/restful_api_client.dart'
;
import
'../network/restful_api_client_all_request.dart'
;
import
'../../shared/preferences/data_preference.dart'
;
class
LogoutService
{
LogoutService
.
_
();
...
...
lib/
preferen
ce/package_info.dart
→
lib/
core/servi
ce
s
/package_info.dart
View file @
6b980613
File moved
lib/services/token_refresh_service.dart
→
lib/
core/
services/token_refresh_service.dart
View file @
6b980613
import
'package:flutter/widgets.dart'
;
import
'package:mypoint_flutter_app/extensions/string_extension.dart'
;
import
'package:mypoint_flutter_app/network
ing
/restful_api_client_all_request.dart'
;
import
'../config
s
/constants.dart'
;
import
'../model
/auth
/login_token_response_model.dart'
;
import
'../network
ing
/restful_api_viewmodel.dart'
;
import
'../preference/data_preference.dart'
;
import
'../
base
/app_navigator.dart'
;
import
'package:mypoint_flutter_app/
core/utils/
extensions/string_extension.dart'
;
import
'package:mypoint_flutter_app/
core/
network/restful_api_client_all_request.dart'
;
import
'../
../app/
config/constants.dart'
;
import
'../
../features/login/
model/login_token_response_model.dart'
;
import
'../network/restful_api_viewmodel.dart'
;
import
'../
../shared/
preference
s
/data_preference.dart'
;
import
'../
../app/routing
/app_navigator.dart'
;
class
TokenRefreshService
extends
RestfulApiViewModel
{
static
final
TokenRefreshService
_instance
=
TokenRefreshService
.
_internal
();
...
...
lib/web/web_helper.dart
→
lib/
core/services/
web/web_helper.dart
View file @
6b980613
File moved
lib/web/web_helper_stub.dart
→
lib/
core/services/
web/web_helper_stub.dart
View file @
6b980613
...
...
@@ -41,6 +41,10 @@ void webResetSDK() {
// no-op on non-web
}
void
webNotifySplashScreenReady
(
)
{
// no-op on non-web
}
Future
<
dynamic
>
webConfigUIApp
(
Map
<
String
,
dynamic
>
config
)
async
{
return
null
;
}
...
...
lib/web/web_helper_web.dart
→
lib/
core/services/
web/web_helper_web.dart
View file @
6b980613
// Web-specific implementations for x-app-sdk
import
'dart:html'
as
html
;
import
'package:flutter/foundation.dart'
;
import
'x_app_sdk_service.dart'
;
...
...
@@ -81,6 +82,14 @@ void webResetSDK() {
}
}
void
webNotifySplashScreenReady
(
)
{
try
{
html
.
window
.
dispatchEvent
(
html
.
CustomEvent
(
'mypoint-splash-ready'
));
}
catch
(
e
)
{
debugPrint
(
'❌ Error notifying splash readiness:
$e
'
);
}
}
Future
<
dynamic
>
webConfigUIApp
(
Map
<
String
,
dynamic
>
config
)
async
{
try
{
return
await
XAppSDKService
().
configUIApp
(
config
);
...
...
lib/web/x_app_sdk_service.dart
→
lib/
core/services/
web/x_app_sdk_service.dart
View file @
6b980613
File moved
lib/
resources
/base_color.dart
→
lib/
core/theme
/base_color.dart
View file @
6b980613
File moved
Prev
1
2
3
4
5
6
7
…
26
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