Adding base project of flutter-hybrid
This commit is contained in:
@@ -0,0 +1,240 @@
|
||||
|
||||
|
||||
int calcDaysBetween(DateTime from, DateTime to) {
|
||||
from = DateTime(from.year, from.month, from.day);
|
||||
to = DateTime(to.year, to.month, to.day);
|
||||
return (to.difference(from).inHours ~/ 24);
|
||||
}
|
||||
|
||||
int calcSecondsBetween(DateTime from, DateTime to) {
|
||||
from = DateTime(
|
||||
from.year, from.month, from.day, from.hour, from.minute, from.second);
|
||||
to = DateTime(to.year, to.month, to.day, to.hour, to.minute, to.second);
|
||||
return to.difference(from).inSeconds;
|
||||
}
|
||||
|
||||
String customGroup(DateTime transactionDate) {
|
||||
String response = '';
|
||||
DateTime latestDate = DateTime.now();
|
||||
int nDaysInBetween = calcDaysBetween(transactionDate, latestDate);
|
||||
|
||||
int years = nDaysInBetween ~/ 365;
|
||||
|
||||
if (years == 1) {
|
||||
response = 'Last year';
|
||||
} else if (years > 1 && years <= 5) {
|
||||
response = '$years years ago';
|
||||
} else if (years > 5) {
|
||||
response = 'More than 5 years ago';
|
||||
} else {
|
||||
nDaysInBetween -= 365 * years;
|
||||
|
||||
int months = nDaysInBetween ~/ 30;
|
||||
if (months == 1) {
|
||||
response = 'Last month';
|
||||
} else if (months > 1 && months <= 6) {
|
||||
response = '$months months ago';
|
||||
} else if (months >= 6) {
|
||||
response = 'More than 6 months ago';
|
||||
} else {
|
||||
int days = latestDate.day - transactionDate.day;
|
||||
|
||||
if (days == 1) {
|
||||
response = 'Yesterday';
|
||||
|
||||
|
||||
} else if (days > 1 && days <= 7) {
|
||||
response = 'This week';
|
||||
} else if (days > 7 && days <= 14) {
|
||||
response = 'Last week';
|
||||
} else if (days > 14 && days <= 30) {
|
||||
int weeks = days ~/ 7;
|
||||
response = '$weeks weeks ago';
|
||||
} else {
|
||||
response = 'Today';
|
||||
}
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
int customGroupComparator(String group1, String group2) {
|
||||
int comparison = -1;
|
||||
int group1Match = 0;
|
||||
int group2Match = 0;
|
||||
List<String> dateGroups = [
|
||||
r'Today',
|
||||
r'Yesterday',
|
||||
r'This week',
|
||||
r'Last week',
|
||||
r'\d{1} weeks ago',
|
||||
r'Last month',
|
||||
r'\d{1} months ago',
|
||||
r'More than 6 months ago',
|
||||
r'Last year',
|
||||
r'\d{1} years ago',
|
||||
r'More than 5 years ago',
|
||||
];
|
||||
|
||||
for (var i = 0; i < dateGroups.length; i++) {
|
||||
if (RegExp(dateGroups[i]).hasMatch(group1)) {
|
||||
group1Match = i;
|
||||
}
|
||||
if (RegExp(dateGroups[i]).hasMatch(group2)) {
|
||||
group2Match = i;
|
||||
}
|
||||
}
|
||||
// check
|
||||
if (group1Match == group2Match) {
|
||||
comparison = group1.compareTo(group2);
|
||||
} else if (group1Match < group2Match) {
|
||||
comparison = -1;
|
||||
} else {
|
||||
comparison = 1;
|
||||
}
|
||||
return comparison;
|
||||
}
|
||||
|
||||
String dateFormatter(String dateGroup, DateTime transactionDate) {
|
||||
String formattedDate = '';
|
||||
if (dateGroup == 'Today') {
|
||||
formattedDate = _formatTime1(transactionDate);
|
||||
} else if (dateGroup == 'Yesterday') {
|
||||
formattedDate =
|
||||
"Yesterday at ${formatTime2(transactionDate.hour, transactionDate.minute)}";
|
||||
} else {
|
||||
formattedDate =
|
||||
"${transactionDate.day}-${transactionDate.month}-${transactionDate.year} at ${formatTime2(transactionDate.hour, transactionDate.minute)}";
|
||||
}
|
||||
return formattedDate;
|
||||
}
|
||||
|
||||
String formatTime2(int hrs, int mins) {
|
||||
int newHrs = 0;
|
||||
String midDayStatus = '';
|
||||
String minutesAsString=mins<10?"0$mins":"$mins";
|
||||
if (hrs > 12 && hrs < 24) {
|
||||
midDayStatus = 'PM';
|
||||
newHrs = hrs - 12;
|
||||
} else if (hrs == 12 && mins > 0) {
|
||||
midDayStatus = 'PM';
|
||||
newHrs = 12;
|
||||
} else if (hrs < 12) {
|
||||
midDayStatus = 'AM';
|
||||
newHrs = hrs;
|
||||
} else if (hrs == 24) {
|
||||
midDayStatus = 'AM';
|
||||
newHrs = 00;
|
||||
}
|
||||
|
||||
return "$newHrs:$minutesAsString $midDayStatus";
|
||||
}
|
||||
|
||||
String formatTime3(String date) {
|
||||
DateTime someDate = DateTime.parse(date);
|
||||
int hrs = someDate.hour;
|
||||
dynamic mins = someDate.minute;
|
||||
int newHrs = 0;
|
||||
String midDayStatus = '';
|
||||
|
||||
if (hrs > 12 && hrs < 24) {
|
||||
midDayStatus = 'PM';
|
||||
newHrs = hrs - 12;
|
||||
} else if (hrs == 12 && mins > 0) {
|
||||
midDayStatus = 'PM';
|
||||
newHrs = 12;
|
||||
} else if (hrs < 12) {
|
||||
midDayStatus = 'AM';
|
||||
newHrs = hrs;
|
||||
} else if (hrs == 24) {
|
||||
midDayStatus = 'AM';
|
||||
newHrs = 00;
|
||||
}
|
||||
|
||||
if (mins<=9) {
|
||||
mins="0$mins";
|
||||
}
|
||||
|
||||
return "$newHrs:$mins $midDayStatus";
|
||||
}
|
||||
|
||||
String _formatTime1(DateTime transactionDate) {
|
||||
DateTime latestDate = DateTime.now();
|
||||
|
||||
int seconds = calcSecondsBetween(transactionDate, latestDate);
|
||||
|
||||
int minutes = seconds ~/ 60;
|
||||
int hours = minutes ~/ 60;
|
||||
|
||||
String response = '';
|
||||
if (hours == 1) {
|
||||
response = 'an hour ago';
|
||||
} else if (hours > 1 && hours < 24) {
|
||||
response = '$hours hours ago';
|
||||
} else {
|
||||
if (minutes > 30) {
|
||||
response = 'half an hour ago';
|
||||
} else if (minutes <= 30 && minutes > 1) {
|
||||
response = '$minutes minutes ago';
|
||||
} else if (minutes == 1) {
|
||||
response = 'a minute ago';
|
||||
} else {
|
||||
if (seconds <= 0) {
|
||||
response = 'just now';
|
||||
} else if (seconds == 1) {
|
||||
response = 'a second ago';
|
||||
} else {
|
||||
response = '$seconds seconds ago';
|
||||
}
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
String dateToWords(DateTime transactionDate) {
|
||||
String day = _formatDay(transactionDate.day);
|
||||
String month = _findMonthInWords(transactionDate.month);
|
||||
return "$day $month, ${transactionDate.year}";
|
||||
}
|
||||
|
||||
//? FUNCTION FOR RETRIEVING ORDINALS
|
||||
String _formatDay(int day) {
|
||||
String suffix = '';
|
||||
if (day >= 11 && day<=13) {
|
||||
suffix = 'th';
|
||||
} else {
|
||||
switch (day % 10) {
|
||||
case 1:
|
||||
suffix = 'st';
|
||||
break;
|
||||
case 2:
|
||||
suffix = 'nd';
|
||||
break;
|
||||
case 3:
|
||||
suffix = 'rd';
|
||||
break;
|
||||
default:
|
||||
suffix = 'th';
|
||||
}
|
||||
}
|
||||
return "$day$suffix";
|
||||
}
|
||||
|
||||
String _findMonthInWords(int month) {
|
||||
List<String> months = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December'
|
||||
];
|
||||
return months[month - 1];
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../database/login_info_storage.dart';
|
||||
import '../database/user_data_storage.dart';
|
||||
import '../screens/Login Screen/login_screen.dart';
|
||||
|
||||
Future<bool> _deleteLoggedInUserData() async {
|
||||
List<bool> deletionStatus = await Future.wait(
|
||||
[LoginInfoStorage().deleteFile(), UserDataStorage().deleteFile()]);
|
||||
return deletionStatus.first && deletionStatus.last;
|
||||
}
|
||||
|
||||
void showErrorAlert(BuildContext context, Map<String, dynamic> error) {
|
||||
Map<String, dynamic> errorTypes = {
|
||||
'error': _CommonError(context, error),
|
||||
'internetConnectionError': _LocalError(context, error),
|
||||
'localDBError': _LocalError(context, error),
|
||||
'authenticationError': _CommonError(context, error),
|
||||
'apiAuthorizationError': _HazardousError(context, error),
|
||||
'corruptedTokenError': _HazardousError(context, error)
|
||||
};
|
||||
String currentError = error.keys.first;
|
||||
// String currentError = error['operationMessage'];
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(
|
||||
"Error",
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: errorTypes[currentError].errorDescription,
|
||||
),
|
||||
shape:
|
||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
actionsAlignment: MainAxisAlignment.center,
|
||||
actions: [
|
||||
Container(
|
||||
height: 48,
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.blueGrey.shade100,
|
||||
offset: Offset(0, 4),
|
||||
blurRadius: 5.0)
|
||||
],
|
||||
gradient: RadialGradient(
|
||||
colors: [Color(0xff0070BA), Color(0xff1546A0)],
|
||||
radius: 8.4,
|
||||
center: Alignment(-0.24, -0.36)),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: ElevatedButton(
|
||||
onPressed: errorTypes[currentError].onClose,
|
||||
child: Text('OK'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
primary: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
)),
|
||||
)
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
class _CommonError {
|
||||
BuildContext context;
|
||||
Map<String, dynamic> error;
|
||||
_CommonError(this.context, this.error);
|
||||
List<Widget> get errorDescription => <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24, bottom: 12),
|
||||
child: Text(
|
||||
error[error['operationMessage']],
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
void onClose() {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
}
|
||||
|
||||
class _LocalError {
|
||||
BuildContext context;
|
||||
Map<String, dynamic> error;
|
||||
_LocalError(this.context, this.error);
|
||||
|
||||
List<Widget> get errorDescription => <Widget>[
|
||||
error.keys.first == 'internetConnectionError'
|
||||
? ColorFiltered(
|
||||
colorFilter:
|
||||
ColorFilter.mode(Color(0xFF0070BA), BlendMode.color),
|
||||
child: ColorFiltered(
|
||||
colorFilter:
|
||||
ColorFilter.mode(Colors.grey, BlendMode.saturation),
|
||||
child: Image.asset(
|
||||
'assets/images/notification_assets/no-wifi.png',
|
||||
height: 48,
|
||||
width: 48,
|
||||
),
|
||||
))
|
||||
: Image.asset(
|
||||
'assets/images/notification_assets/file-error.png',
|
||||
height: 48,
|
||||
width: 48,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24, bottom: 12),
|
||||
child: Text(
|
||||
error[error.keys.first],
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
void onClose() {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
}
|
||||
|
||||
class _HazardousError {
|
||||
BuildContext context;
|
||||
Map<String, dynamic> error;
|
||||
_HazardousError(this.context, this.error);
|
||||
List<Widget> get errorDescription => <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 24, bottom: 12),
|
||||
child: Text(
|
||||
error[error.keys.first],
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
void onClose() async {
|
||||
final logOutStatus = await _deleteLoggedInUserData();
|
||||
if (logOutStatus) {
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
MaterialPageRoute(builder: (context) => LoginScreen()),
|
||||
(route) => false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/// Flutter icons HadWinIcons
|
||||
/// Copyright (C) 2022 by original authors @ fluttericon.com, fontello.com
|
||||
/// This font was generated by FlutterIcon.com, which is derived from Fontello.
|
||||
///
|
||||
/// To use this font, place it in your fonts/ directory and include the
|
||||
/// following in your pubspec.yaml
|
||||
///
|
||||
/// flutter:
|
||||
/// fonts:
|
||||
/// - family: HadWinIcons
|
||||
/// fonts:
|
||||
/// - asset: fonts/HadWinIcons.ttf
|
||||
///
|
||||
///
|
||||
///
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class HadWinIcons {
|
||||
HadWinIcons._();
|
||||
|
||||
static const _kFontFam = 'HadWinIcons';
|
||||
static const String? _kFontPkg = null;
|
||||
|
||||
static const IconData wallet_business_and_trade = IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData wallet_education_29 = IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
static const IconData line_awesome_wallet_solid = IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg);
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:fade_shimmer/fade_shimmer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import 'display_error_alert.dart';
|
||||
|
||||
class HadWinMarkdownViewer extends StatefulWidget {
|
||||
final String screenName;
|
||||
final String urlRequested;
|
||||
|
||||
const HadWinMarkdownViewer({
|
||||
Key? key,
|
||||
required this.screenName,
|
||||
required this.urlRequested,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
HadWinMarkdownViewerState createState() => HadWinMarkdownViewerState();
|
||||
}
|
||||
|
||||
class HadWinMarkdownViewerState extends State<HadWinMarkdownViewer> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
widget.screenName,
|
||||
style: const TextStyle(fontSize: 24),
|
||||
),
|
||||
centerTitle: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
foregroundColor: const Color(0xff243656),
|
||||
elevation: 0,
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
height: 100,
|
||||
width: MediaQuery.of(context).size.width - 20,
|
||||
padding: const EdgeInsets.only(
|
||||
left: 16.18,
|
||||
right: 16.18,
|
||||
bottom: 16.18,
|
||||
top: 6.18,
|
||||
),
|
||||
child: FutureBuilder<String>(
|
||||
future: getTextData(widget.urlRequested),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
print('testing');
|
||||
|
||||
// return MarkdownWidgetBuilder(
|
||||
// markdownData: snapshot.data!,
|
||||
// styleConfig: MarkdownWidgetConfig(
|
||||
// markdownTheme: MarkdownTheme(
|
||||
// blockquoteDecoration: BoxDecoration(
|
||||
// color: Color(0xffcaf0f8),
|
||||
// ),
|
||||
// blockquoteTextStyle: TextStyle(
|
||||
// color: Color(0xff0077b6),
|
||||
// ),
|
||||
// tableConfig: TableConfig(
|
||||
// headerStyle: TextStyle(
|
||||
// fontWeight: FontWeight.w700,
|
||||
// ),
|
||||
// bodyTextConfig: TextConfig(
|
||||
// textAlign: TextAlign.center,
|
||||
// ),
|
||||
// ),
|
||||
// titleConfig: TitleConfig(
|
||||
// commonStyle: GoogleFonts.ubuntu(),
|
||||
// showDivider: false,
|
||||
// ),
|
||||
// ulConfig: UlConfig(
|
||||
// textStyle: GoogleFonts.workSans(),
|
||||
// dotWidget: (deep, index) => Text(
|
||||
// "${index + 1}.\t",
|
||||
// style: GoogleFonts.ubuntu(),
|
||||
// ),
|
||||
// ),
|
||||
// olConfig: OlConfig(
|
||||
// textStyle: GoogleFonts.workSans(),
|
||||
// indexWidget: (deep, index) => Text(
|
||||
// "${index + 1}.\t",
|
||||
// style: GoogleFonts.ubuntu(),
|
||||
// ),
|
||||
// ),
|
||||
// pConfig: PConfig(
|
||||
// textStyle: GoogleFonts.workSans(),
|
||||
// onLinkTap: (url) {
|
||||
// launchExternalURL(url!).then(
|
||||
// (value) =>
|
||||
// debugPrint("requested to access $url"),
|
||||
// );
|
||||
// },
|
||||
// emStyle: const TextStyle(
|
||||
// fontWeight: FontWeight.w600,
|
||||
// backgroundColor: Color(0xffccff33),
|
||||
// fontStyle: FontStyle.italic,
|
||||
// ),
|
||||
// ),
|
||||
// codeConfig: CodeConfig(
|
||||
// codeStyle: GoogleFonts.spaceMono(
|
||||
// backgroundColor: Color(0xff4a4e69),
|
||||
// fontWeight: FontWeight.w600,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// builder: (context, content) {
|
||||
// return content;
|
||||
// },
|
||||
// );
|
||||
}
|
||||
return docsLoading();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> getTextData(String url) async {
|
||||
var response;
|
||||
try {
|
||||
response = await http.get(Uri.parse(url));
|
||||
} on SocketException {
|
||||
showErrorAlert(
|
||||
context,
|
||||
{'internetConnectionError': 'no internet connection'},
|
||||
);
|
||||
} catch (e) {
|
||||
showErrorAlert(context, {'error': "something went wrong"});
|
||||
}
|
||||
return response.body;
|
||||
}
|
||||
|
||||
Widget docsLoading() {
|
||||
return ListView.separated(
|
||||
itemBuilder: (context, index) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 5, vertical: 1.618),
|
||||
child: const FadeShimmer(
|
||||
height: 27,
|
||||
width: 100,
|
||||
radius: 7.2,
|
||||
highlightColor: Color(0xffced4da),
|
||||
baseColor: Color(0xffe9ecef),
|
||||
),
|
||||
),
|
||||
...List.generate(
|
||||
4,
|
||||
(i) => Container(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 5, vertical: 1.618),
|
||||
child: FadeShimmer(
|
||||
height: 21,
|
||||
width: MediaQuery.of(context).size.width - 24,
|
||||
radius: 7.2,
|
||||
highlightColor: const Color(0xffced4da),
|
||||
baseColor: const Color(0xffe9ecef),
|
||||
),
|
||||
),
|
||||
).toList(),
|
||||
],
|
||||
);
|
||||
},
|
||||
separatorBuilder: (_, b) => const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
itemCount: 5,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../resources/api_constants.dart';
|
||||
|
||||
Future<Map<String, dynamic>> getData(
|
||||
{required String urlPath, String? authKey}) async {
|
||||
String backendServiceHost = "${ApiConstants.baseUrl}$urlPath";
|
||||
var response;
|
||||
try {
|
||||
response = await http.get(
|
||||
Uri.parse(backendServiceHost),
|
||||
headers: <String, String>{
|
||||
'Content-Type': 'application/json',
|
||||
if (authKey != null) 'Authorization': authKey
|
||||
},
|
||||
);
|
||||
} on SocketException {
|
||||
return {'internetConnectionError': 'no internet connection'};
|
||||
}
|
||||
return jsonDecode(response.body);
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> sendData(
|
||||
{required String urlPath,
|
||||
required Map<String, dynamic> data,
|
||||
String? authKey}) async {
|
||||
String backendServiceHost = "${ApiConstants.baseUrl}" + urlPath;
|
||||
var response;
|
||||
try {
|
||||
response = await http.post(
|
||||
Uri.parse(backendServiceHost),
|
||||
headers: <String, String>{
|
||||
'Content-Type': 'application/json',
|
||||
if (authKey != null) 'Authorization': authKey
|
||||
},
|
||||
body: jsonEncode(data),
|
||||
);
|
||||
} on SocketException {
|
||||
return {'internetConnectionError': 'no internet connection'};
|
||||
}
|
||||
return jsonDecode(response.body);
|
||||
}
|
||||
|
||||
Future<int> checkUrlValidity(String url) async {
|
||||
try {
|
||||
final response = await http.get(Uri.parse(url));
|
||||
|
||||
return response.statusCode;
|
||||
} catch (e) {
|
||||
return 404;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// page slide transition effect
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class SlideRightRoute extends PageRouteBuilder {
|
||||
final Widget page;
|
||||
SlideRightRoute({required this.page})
|
||||
: super(
|
||||
pageBuilder: (
|
||||
BuildContext context,
|
||||
Animation<double> animation,
|
||||
Animation<double> secondaryAnimation,
|
||||
) =>
|
||||
page,
|
||||
transitionsBuilder: (
|
||||
BuildContext context,
|
||||
Animation<double> animation,
|
||||
Animation<double> secondaryAnimation,
|
||||
Widget child,
|
||||
) =>
|
||||
SlideTransition(
|
||||
textDirection: TextDirection.rtl,
|
||||
position: Tween<Offset>(
|
||||
begin: const Offset(-1, 0),
|
||||
end: Offset.zero,
|
||||
).animate(animation),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
Future<void> launchExternalURL(String url) async {
|
||||
Uri uri =Uri.parse(url);
|
||||
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri,mode: LaunchMode.externalApplication);
|
||||
}
|
||||
// else {
|
||||
// throw 'Could not launch $url';
|
||||
// }
|
||||
}
|
||||
Reference in New Issue
Block a user