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
a7abbe4d
Commit
a7abbe4d
authored
Nov 27, 2025
by
DatHV
Browse files
fix bug change profile when logout
parent
2cf5375a
Changes
7
Show whitespace changes
Inline
Side-by-side
lib/app/config/constants.dart
View file @
a7abbe4d
...
...
@@ -8,9 +8,11 @@ class Constants {
static
const
timeoutSeconds
=
30
;
static
const
appStoreId
=
'1495923300'
;
static
double
get
extendTopPaddingNavigation
{
print
(
'extendTopPaddingNavigation:
$kIsWeb
'
);
return
kIsWeb
?
24.0
:
0.0
;
}
static
double
get
extendTopPaddingNavigationButton
{
return
kIsWeb
?
8.0
:
0.0
;
}
}
class
ErrorCodes
{
...
...
lib/features/interested_categories/interestied_categories_screen.dart
View file @
a7abbe4d
import
'package:flutter/material.dart'
;
import
'package:get/get.dart'
;
import
'package:get/get_core/src/get_main.dart'
;
import
'package:get/get_state_manager/src/rx_flutter/rx_obx_widget.dart'
;
import
'package:mypoint_flutter_app/shared/widgets/custom_empty_widget.dart'
;
import
'../../shared/widgets/base_view/base_screen.dart'
;
...
...
@@ -21,10 +23,17 @@ class _InterestCategoriesScreenState extends BaseState<InterestCategoriesScreen>
@override
void
initState
()
{
super
.
initState
();
_viewModel
.
onShowAlertError
=
(
message
)
{
if
(
message
.
isNotEmpty
)
{
showAlertError
(
content:
message
,
headerImage:
"assets/images/ic_pipi_05.png"
);
_viewModel
.
onShowAlertError
=
(
message
,
onBack
)
{
if
(
message
.
isEmpty
)
return
;
showAlertError
(
content:
message
,
headerImage:
"assets/images/ic_pipi_05.png"
,
onConfirmed:
onBack
?
()
{
Get
.
back
();
}
:
null
,
);
};
_viewModel
.
getInterestedCategories
();
}
...
...
lib/features/interested_categories/interestied_categories_viewmodel.dart
View file @
a7abbe4d
...
...
@@ -8,7 +8,7 @@ class InterestedCategoriesViewModel extends RestfulApiViewModel {
final
Rxn
<
InterestedCategoriesResponse
>
interestedCategories
=
Rxn
<
InterestedCategoriesResponse
>();
Set
<
String
>
selectedIds
=
{};
void
Function
(
String
message
)?
onShowAlertError
;
void
Function
(
String
message
,
bool
onBack
)?
onShowAlertError
;
Future
<
void
>
getInterestedCategories
()
async
{
await
callApi
<
InterestedCategoriesResponse
>(
...
...
@@ -25,7 +25,7 @@ class InterestedCategoriesViewModel extends RestfulApiViewModel {
interestedCategories
.
value
=
data
;
},
onFailure:
(
msg
,
_
,
_
)
async
{
onShowAlertError
?.
call
(
msg
);
onShowAlertError
?.
call
(
msg
,
false
);
},
);
}
...
...
@@ -35,11 +35,11 @@ class InterestedCategoriesViewModel extends RestfulApiViewModel {
await
callApi
<
EmptyCodable
>(
request:
()
=>
client
.
submitCategorySubscribe
(
categories
.
join
(
','
)),
onSuccess:
(
data
,
_
)
{
onShowAlertError
?.
call
(
"Cập nhật sở thích thành công"
);
onShowAlertError
?.
call
(
"Cập nhật sở thích thành công"
,
true
);
_handleUnsubscribeCategories
(
categories
);
},
onFailure:
(
msg
,
_
,
_
)
async
{
onShowAlertError
?.
call
(
msg
);
onShowAlertError
?.
call
(
msg
,
false
);
},
);
}
...
...
lib/features/splash/splash_screen_viewmodel.dart
View file @
a7abbe4d
...
...
@@ -45,19 +45,17 @@ class SplashScreenViewModel extends RestfulApiViewModel {
Future
<
void
>
makeDataFollowInitApp
()
async
{
try
{
if
(
kIsWeb
)
{
final
token
=
await
_getTokenFromSDK
();
if
(
token
.
orEmpty
.
isNotEmpty
)
{
await
DataPreference
.
instance
.
saveLoginToken
(
LoginTokenResponseModel
(
accessToken:
token
));
}
}
if
(
DataPreference
.
instance
.
logged
)
{
await
_loadProfileAndNavigate
();
return
;
}
final
token
=
await
_getTokenFromSDK
();
if
(
token
.
orEmpty
.
isEmpty
)
{
}
else
{
directionWhenTokenInvalid
();
return
;
}
await
DataPreference
.
instance
.
saveLoginToken
(
LoginTokenResponseModel
(
accessToken:
token
));
await
_loadProfileAndNavigate
();
}
on
Object
catch
(
e
)
{
debugPrint
(
'❌ SplashScreen - makeDataFollowInitApp error:
$e
'
);
DataPreference
.
instance
.
clearLoginToken
();
...
...
@@ -156,7 +154,7 @@ class SplashScreenViewModel extends RestfulApiViewModel {
void
_goToMain
()
{
if
(
Get
.
currentRoute
==
mainScreen
)
return
;
if
(
Get
.
currentRoute
==
onboardingScreen
)
{
if
(
kIsWeb
||
Get
.
currentRoute
==
onboardingScreen
)
{
Get
.
offNamed
(
mainScreen
);
}
else
{
Get
.
offAllNamed
(
mainScreen
);
...
...
lib/features/traffic_service/traffic_service_certificate_screen.dart
View file @
a7abbe4d
import
'dart:io'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:mypoint_flutter_app/shared/widgets/custom_toast_message.dart'
;
import
'package:share_plus/share_plus.dart'
;
import
'package:url_launcher/url_launcher.dart'
;
import
'package:webview_flutter/webview_flutter.dart'
;
import
'package:path_provider/path_provider.dart'
;
import
'package:http/http.dart'
as
http
;
...
...
@@ -33,6 +36,27 @@ class _TrafficServiceCertificateScreenState extends BaseState<TrafficServiceCert
@override
void
initState
()
{
super
.
initState
();
if
(
kIsWeb
)
{
_openUrlInBrowser
();
}
else
{
_initializeWebView
();
}
}
Future
<
void
>
_openUrlInBrowser
()
async
{
Future
.
microtask
(()
async
{
final
uri
=
Uri
.
parse
(
widget
.
urlView
);
if
(
await
canLaunchUrl
(
uri
))
{
await
launchUrl
(
uri
,
mode:
LaunchMode
.
externalApplication
);
}
else
if
(
mounted
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'Không thể mở giấy chứng nhận'
)),
);
}
});
}
void
_initializeWebView
()
{
AppLoading
().
show
();
_controller
=
WebViewController
()
..
loadRequest
(
Uri
.
parse
(
widget
.
urlView
))
...
...
@@ -53,7 +77,7 @@ class _TrafficServiceCertificateScreenState extends BaseState<TrafficServiceCert
Widget
createBody
()
{
return
Scaffold
(
appBar:
CustomNavigationBar
(
title:
"Giấy chứng nhận cứu hộ VNTRA"
),
body:
WebViewWidget
(
controller:
_controller
),
body:
kIsWeb
?
_WebFallback
(
onRetry:
_openUrlInBrowser
)
:
WebViewWidget
(
controller:
_controller
),
bottomNavigationBar:
_buildBottomButtonEditMode
(),
);
}
...
...
@@ -86,29 +110,6 @@ class _TrafficServiceCertificateScreenState extends BaseState<TrafficServiceCert
);
}
// Future<void> _savePdfToFiles() async {
// final url = widget.urlDownload;
// final licensePlate = widget.licensePlate;
// try {
// final response = await http.get(Uri.parse(url));
// if (response.statusCode == 200) {
// typed_data.Uint8List bytes = response.bodyBytes;
// final fileName = 'MyPoint-Cer-$licensePlate.pdf';
//
// await FileSaver.instance.saveFile(
// name: fileName,
// bytes: bytes,
// ext: 'pdf',
// mimeType: MimeType.pdf,
// );
// } else {
// print("Tải file thất bại");
// }
// } catch (e) {
// print("Lỗi: $e");
// }
// }
Future
<
void
>
_savePdfToFiles
()
async
{
final
url
=
widget
.
urlDownload
;
final
licensePlate
=
widget
.
licensePlate
;
...
...
@@ -117,52 +118,46 @@ class _TrafficServiceCertificateScreenState extends BaseState<TrafficServiceCert
if
(
response
.
statusCode
==
200
)
{
typed_data
.
Uint8List
bytes
=
response
.
bodyBytes
;
final
dir
=
await
getTemporaryDirectory
();
final
filePath
=
'
${dir.path}
/MyPoint-Cer-
$licensePlate
.pdf'
;
final
filePath
=
'
${dir.path}
/MyPoint-Cer-
$licensePlate
-
${DateTime.now().toString()}
.pdf'
;
final
file
=
File
(
filePath
);
await
file
.
writeAsBytes
(
bytes
);
await
Share
.
shareXFiles
([
XFile
(
filePath
)],
text:
'Giấy chứng nhận cứu hộ'
);
showToastMessage
(
'Lưu file thành công'
);
}
else
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'Tải file thất bại'
)),
);
showToastMessage
(
'Tải file thất bại'
);
}
}
catch
(
e
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'Lỗi:
$e
'
)),
);
showToastMessage
(
'Tải file thất bại'
);
}
}
}
Future
<
void
>
_savePdf
()
async
{
final
url
=
widget
.
urlDownload
;
final
licensePlate
=
widget
.
licensePlate
;
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'Đang tải PDF...'
)),
);
try
{
final
response
=
await
http
.
get
(
Uri
.
parse
(
url
));
if
(
response
.
statusCode
==
200
)
{
final
dir
=
await
getApplicationDocumentsDirectory
();
String
baseName
=
'MyPoint-Cer-
$licensePlate
.pdf'
;
String
path
=
'
${dir.path}
/
$baseName
'
;
int
count
=
0
;
while
(
File
(
path
).
existsSync
())
{
path
=
'
${dir.path}
/MyPoint-Cer-
$licensePlate
-
${count++}
.pdf'
;
}
final
file
=
File
(
path
);
await
file
.
writeAsBytes
(
response
.
bodyBytes
);
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'Lưu file thành công:
\n
${file.path}
'
)),
);
}
else
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
const
SnackBar
(
content:
Text
(
'Tải file thất bại'
)),
);
}
}
catch
(
e
)
{
ScaffoldMessenger
.
of
(
context
).
showSnackBar
(
SnackBar
(
content:
Text
(
'Lỗi:
$e
'
)),
class
_WebFallback
extends
StatelessWidget
{
final
VoidCallback
onRetry
;
const
_WebFallback
({
required
this
.
onRetry
});
@override
Widget
build
(
BuildContext
context
)
{
return
Center
(
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
children:
[
const
Padding
(
padding:
EdgeInsets
.
symmetric
(
horizontal:
24.0
),
child:
Text
(
'Giấy chứng nhận đang được mở trong tab trình duyệt mới. '
'Nếu không tự mở, vui lòng chọn "Mở lại" hoặc sử dụng nút Lưu file.'
,
textAlign:
TextAlign
.
center
,
),
),
const
SizedBox
(
height:
16
),
ElevatedButton
(
onPressed:
onRetry
,
child:
const
Text
(
'Mở lại'
),
),
],
),
);
}
}
}
\ No newline at end of file
lib/shared/widgets/custom_navigation_bar.dart
View file @
a7abbe4d
...
...
@@ -91,9 +91,9 @@ class CustomNavigationBar extends StatelessWidget implements PreferredSizeWidget
),
),
if
(
leftButtons
.
isNotEmpty
)
Positioned
(
left:
12
,
child:
Row
(
mainAxisSize:
MainAxisSize
.
min
,
children:
leftButtons
)),
Positioned
(
left:
12
,
top:
Constants
.
extendTopPaddingNavigationButton
,
child:
Row
(
mainAxisSize:
MainAxisSize
.
min
,
children:
leftButtons
)),
if
(
rightButtons
.
isNotEmpty
)
Positioned
(
right:
8
,
child:
Row
(
mainAxisSize:
MainAxisSize
.
min
,
children:
rightButtons
)),
Positioned
(
right:
8
,
top:
Constants
.
extendTopPaddingNavigationButton
,
child:
Row
(
mainAxisSize:
MainAxisSize
.
min
,
children:
rightButtons
)),
],
),
),
...
...
lib/shared/widgets/custom_search_navigation_bar.dart
View file @
a7abbe4d
...
...
@@ -122,9 +122,9 @@ class _CustomSearchNavigationBarState extends State<CustomSearchNavigationBar> {
),
),
),
if
(
widget
.
showBackButton
)
Positioned
(
left:
12
,
child:
CustomBackButton
()),
if
(
widget
.
showBackButton
)
Positioned
(
left:
12
,
top:
Constants
.
extendTopPaddingNavigationButton
,
child:
CustomBackButton
()),
if
(
widget
.
rightButtons
.
isNotEmpty
)
Positioned
(
right:
12
,
child:
Row
(
mainAxisSize:
MainAxisSize
.
min
,
children:
widget
.
rightButtons
)),
Positioned
(
right:
12
,
top:
Constants
.
extendTopPaddingNavigationButton
,
child:
Row
(
mainAxisSize:
MainAxisSize
.
min
,
children:
widget
.
rightButtons
)),
],
),
),
...
...
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