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
abd9f02e
Commit
abd9f02e
authored
Feb 28, 2025
by
DatHV
Browse files
update screen
parent
e41fc4fe
Changes
38
Hide whitespace changes
Inline
Side-by-side
lib/onboading/model/onboarding_info_model.dart
0 → 100644
View file @
abd9f02e
import
'package:json_annotation/json_annotation.dart'
;
part
'onboarding_info_model.g.dart'
;
@JsonSerializable
()
class
OnboardingInfoModel
{
final
String
?
url
;
final
String
?
content
;
OnboardingInfoModel
({
this
.
url
,
this
.
content
});
factory
OnboardingInfoModel
.
fromJson
(
Map
<
String
,
dynamic
>
json
)
=>
_$OnboardingInfoModelFromJson
(
json
);
Map
<
String
,
dynamic
>
toJson
()
=>
_$OnboardingInfoModelToJson
(
this
);
}
\ No newline at end of file
lib/onboading/model/onboarding_info_model.g.dart
0 → 100644
View file @
abd9f02e
// GENERATED CODE - DO NOT MODIFY BY HAND
part of
'onboarding_info_model.dart'
;
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
OnboardingInfoModel
_$OnboardingInfoModelFromJson
(
Map
<
String
,
dynamic
>
json
)
=>
OnboardingInfoModel
(
url:
json
[
'url'
]
as
String
?,
content:
json
[
'content'
]
as
String
?,
);
Map
<
String
,
dynamic
>
_$OnboardingInfoModelToJson
(
OnboardingInfoModel
instance
,
)
=>
<
String
,
dynamic
>{
'url'
:
instance
.
url
,
'content'
:
instance
.
content
};
lib/onboading/onboarding_screen.dart
View file @
abd9f02e
import
'package:flutter/material.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_widget_from_html/flutter_widget_from_html.dart'
;
// Hiển thị HTML
import
'package:flutter_widget_from_html/flutter_widget_from_html.dart'
;
// Hiển thị HTML
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/base/base_response_model.dart'
;
import
'../base/base_screen.dart'
;
import
'../base/basic_state.dart'
;
import
'../configs/constants.dart'
;
import
'../resouce/base_color.dart'
;
import
'model/check_phone_response_model.dart'
;
import
'onboarding_viewmodel.dart'
;
import
'onboarding_viewmodel.dart'
;
class
OnboardingScreen
extends
StatelessWidget
{
class
OnboardingScreen
extends
BaseScreen
{
final
OnboardingViewModel
controller
=
Get
.
find
<
OnboardingViewModel
>();
const
OnboardingScreen
({
super
.
key
});
@override
State
<
OnboardingScreen
>
createState
()
=>
_OnboardingScreenState
();
}
class
_OnboardingScreenState
extends
BaseState
<
OnboardingScreen
>
with
BasicState
{
final
OnboardingViewModel
_viewModel
=
Get
.
find
<
OnboardingViewModel
>();
final
FocusNode
_focusNode
=
FocusNode
();
final
FocusNode
_focusNode
=
FocusNode
();
void
hideKeyboard
()
{
@override
void
initState
()
{
super
.
initState
();
_viewModel
.
fetchOnboardingContent
();
_viewModel
.
checkPhoneRes
.
listen
((
response
)
{
_handleResponseCheckPhoneNumber
(
response
.
data
);
_handleResponseError
(
response
);
});
}
void
_handleResponseError
(
BaseResponseModel
<
CheckPhoneResponseModel
>?
response
)
{
if
(
response
?.
isSuccess
??
false
)
return
;
var
errorCode
=
response
?.
errorCode
??
""
;
var
errorMessage
=
response
?.
errorMessage
??
Constants
.
commonError
;
WidgetsBinding
.
instance
.
addPostFrameCallback
((
_
)
{
showAlertError
(
errorMessage
);
if
(
errorCode
==
ErrorCodes
.
deviceLock
)
{
// show alert error popupErrorCSKH
return
;
}
//show alert error popupError
});
}
void
_handleResponseCheckPhoneNumber
(
CheckPhoneResponseModel
?
response
)
{
if
(
response
==
null
)
return
;
if
(
response
.
requireRecaptcha
==
true
)
{
// show Captcha
return
;
}
if
((
response
.
mfaToken
??
""
).
isNotEmpty
)
{
// show OTP
return
;
}
if
(
response
.
nextAction
==
"login"
)
{
return
;
}
if
(
response
.
nextAction
==
"signup"
)
{
return
;
}
}
void
_hideKeyboard
()
{
FocusScope
.
of
(
Get
.
context
!).
unfocus
();
FocusScope
.
of
(
Get
.
context
!).
unfocus
();
}
}
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
createBody
(
)
{
return
GestureDetector
(
return
GestureDetector
(
onTap:
hideKeyboard
,
onTap:
_
hideKeyboard
,
child:
Scaffold
(
child:
Scaffold
(
resizeToAvoidBottomInset:
false
,
resizeToAvoidBottomInset:
false
,
body:
Stack
(
body:
Stack
(
children:
[
children:
[
/// 📌 Hiển thị background từ API (hoặc ảnh mặc định)
/// 📌 Hiển thị background từ API (hoặc ảnh mặc định)
Obx
(()
=>
Positioned
.
fill
(
Obx
(
child:
controller
.
backgroundUrl
.
value
.
isNotEmpty
()
=>
Positioned
.
fill
(
?
Image
.
network
(
controller
.
backgroundUrl
.
value
,
fit:
BoxFit
.
cover
)
child:
:
Image
.
asset
(
"assets/images/bg_onboarding.png"
,
fit:
BoxFit
.
cover
),
_viewModel
.
url
.
isNotEmpty
)),
?
Image
.
network
(
_viewModel
.
url
,
fit:
BoxFit
.
cover
)
:
Image
.
asset
(
"assets/images/bg_onboarding.png"
,
fit:
BoxFit
.
cover
),
),
),
/// 📌 Nội dung chính
/// 📌 Nội dung chính
AnimatedPadding
(
AnimatedPadding
(
duration:
const
Duration
(
milliseconds:
30
0
),
duration:
const
Duration
(
milliseconds:
12
0
),
padding:
EdgeInsets
.
only
(
bottom:
MediaQuery
.
of
(
context
).
viewInsets
.
bottom
),
padding:
EdgeInsets
.
only
(
bottom:
MediaQuery
.
of
(
context
).
viewInsets
.
bottom
),
child:
Column
(
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
end
,
mainAxisAlignment:
MainAxisAlignment
.
end
,
children:
[
children:
[
Container
(
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
20
,
vertical:
3
0
),
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
3
2
),
decoration:
const
BoxDecoration
(
//
decoration: const BoxDecoration(
color:
Colors
.
redAccent
,
//
color: Colors.redAccent,
borderRadius:
BorderRadius
.
only
(
//
borderRadius: BorderRadius.only(
topLeft:
Radius
.
circular
(
30
),
//
topLeft: Radius.circular(30),
topRight:
Radius
.
circular
(
30
),
//
topRight: Radius.circular(30),
),
//
),
),
//
),
child:
Column
(
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
start
,
crossAxisAlignment:
CrossAxisAlignment
.
start
,
mainAxisSize:
MainAxisSize
.
min
,
mainAxisSize:
MainAxisSize
.
min
,
children:
[
children:
[
/// 📌 Tiêu đề (Hiển thị nội dung HTML từ API hoặc mặc định)
/// 📌 Tiêu đề (Hiển thị nội dung HTML từ API hoặc mặc định)
Obx
(()
=>
Visibility
(
Obx
(
visible:
!
_focusNode
.
hasFocus
,
()
=>
Visibility
(
child:
HtmlWidget
(
visible:
!
_focusNode
.
hasFocus
,
controller
.
contentHtml
.
value
.
isNotEmpty
child:
HtmlWidget
(
?
controller
.
contentHtml
.
value
_viewModel
.
content
.
isNotEmpty
:
"""<h2 style="
color:
white
;
">Tiêu điểm dễ - Trừ tiền mê</h2>
?
_viewModel
.
content
:
"""<h4 style="
color:
white
;
">Tiêu điểm dễ - Trừ tiền mê</h4>
<p style="
color:
white
;
">Đừng bỏ lỡ cơ hội tích tới 30% tất cả giao dịch viễn thông
<p style="
color:
white
;
">Đừng bỏ lỡ cơ hội tích tới 30% tất cả giao dịch viễn thông
của các nhà mạng và đổi phiếu giảm giá tại hơn 200 thương hiệu được yêu thích nhất.</p>"""
,
của các nhà mạng và đổi phiếu giảm giá tại hơn 200 thương hiệu được yêu thích nhất.</p>"""
,
textStyle:
TextStyle
(
color:
Colors
.
white
),
),
),
),
)),
),
const
SizedBox
(
height:
16
),
/// 📌 Ô nhập số điện thoại
/// 📌 Ô nhập số điện thoại
TextField
(
TextField
(
inputFormatters:
[
LengthLimitingTextInputFormatter
(
10
)
],
// maxLength: 10,
focusNode:
_focusNode
,
focusNode:
_focusNode
,
keyboardType:
TextInputType
.
phone
,
keyboardType:
TextInputType
.
phone
,
style:
const
TextStyle
(
color:
Color
s
.
black
),
style:
const
TextStyle
(
color:
Base
Color
.
second600
),
decoration:
InputDecoration
(
decoration:
InputDecoration
(
filled:
true
,
filled:
true
,
fillColor:
Colors
.
white
,
fillColor:
Colors
.
white
,
...
@@ -72,55 +140,58 @@ class OnboardingScreen extends StatelessWidget {
...
@@ -72,55 +140,58 @@ class OnboardingScreen extends StatelessWidget {
borderRadius:
BorderRadius
.
circular
(
10
),
borderRadius:
BorderRadius
.
circular
(
10
),
borderSide:
BorderSide
.
none
,
borderSide:
BorderSide
.
none
,
),
),
prefixIcon:
const
Icon
(
Icons
.
phone
,
color:
Color
s
.
black
),
prefixIcon:
const
Icon
(
Icons
.
phone
,
color:
Color
(
0xFF9DA4AE
))
),
),
onChanged:
controller
.
updatePhoneNumber
,
onChanged:
_viewModel
.
updatePhoneNumber
,
),
),
const
SizedBox
(
height:
20
),
const
SizedBox
(
height:
16
),
/// 📌 Nút Tiếp Tục
/// 📌 Nút Tiếp Tục
Obx
(()
=>
SizedBox
(
Obx
(
width:
double
.
infinity
,
()
=>
SizedBox
(
child:
ElevatedButton
(
width:
double
.
infinity
,
onPressed:
controller
.
isButtonEnabled
child:
ElevatedButton
(
?
()
{
onPressed:
debugPrint
(
"Số điện thoại:
${controller.phoneNumber.value}
"
);
_viewModel
.
isButtonEnabled
}
?
()
{
:
null
,
_viewModel
.
checkPhoneNumber
();
style:
ElevatedButton
.
styleFrom
(
}
padding:
const
EdgeInsets
.
symmetric
(
vertical:
15
),
:
null
,
backgroundColor:
controller
.
isButtonEnabled
?
Colors
.
white
:
Colors
.
white54
,
style:
ElevatedButton
.
styleFrom
(
shape:
RoundedRectangleBorder
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
15
),
borderRadius:
BorderRadius
.
circular
(
10
),
backgroundColor:
_viewModel
.
isButtonEnabled
?
Colors
.
white
:
Colors
.
white54
,
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
10
)),
),
),
),
child:
Text
(
child:
Text
(
"Tiếp tục"
,
"Tiếp tục"
,
style:
TextStyle
(
style:
TextStyle
(
color:
_viewModel
.
isButtonEnabled
?
BaseColor
.
second600
:
BaseColor
.
second400
,
color:
controller
.
isButtonEnabled
?
Colors
.
redAccent
:
Colors
.
grey
,
fontSize:
18
,
font
Size:
18
,
font
Weight:
FontWeight
.
bold
,
fontWeight:
FontWeight
.
bold
,
)
,
),
),
),
),
),
),
)
),
),
const
SizedBox
(
height:
1
0
),
const
SizedBox
(
height:
1
6
),
/// 📌 Checkbox + Điều khoản sử dụng + Chính sách bảo mật
/// 📌 Checkbox + Điều khoản sử dụng + Chính sách bảo mật
Row
(
Row
(
crossAxisAlignment:
CrossAxisAlignment
.
center
,
crossAxisAlignment:
CrossAxisAlignment
.
center
,
children:
[
children:
[
Obx
(()
=>
Checkbox
(
Obx
(
value:
controller
.
isChecked
.
value
,
()
=>
Checkbox
(
onChanged:
controller
.
toggleCheckbox
,
value:
_viewModel
.
isChecked
.
value
,
activeColor:
Colors
.
white
,
onChanged:
_viewModel
.
toggleCheckbox
,
checkColor:
Colors
.
red
,
activeColor:
Colors
.
white
,
side:
const
BorderSide
(
color:
Colors
.
white
,
width:
2
),
checkColor:
Colors
.
red
,
)),
side:
const
BorderSide
(
color:
Colors
.
white
,
width:
2
),
),
),
Expanded
(
Expanded
(
child:
RichText
(
child:
RichText
(
text:
TextSpan
(
text:
TextSpan
(
style:
const
TextStyle
(
color:
Colors
.
white
70
,
fontSize:
1
2
),
style:
const
TextStyle
(
color:
Colors
.
white
,
fontSize:
1
4
),
children:
[
children:
[
const
TextSpan
(
text:
"Bằng việc tiếp tục, bạn đã đọc và đồng ý với "
),
const
TextSpan
(
text:
"Bằng việc tiếp tục, bạn đã đọc và đồng ý với "
),
WidgetSpan
(
WidgetSpan
(
...
@@ -130,6 +201,8 @@ class OnboardingScreen extends StatelessWidget {
...
@@ -130,6 +201,8 @@ class OnboardingScreen extends StatelessWidget {
"Điều khoản sử dụng"
,
"Điều khoản sử dụng"
,
style:
TextStyle
(
style:
TextStyle
(
decoration:
TextDecoration
.
underline
,
decoration:
TextDecoration
.
underline
,
decorationColor:
Colors
.
white
,
decorationThickness:
2
,
color:
Colors
.
white
,
color:
Colors
.
white
,
),
),
),
),
...
@@ -143,6 +216,8 @@ class OnboardingScreen extends StatelessWidget {
...
@@ -143,6 +216,8 @@ class OnboardingScreen extends StatelessWidget {
"Chính sách bảo mật"
,
"Chính sách bảo mật"
,
style:
TextStyle
(
style:
TextStyle
(
decoration:
TextDecoration
.
underline
,
decoration:
TextDecoration
.
underline
,
decorationColor:
Colors
.
white
,
decorationThickness:
2
,
color:
Colors
.
white
,
color:
Colors
.
white
,
),
),
),
),
...
...
lib/onboading/onboarding_viewmodel.dart
View file @
abd9f02e
import
'package:get/get.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/extensions/string_extension.dart'
;
import
'package:mypoint_flutter_app/extensions/string_extension.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_request.dart'
;
import
'package:mypoint_flutter_app/onboading/model/check_phone_response_model.dart'
;
import
'../base/base_response_model.dart'
;
import
'../base/restful_api_viewmodel.dart'
;
import
'model/onboarding_info_model.dart'
;
class
OnboardingViewModel
extends
GetxController
{
class
OnboardingViewModel
extends
RestfulApiViewModel
{
var
info
=
BaseResponseModel
<
OnboardingInfoModel
>().
obs
;
var
checkPhoneRes
=
BaseResponseModel
<
CheckPhoneResponseModel
>().
obs
;
var
phoneNumber
=
""
.
obs
;
var
phoneNumber
=
""
.
obs
;
var
isChecked
=
false
.
obs
;
var
isChecked
=
false
.
obs
;
var
backgroundUrl
=
""
.
obs
;
// URL ảnh nền
var
contentHtml
=
""
.
obs
;
// Nội dung HTML
bool
get
isButtonEnabled
=>
isChecked
.
value
&&
phoneNumber
.
value
.
isPhoneValid
();
bool
get
isButtonEnabled
=>
isChecked
.
value
&&
phoneNumber
.
value
.
isPhoneValid
();
String
get
content
=>
info
?.
value
?.
data
?.
content
??
""
;
String
get
url
=>
info
?.
value
?.
data
?.
url
??
""
;
/// Cập nhật số điện thoại
void
updatePhoneNumber
(
String
value
)
{
void
updatePhoneNumber
(
String
value
)
{
phoneNumber
.
value
=
value
;
phoneNumber
.
value
=
value
;
}
}
/// Cập nhật trạng thái checkbox
void
toggleCheckbox
(
bool
?
value
)
{
void
toggleCheckbox
(
bool
?
value
)
{
isChecked
.
value
=
value
!;
isChecked
.
value
=
value
!;
}
}
/// Gọi API để lấy dữ liệu
Future
<
void
>
fetchOnboardingContent
()
async
{
Future
<
void
>
fetchOnboardingContent
()
async
{
var
data
=
{
""
:
""
};
client
.
getOnboardingInfo
().
then
((
value
)
{
backgroundUrl
.
value
=
data
[
"url_background"
]
??
backgroundUrl
.
value
;
// Nếu API có ảnh nền, thay thế
info
.
value
=
value
;
contentHtml
.
value
=
data
[
"content"
]
??
contentHtml
.
value
;
// Nếu API có nội dung, thay thế
});
}
Future
<
void
>
checkPhoneNumber
()
async
{
showLoading
();
client
.
checkPhoneNumber
(
phoneNumber
.
value
).
then
((
value
)
{
checkPhoneRes
.
value
=
value
;
hideLoading
();
});
}
}
@override
@override
...
...
lib/resouce/base_color.dart
0 → 100644
View file @
abd9f02e
import
'package:flutter/material.dart'
;
class
BaseColor
{
static
const
Color
backgroundColor
=
Colors
.
green
;
static
const
Color
second25
=
Color
(
0xFFFCFCFD
);
static
const
Color
second50
=
Color
(
0xFFF9FAFB
);
static
const
Color
second100
=
Color
(
0xFFF3F4F6
);
static
const
Color
second150
=
Color
(
0xFFEBEDEF
);
static
const
Color
second200
=
Color
(
0xFFE5E7EB
);
static
const
Color
second300
=
Color
(
0xFFD2D6DB
);
static
const
Color
second400
=
Color
(
0xFF9DA4AE
);
static
const
Color
second500
=
Color
(
0xFF6C737F
);
static
const
Color
second600
=
Color
(
0xFF4D5761
);
static
const
Color
second700
=
Color
(
0xFF384250
);
static
const
Color
second800
=
Color
(
0xFF1F2A37
);
static
const
Color
second900
=
Color
(
0xFF111927
);
static
const
Color
primary50
=
Color
(
0xFFFDE8EA
);
static
const
Color
primary100
=
Color
(
0xFFFAD2D4
);
static
const
Color
primary150
=
Color
(
0xFFF8BBBF
);
static
const
Color
primary200
=
Color
(
0xFFF5A5A9
);
static
const
Color
primary300
=
Color
(
0xFFF1777E
);
static
const
Color
primary400
=
Color
(
0xFFEC4A53
);
static
const
Color
primary500
=
Color
(
0xFFE71D28
);
static
const
Color
primary600
=
Color
(
0xFFB91720
);
static
const
Color
primary00
=
Color
(
0xFF8B1118
);
static
const
Color
primary800
=
Color
(
0xFF5C0C10
);
static
const
Color
primary900
=
Color
(
0xFF170304
);
static
const
Color
error25
=
Color
(
0xFFFFFBFA
);
static
const
Color
error50
=
Color
(
0xFFFEF3F2
);
static
const
Color
error100
=
Color
(
0xFFFEE4E2
);
static
const
Color
error200
=
Color
(
0xFFFECDCA
);
static
const
Color
error300
=
Color
(
0xFFFDA29B
);
static
const
Color
error400
=
Color
(
0xFFF97066
);
static
const
Color
error500
=
Color
(
0xFFF04438
);
static
const
Color
error600
=
Color
(
0xFFD92D20
);
static
const
Color
error700
=
Color
(
0xFFB42318
);
static
const
Color
error800
=
Color
(
0xFF912018
);
static
const
Color
error900
=
Color
(
0xFF7A271A
);
static
const
Color
error950
=
Color
(
0xFF55160C
);
static
const
Color
warning25
=
Color
(
0xFFFFFCF5
);
static
const
Color
warning50
=
Color
(
0xFFFFFAEB
);
static
const
Color
warning100
=
Color
(
0xFFFEF0C7
);
static
const
Color
warning200
=
Color
(
0xFFFEDF89
);
static
const
Color
warning300
=
Color
(
0xFFFEC84B
);
static
const
Color
warning400
=
Color
(
0xFFFDB022
);
static
const
Color
warning500
=
Color
(
0xFFF79009
);
static
const
Color
warning600
=
Color
(
0xFFDC6803
);
static
const
Color
warning700
=
Color
(
0xFFB54708
);
static
const
Color
warning800
=
Color
(
0xFF93370D
);
static
const
Color
warning900
=
Color
(
0xFF7A2E0E
);
static
const
Color
warning950
=
Color
(
0xFF4E1D09
);
static
const
Color
success25
=
Color
(
0xFFF6FEF9
);
static
const
Color
success50
=
Color
(
0xFFECFDF3
);
static
const
Color
success100
=
Color
(
0xFFDCFAE6
);
static
const
Color
success200
=
Color
(
0xFFABEFC6
);
static
const
Color
success300
=
Color
(
0xFF75E0A7
);
static
const
Color
success400
=
Color
(
0xFF47CD89
);
static
const
Color
success500
=
Color
(
0xFF17B26A
);
static
const
Color
success600
=
Color
(
0xFF079455
);
static
const
Color
success700
=
Color
(
0xFF067647
);
static
const
Color
success800
=
Color
(
0xFF085D3A
);
static
const
Color
success900
=
Color
(
0xFF074D31
);
static
const
Color
success950
=
Color
(
0xFF074D31
);
}
\ No newline at end of file
lib/resouce/define_image.dart
0 → 100644
View file @
abd9f02e
const
module
=
'assets/images'
;
const
String
icClose
=
'
$module
/ic_close.svg'
;
const
String
icLogo
=
'
$module
/ic_logo.svg'
;
const
String
bgAlertHeader
=
'
$module
/bg_alert_header.svg'
;
\ No newline at end of file
lib/resouce/text_style.dart
0 → 100644
View file @
abd9f02e
import
'package:flutter/material.dart'
;
enum
TextStyleIconAndText
{
header1
,
header2
,
header3
,
normal
,
underline
,
normalDisable
,
normalButton
,
}
TextStyle
header1
=
TextStyle
(
fontSize:
22
,
fontWeight:
FontWeight
.
bold
,
color:
Colors
.
black
,
);
TextStyle
header2
=
TextStyle
(
fontSize:
18
,
fontWeight:
FontWeight
.
bold
,
color:
Colors
.
black
,
);
TextStyle
header3
=
TextStyle
(
fontSize:
16
,
fontWeight:
FontWeight
.
bold
,
color:
Colors
.
black
,
);
const
TextStyle
textNormal
=
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
normal
,
color:
Colors
.
black
,
);
const
TextStyle
textMedium
=
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
w500
,
color:
Colors
.
black
,
);
const
TextStyle
textSemiBold
=
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
w600
,
color:
Colors
.
black
,
);
TextStyle
textBold
=
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
bold
,
color:
Colors
.
black
,
);
TextStyle
underline
=
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
normal
,
decoration:
TextDecoration
.
underline
,
color:
Colors
.
blue
,
);
TextStyle
normalDisable
=
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
bold
,
color:
Colors
.
grey
,
);
TextStyle
normalButton
=
TextStyle
(
fontSize:
14
,
fontWeight:
FontWeight
.
bold
,
color:
Colors
.
white
,
);
TextStyle
getTextStyle
(
TextStyleIconAndText
?
textType
)
{
switch
(
textType
)
{
case
TextStyleIconAndText
.
header1
:
return
header1
;
case
TextStyleIconAndText
.
header2
:
return
header2
;
case
TextStyleIconAndText
.
header3
:
return
header3
;
case
TextStyleIconAndText
.
normal
:
return
textNormal
;
case
TextStyleIconAndText
.
underline
:
return
underline
;
case
TextStyleIconAndText
.
normalDisable
:
return
normalDisable
;
case
TextStyleIconAndText
.
normalButton
:
return
normalButton
;
default
:
return
textNormal
;
}
}
\ No newline at end of file
lib/shared/
e_grab_
navigate.dart
→
lib/shared/navigate
_helper
.dart
View file @
abd9f02e
File moved
lib/splash_screen/splash_screen.dart
View file @
abd9f02e
...
@@ -27,21 +27,6 @@ class _SplashScreenState extends State<SplashScreen> with ApiHelper {
...
@@ -27,21 +27,6 @@ class _SplashScreenState extends State<SplashScreen> with ApiHelper {
super
.
initState
();
super
.
initState
();
initNetWork
(
APIPaths
.
baseUrl
);
initNetWork
(
APIPaths
.
baseUrl
);
_viewModel
.
checkUpdateApp
();
_viewModel
.
checkUpdateApp
();
// ApiService().checkUpdateWithRequestManager().then((value) {
// if (value != null) {
// if (value!.status == UpdateStatus.force) {
// _showForceUpdateAlert();
// } else if (value!.status == UpdateStatus.suggest) {
// _showSuggestUpdateAlert();
// } else {
// _showForceUpdateAlert();
// // _navigateToHome();
// }
// } else {
// _showSuggestUpdateAlert();
// // _navigateToHome();
// }
// });
}
}
@override
@override
...
@@ -69,8 +54,7 @@ class _SplashScreenState extends State<SplashScreen> with ApiHelper {
...
@@ -69,8 +54,7 @@ class _SplashScreenState extends State<SplashScreen> with ApiHelper {
}
else
if
(
status
==
UpdateStatus
.
suggest
)
{
}
else
if
(
status
==
UpdateStatus
.
suggest
)
{
_showSuggestUpdateAlert
();
_showSuggestUpdateAlert
();
}
else
{
}
else
{
_showSuggestUpdateAlert
();
_navigateToBeforCheckUpdate
();
// _navigateToBeforCheckUpdate();
}
}
});
});
return
Container
(
width:
double
.
infinity
,
height:
double
.
infinity
,
color:
Colors
.
black
.
withOpacity
(
0.5
));
return
Container
(
width:
double
.
infinity
,
height:
double
.
infinity
,
color:
Colors
.
black
.
withOpacity
(
0.5
));
...
...
lib/splash_screen/splash_screen_view_model.dart
View file @
abd9f02e
...
@@ -2,6 +2,7 @@ import 'package:get/get.dart';
...
@@ -2,6 +2,7 @@ import 'package:get/get.dart';
import
'package:mypoint_flutter_app/base/restful_api_viewmodel.dart'
;
import
'package:mypoint_flutter_app/base/restful_api_viewmodel.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_request.dart'
;
import
'package:mypoint_flutter_app/networking/restful_api_request.dart'
;
import
'../base/base_response_model.dart'
;
import
'../base/base_response_model.dart'
;
import
'../model/check_update_response_model.dart'
;
import
'../model/update_response_object.dart'
;
import
'../model/update_response_object.dart'
;
class
SplashScreenViewModel
extends
RestfulApiViewModel
{
class
SplashScreenViewModel
extends
RestfulApiViewModel
{
...
...
lib/widgets/alert/custom_alert_dialog.dart
0 → 100644
View file @
abd9f02e
import
'package:flutter/material.dart'
;
import
'package:flutter_widget_from_html/flutter_widget_from_html.dart'
;
import
'package:get/get.dart'
;
import
'package:mypoint_flutter_app/resouce/define_image.dart'
;
import
'data_alert_model.dart'
;
enum
ButtonsDirection
{
row
,
column
}
class
CustomAlertDialog
extends
StatelessWidget
{
final
DataAlertModel
alertData
;
final
ButtonsDirection
direction
;
const
CustomAlertDialog
({
super
.
key
,
required
this
.
alertData
,
this
.
direction
=
ButtonsDirection
.
column
});
@override
Widget
build
(
BuildContext
context
)
{
return
Dialog
(
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
16
)),
child:
Container
(
padding:
const
EdgeInsets
.
all
(
16
),
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
16
),
color:
Colors
.
white
),
child:
Stack
(
children:
[
Container
(
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
children:
[
// Header Image
if
(
alertData
.
background
!=
null
)
ClipRRect
(
borderRadius:
BorderRadius
.
circular
(
12
),
child:
Image
.
asset
(
alertData
.
background
!),
// .network(
// alertData.background!,
// height: 120,
// width: 120,
// fit: BoxFit.cover,
// ),
),
const
SizedBox
(
height:
10
),
// Title
if
(
alertData
.
title
!=
null
)
Text
(
alertData
.
title
!,
style:
const
TextStyle
(
fontSize:
18
,
fontWeight:
FontWeight
.
bold
),
textAlign:
TextAlign
.
center
,
),
const
SizedBox
(
height:
8
),
// HTML Content
if
(
alertData
.
content
!=
null
)
HtmlWidget
(
alertData
.
content
!,
),
// Html(
// data: alertData.content!,
// style: {
// "body": Style(
// textAlign: TextAlign.center,
// fontSize: FontSize.medium,
// ),
// },
// ),
const
SizedBox
(
height:
10
),
// Buttons
_buildButtons
(),
],
),
),
// Close Button (X) ở góc phải trên
Positioned
(
top:
0
,
right:
0
,
child:
GestureDetector
(
onTap:
()
=>
Get
.
back
(),
child:
const
Icon
(
Icons
.
close
,
color:
Colors
.
black
,
size:
24
),
),
),
]
),
),
);
}
Widget
_buildButtons
()
{
return
direction
==
ButtonsDirection
.
column
?
Column
(
children:
alertData
.
buttons
?.
map
(
(
btn
)
=>
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
4
),
child:
ElevatedButton
(
style:
ElevatedButton
.
styleFrom
(
backgroundColor:
btn
.
bgColor
,
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
24
)),
minimumSize:
const
Size
(
double
.
infinity
,
48
),
),
onPressed:
btn
.
onPressed
,
child:
Text
(
btn
.
text
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
14
,
fontWeight:
FontWeight
.
bold
),
),
),
),
)
.
toList
()
??
[],
)
:
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceEvenly
,
children:
alertData
.
buttons
?.
map
(
(
btn
)
=>
Expanded
(
child:
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
4
),
child:
ElevatedButton
(
style:
ElevatedButton
.
styleFrom
(
backgroundColor:
btn
.
bgColor
,
shape:
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
24
)),
minimumSize:
const
Size
(
100
,
48
),
),
onPressed:
btn
.
onPressed
,
child:
Text
(
btn
.
text
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
14
,
fontWeight:
FontWeight
.
bold
),
),
),
),
),
)
.
toList
()
??
[],
);
}
}
lib/widgets/alert/data_alert_model.dart
0 → 100644
View file @
abd9f02e
import
'dart:ui'
;
import
'package:flutter/material.dart'
;
import
'../../resouce/base_color.dart'
;
class
DataAlertModel
{
final
String
?
background
;
final
String
?
title
;
final
String
?
content
;
final
List
<
AlertButton
>?
buttons
;
DataAlertModel
({
this
.
background
,
this
.
title
,
this
.
content
,
this
.
buttons
=
const
[],
});
}
class
AlertButton
{
final
String
text
;
final
Color
textColor
;
final
Color
bgColor
;
final
bool
isPrimary
;
final
VoidCallback
onPressed
;
AlertButton
({
required
this
.
text
,
required
this
.
textColor
,
required
this
.
bgColor
,
required
this
.
isPrimary
,
required
this
.
onPressed
,
});
}
lib/widgets/alert/src/alert.dart
0 → 100755
View file @
abd9f02e
import
'dart:async'
;
import
'package:flutter/material.dart'
;
import
'package:mypoint_flutter_app/resouce/define_image.dart'
;
import
'alert_style.dart'
;
import
'animation_transition.dart'
;
import
'dialog_button.dart'
;
class
Alert
{
final
String
?
id
;
final
BuildContext
context
;
final
AlertType
?
type
;
final
AlertStyle
style
;
final
EdgeInsets
?
padding
;
final
Widget
?
image
;
final
String
?
urlImage
;
final
String
?
title
;
final
String
?
desc
;
final
Widget
content
;
final
List
<
DialogButton
>?
buttons
;
final
Function
?
closeFunction
;
final
Widget
?
closeIcon
;
final
bool
onWillPopActive
;
final
bool
useRootNavigator
;
final
AlertAnimation
?
alertAnimation
;
Alert
({
required
this
.
context
,
this
.
id
,
this
.
type
,
this
.
style
=
const
AlertStyle
(),
this
.
padding
,
this
.
image
,
this
.
urlImage
,
this
.
title
,
this
.
desc
,
this
.
content
=
const
SizedBox
(),
this
.
buttons
,
this
.
closeFunction
,
this
.
closeIcon
,
this
.
onWillPopActive
=
false
,
this
.
alertAnimation
,
this
.
useRootNavigator
=
true
,
});
/// Displays defined alert window
Future
<
bool
?>
show
()
async
{
return
await
showGeneralDialog
(
context:
context
,
pageBuilder:
(
BuildContext
buildContext
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
)
{
return
_buildDialog
();
},
barrierDismissible:
style
.
isOverlayTapDismiss
,
barrierLabel:
MaterialLocalizations
.
of
(
context
).
modalBarrierDismissLabel
,
barrierColor:
style
.
overlayColor
,
useRootNavigator:
useRootNavigator
,
transitionDuration:
style
.
animationDuration
,
transitionBuilder:
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
,
)
=>
alertAnimation
==
null
?
_showAnimation
(
animation
,
secondaryAnimation
,
child
)
:
alertAnimation
!(
context
,
animation
,
secondaryAnimation
,
child
));
}
/// Dismisses the alert dialog.
Future
<
void
>
dismiss
()
async
{
Navigator
.
of
(
context
,
rootNavigator:
useRootNavigator
).
pop
();
}
/// Alert dialog content widget
Widget
_buildDialog
()
{
final
Widget
child
=
Align
(
alignment:
style
.
alertAlignment
,
child:
ConstrainedBox
(
constraints:
style
.
constraints
??
BoxConstraints
.
loose
(
Size
.
infinite
),
child:
SingleChildScrollView
(
child:
AlertDialog
(
key:
id
==
null
?
null
:
Key
(
id
!),
backgroundColor:
style
.
backgroundColor
??
Theme
.
of
(
context
).
dialogTheme
.
backgroundColor
,
shape:
style
.
alertBorder
??
_defaultShape
(),
insetPadding:
style
.
alertPadding
,
elevation:
style
.
alertElevation
,
titlePadding:
const
EdgeInsets
.
all
(
0.0
),
title:
Container
(
child:
Center
(
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
<
Widget
>[
_getCloseButton
(),
Padding
(
padding:
padding
??
EdgeInsets
.
fromLTRB
(
20
,
(
style
.
isCloseButton
?
0
:
10
),
20
,
0
),
child:
Column
(
crossAxisAlignment:
CrossAxisAlignment
.
stretch
,
children:
<
Widget
>[
Center
(
child:
_getImage
(),
),
if
(
title
!=
null
)
_getTextWidget
(
style
.
isTitleSelectable
,
title
,
style
.
titleStyle
,
style
.
titleTextAlign
,
style
.
titlePadding
??
EdgeInsets
.
only
(
top:
15
,
bottom:
desc
==
null
?
0
:
10
,
),
),
if
(
desc
!=
null
)
_getTextWidget
(
style
.
isDescSelectable
,
desc
,
style
.
descStyle
,
style
.
descTextAlign
,
style
.
descPadding
,
),
content
,
],
),
)
],
),
),
),
contentPadding:
style
.
buttonAreaPadding
,
content:
style
.
buttonsDirection
==
ButtonsDirection
.
row
?
Row
(
mainAxisAlignment:
MainAxisAlignment
.
spaceEvenly
,
children:
_getButtons
(),
)
:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
crossAxisAlignment:
CrossAxisAlignment
.
center
,
mainAxisAlignment:
MainAxisAlignment
.
spaceEvenly
,
children:
_getButtons
(),
)),
),
),
);
return
onWillPopActive
?
PopScope
(
child:
child
)
//WillPopScope(onWillPop: () async => false, child: child)
:
child
;
}
/// Returns Text Widget or Selectable Text Widget with Padding
/// based on isSelectable property.
Widget
_getTextWidget
(
bool
isSelectable
,
String
?
text
,
TextStyle
textStyle
,
TextAlign
textAlign
,
EdgeInsets
edgeInsets
)
{
return
Padding
(
padding:
edgeInsets
,
child:
_getTextWidgetBySelectable
(
isSelectable
,
text
,
textStyle
,
textAlign
,
),
);
}
/// Returns Text Widget or Selectable Text Widget
/// based on isSelectable property.
Widget
_getTextWidgetBySelectable
(
bool
isSelectable
,
String
?
text
,
TextStyle
textStyle
,
TextAlign
textAlign
)
{
if
(
isSelectable
)
{
return
SelectableText
(
text
??
""
,
style:
textStyle
,
textAlign:
textAlign
,
);
}
else
{
return
Text
(
text
??
""
,
style:
textStyle
,
textAlign:
textAlign
,
);
}
}
/// Returns the close button on the top right
Widget
_getCloseButton
()
{
return
style
.
isCloseButton
?
Padding
(
padding:
const
EdgeInsets
.
fromLTRB
(
0
,
10
,
10
,
0
),
child:
GestureDetector
(
onTap:
()
{
if
(
closeFunction
==
null
)
{
Navigator
.
of
(
context
,
rootNavigator:
useRootNavigator
).
pop
();
}
else
{
closeFunction
!();
}
},
child:
Container
(
alignment:
FractionalOffset
.
topRight
,
child:
closeIcon
!=
null
?
Container
(
child:
closeIcon
)
:
Container
(
width:
20
,
height:
20
,
decoration:
BoxDecoration
(
image:
DecorationImage
(
image:
AssetImage
(
icClose
),
),
),
),
),
),
)
:
Container
();
}
/// Returns defined buttons. Default: Cancel Button
List
<
Widget
>
_getButtons
()
{
List
<
Widget
>
expandedButtons
=
[];
if
(
style
.
isButtonVisible
)
{
if
(
buttons
!=
null
)
{
for
(
var
button
in
buttons
!)
{
var
buttonWidget
=
Padding
(
padding:
const
EdgeInsets
.
only
(
left:
2
,
right:
2
),
child:
button
,
);
if
((
button
.
width
!=
null
&&
buttons
!.
length
==
1
)
||
style
.
buttonsDirection
==
ButtonsDirection
.
column
)
{
expandedButtons
.
add
(
buttonWidget
);
}
else
{
expandedButtons
.
add
(
Expanded
(
child:
buttonWidget
,
));
}
}
}
else
{
Widget
cancelButton
=
DialogButton
(
child:
Text
(
"CANCEL"
,
style:
TextStyle
(
color:
Colors
.
white
,
fontSize:
20
),
),
onPressed:
()
=>
Navigator
.
pop
(
context
),
);
if
(
style
.
buttonsDirection
==
ButtonsDirection
.
row
)
{
cancelButton
=
Expanded
(
child:
cancelButton
,
);
}
expandedButtons
.
add
(
cancelButton
);
}
}
return
expandedButtons
;
}
/// Returns alert default border style
ShapeBorder
_defaultShape
()
{
return
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
10.0
),
side:
BorderSide
(
color:
Colors
.
blueGrey
,
),
);
}
/// Returns alert image for icon
Widget
_getImage
()
{
Widget
response
;
if
(
urlImage
!=
null
&&
urlImage
!.
isNotEmpty
)
{
response
=
Image
.
network
(
urlImage
!);
return
response
;
}
switch
(
type
)
{
case
AlertType
.
success
:
response
=
Image
.
asset
(
""
);
break
;
case
AlertType
.
error
:
response
=
Image
.
asset
(
""
);
break
;
case
AlertType
.
info
:
response
=
Image
.
asset
(
""
);
break
;
case
AlertType
.
warning
:
response
=
Image
.
asset
(
""
);
break
;
case
AlertType
.
none
:
response
=
Container
();
break
;
default
:
response
=
image
??
Container
();
break
;
}
return
response
;
}
/// Shows alert with selected animation
_showAnimation
(
animation
,
secondaryAnimation
,
child
)
{
return
AnimationTransition
.
fromBottom
(
animation
,
secondaryAnimation
,
child
);
}
}
lib/widgets/alert/src/alert_style.dart
0 → 100755
View file @
abd9f02e
import
'package:flutter/material.dart'
;
enum
AlertType
{
error
,
success
,
info
,
warning
,
none
}
/// Buttons container
enum
ButtonsDirection
{
row
,
column
}
/// Defines Default Alert Window Padding
const
EdgeInsets
defaultAlertPadding
=
EdgeInsets
.
symmetric
(
horizontal:
40.0
,
vertical:
24.0
);
typedef
AlertAnimation
=
Widget
Function
(
BuildContext
context
,
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
,
);
/// Alert style class for reusable customization of dialogs.
class
AlertStyle
{
/// The [animationDuration] parameter is used to set the animation transition time. Default: "200 ms"
final
Duration
animationDuration
;
/// The [alertBorder] parameter sets border.
final
ShapeBorder
?
alertBorder
;
/// The [isButtonVisible] paramater is used to decide hide or display buttons
final
bool
isButtonVisible
;
/// The [isCloseButton] parameter sets visibility of the close button. Default: "true"
final
bool
isCloseButton
;
/// The [isOverlayTapDismiss] parameter sets closing the alert by clicking outside. Default: "true"
final
bool
isOverlayTapDismiss
;
/// The [backgroundColor] parameter sets the background color.
final
Color
?
backgroundColor
;
/// The [overlayColor] parameter sets the background color of the outside. Default: "Color(0xDD000000)"
final
Color
overlayColor
;
/// The [titleStyle] parameter sets alert title text style.
final
TextStyle
titleStyle
;
/// The [descStyle] parameter sets alert desc text style.
final
TextStyle
descStyle
;
/// The [titleTextAlign] parameter sets alignment of the title.
final
TextAlign
titleTextAlign
;
/// The [descTextAlign] parameter sets alignment of the desc.
final
TextAlign
descTextAlign
;
/// The [buttonAreaPadding] parameter sets button area padding.
final
EdgeInsets
buttonAreaPadding
;
/// The [constraints] parameter sets Alert size.
final
BoxConstraints
?
constraints
;
/// The [buttonsDirection] parameter sets button container as Row or Col.
final
ButtonsDirection
buttonsDirection
;
/// The [alertElevation] parameter sets elevation of alert dialog container.
final
double
?
alertElevation
;
/// The [alertPadding] parameter sets alert area padding.
final
EdgeInsets
alertPadding
;
/// The [alertAlignment] parameter sets alert dialog alignment.
final
AlignmentGeometry
alertAlignment
;
/// The [isTitleSelectable] parameter sets title text is selectable or not.
final
bool
isTitleSelectable
;
/// The [isDescSelectable] parameter sets desc text is selectable or not.
final
bool
isDescSelectable
;
/// The [titlePadding] parameter sets title area padding.
final
EdgeInsets
?
titlePadding
;
/// The [descPadding] parameter sets desc area padding.
final
EdgeInsets
descPadding
;
/// Alert style constructor function
/// All properties are optional.
const
AlertStyle
({
this
.
animationDuration
=
const
Duration
(
milliseconds:
200
),
this
.
alertBorder
,
this
.
isButtonVisible
=
true
,
this
.
isCloseButton
=
true
,
this
.
isOverlayTapDismiss
=
true
,
this
.
backgroundColor
,
this
.
overlayColor
=
Colors
.
black87
,
this
.
titleStyle
=
const
TextStyle
(
color:
Colors
.
black
,
fontWeight:
FontWeight
.
w500
,
fontStyle:
FontStyle
.
normal
),
this
.
titleTextAlign
=
TextAlign
.
center
,
this
.
descStyle
=
const
TextStyle
(
color:
Colors
.
black
,
fontWeight:
FontWeight
.
w400
,
fontStyle:
FontStyle
.
normal
),
this
.
descTextAlign
=
TextAlign
.
center
,
this
.
buttonAreaPadding
=
const
EdgeInsets
.
all
(
20.0
),
this
.
constraints
,
this
.
buttonsDirection
=
ButtonsDirection
.
row
,
this
.
alertElevation
,
this
.
alertPadding
=
defaultAlertPadding
,
this
.
alertAlignment
=
Alignment
.
center
,
this
.
isTitleSelectable
=
false
,
this
.
isDescSelectable
=
false
,
this
.
titlePadding
,
this
.
descPadding
=
const
EdgeInsets
.
all
(
0.0
),
});
}
lib/widgets/alert/src/animation_transition.dart
0 → 100755
View file @
abd9f02e
import
'package:flutter/material.dart'
;
/// Predefined functions for transition animations
///
/// Exp: AnimationTransition.fromRight(animation, secondaryAnimation, child);
class
AnimationTransition
{
/// Slide animation, from right to left (SlideTransition)
static
fromRight
(
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
)
{
return
SlideTransition
(
position:
Tween
<
Offset
>(
begin:
const
Offset
(
1.0
,
0.0
),
end:
Offset
.
zero
,
).
animate
(
animation
),
child:
child
,
);
}
/// Slide animation, from left to right (SlideTransition)
static
fromLeft
(
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
)
{
return
SlideTransition
(
position:
Tween
<
Offset
>(
begin:
const
Offset
(-
1.0
,
0.0
),
end:
Offset
.
zero
,
).
animate
(
animation
),
child:
child
,
);
}
/// Slide animation, from top to bottom (SlideTransition)
static
fromTop
(
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
)
{
return
SlideTransition
(
position:
Tween
<
Offset
>(
begin:
const
Offset
(
0.0
,
-
1.0
),
end:
Offset
.
zero
,
).
animate
(
animation
),
child:
child
,
);
}
/// Slide animation, from top to bottom (SlideTransition)
static
fromBottom
(
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
)
{
return
SlideTransition
(
position:
Tween
<
Offset
>(
begin:
const
Offset
(
0.0
,
1.0
),
end:
Offset
.
zero
,
).
animate
(
animation
),
child:
child
,
);
}
/// Scale animation, from in to out (ScaleTransition)
static
grow
(
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
)
{
return
ScaleTransition
(
scale:
Tween
<
double
>(
begin:
0.0
,
end:
1.0
,
).
animate
(
CurvedAnimation
(
parent:
animation
,
curve:
Interval
(
0.00
,
0.50
,
curve:
Curves
.
linear
,
),
),
),
child:
child
,
);
}
/// Scale animation, from out to in (ScaleTransition)
static
shrink
(
Animation
<
double
>
animation
,
Animation
<
double
>
secondaryAnimation
,
Widget
child
)
{
return
ScaleTransition
(
scale:
Tween
<
double
>(
begin:
1.2
,
end:
1.0
,
).
animate
(
CurvedAnimation
(
parent:
animation
,
curve:
Interval
(
0.5
,
1.0
),
// curve: Interval(0,
// 0.50,
// 1.00,
// curve: Curves.linear,
// ),
),
),
child:
child
,
);
}
}
lib/widgets/alert/src/dialog_button.dart
0 → 100755
View file @
abd9f02e
/*
* rflutter_alert
* Created by Ratel
* https://ratel.com.tr
*
* Copyright (c) 2018 Ratel, LLC. All rights reserved.
* See LICENSE for distribution and usage details.
*/
import
'package:flutter/material.dart'
;
/// Used for defining alert buttons.
///
/// [child] and [onPressed] parameters are required.
class
DialogButton
extends
StatelessWidget
{
final
Widget
?
child
;
final
double
?
width
;
final
double
height
;
final
Color
?
color
;
final
Color
?
highlightColor
;
final
Color
?
splashColor
;
final
Gradient
?
gradient
;
final
BorderRadius
radius
;
final
VoidCallback
?
onPressed
;
final
BoxBorder
border
;
final
EdgeInsets
padding
;
final
EdgeInsets
margin
;
/// DialogButton constructor
const
DialogButton
({
super
.
key
,
required
this
.
child
,
this
.
width
,
this
.
height
=
50.0
,
this
.
color
,
this
.
highlightColor
,
this
.
splashColor
,
this
.
gradient
,
this
.
radius
=
const
BorderRadius
.
all
(
Radius
.
circular
(
20
)),
this
.
border
=
const
Border
.
fromBorderSide
(
BorderSide
(
color:
Color
(
0x00000000
),
width:
0
,
style:
BorderStyle
.
solid
,
),
),
this
.
padding
=
const
EdgeInsets
.
only
(
left:
6
,
right:
6
),
this
.
margin
=
const
EdgeInsets
.
all
(
6
),
required
this
.
onPressed
,
});
/// Creates alert buttons based on constructor params
@override
Widget
build
(
BuildContext
context
)
{
return
Container
(
margin:
margin
,
width:
width
,
height:
height
,
decoration:
BoxDecoration
(
color:
color
??
Theme
.
of
(
context
).
colorScheme
.
secondary
,
gradient:
gradient
,
borderRadius:
radius
,
border:
border
,
),
child:
Material
(
color:
Colors
.
transparent
,
child:
InkWell
(
borderRadius:
radius
,
highlightColor:
highlightColor
??
Theme
.
of
(
context
).
highlightColor
,
splashColor:
splashColor
??
Theme
.
of
(
context
).
splashColor
,
onTap:
onPressed
,
child:
Padding
(
padding:
padding
,
child:
Center
(
child:
child
,
),
),
),
),
);
}
}
lib/widgets/button_container.dart
0 → 100644
View file @
abd9f02e
import
'package:flutter/material.dart'
;
class
ButtonContainer
extends
StatelessWidget
{
final
Color
color
;
final
double
cornerRadius
;
final
double
?
height
;
final
double
?
width
;
final
Widget
child
;
final
bool
visible
;
const
ButtonContainer
({
super
.
key
,
required
this
.
child
,
this
.
height
,
this
.
width
,
this
.
color
=
Colors
.
white
,
this
.
cornerRadius
=
8
,
this
.
visible
=
true
,
});
@override
Widget
build
(
BuildContext
context
)
{
return
Visibility
(
visible:
visible
,
child:
Container
(
decoration:
BoxDecoration
(
borderRadius:
BorderRadius
.
circular
(
cornerRadius
),
color:
color
),
width:
width
,
height:
height
,
child:
child
,
),
);
}
}
pubspec.yaml
View file @
abd9f02e
...
@@ -41,6 +41,10 @@ dependencies:
...
@@ -41,6 +41,10 @@ dependencies:
fluttertoast
:
8.2.12
fluttertoast
:
8.2.12
logger
:
logger
:
url_launcher
:
^6.3.1
url_launcher
:
^6.3.1
flutter_widget_from_html
:
^0.16.0
device_info_plus
:
^9.0.3
uuid
:
^4.3.3
flutter_svg
:
dev_dependencies
:
dev_dependencies
:
flutter_test
:
flutter_test
:
...
@@ -70,8 +74,7 @@ flutter:
...
@@ -70,8 +74,7 @@ flutter:
# To add assets to your application, add an assets section, like this:
# To add assets to your application, add an assets section, like this:
assets
:
assets
:
-
assets/images/splash_screen.png
-
assets/images/
-
assets/images/bg_onboarding.png
# - images/a_dot_burr.jpeg
# - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg
# - images/a_dot_ham.jpeg
...
...
Prev
1
2
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