New Structure Implemented
parent
1eb4ad1db9
commit
0c5d43c04b
@ -0,0 +1,155 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:http/io_client.dart';
|
||||
import 'package:car_customer_app/exceptions/api_exception.dart';
|
||||
|
||||
typedef FactoryConstructor<U> = U Function(dynamic);
|
||||
|
||||
class APIError {
|
||||
int errorCode;
|
||||
String errorMessage;
|
||||
|
||||
APIError(this.errorCode, this.errorMessage);
|
||||
|
||||
Map<String, dynamic> toJson() => {'errorCode': errorCode, 'errorMessage': errorMessage};
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return jsonEncode(this);
|
||||
}
|
||||
}
|
||||
|
||||
APIException _throwAPIException(Response response) {
|
||||
switch (response.statusCode) {
|
||||
case 400:
|
||||
APIError? apiError;
|
||||
if (response.body != null && response.body.isNotEmpty) {
|
||||
var jsonError = jsonDecode(response.body);
|
||||
apiError = APIError(jsonError['errorCode'], jsonError['errorMessage']);
|
||||
}
|
||||
return APIException(APIException.BAD_REQUEST, error: apiError);
|
||||
case 401:
|
||||
return APIException(APIException.UNAUTHORIZED);
|
||||
case 403:
|
||||
return APIException(APIException.FORBIDDEN);
|
||||
case 404:
|
||||
return APIException(APIException.NOT_FOUND);
|
||||
case 500:
|
||||
return APIException(APIException.INTERNAL_SERVER_ERROR);
|
||||
case 444:
|
||||
var downloadUrl = response.headers["location"];
|
||||
return APIException(APIException.UPGRADE_REQUIRED, arguments: downloadUrl);
|
||||
default:
|
||||
return APIException(APIException.OTHER);
|
||||
}
|
||||
}
|
||||
|
||||
class ApiClient {
|
||||
static final ApiClient _instance = ApiClient._internal();
|
||||
|
||||
ApiClient._internal();
|
||||
|
||||
factory ApiClient() => _instance;
|
||||
|
||||
Future<U> postJsonForObject<T, U>(FactoryConstructor<U> factoryConstructor, String url, T jsonObject,
|
||||
{String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0}) async {
|
||||
var _headers = {'Accept': 'application/json'};
|
||||
if (headers != null && headers.isNotEmpty) {
|
||||
_headers.addAll(headers);
|
||||
}
|
||||
if (!kReleaseMode) {
|
||||
print("Url:$url");
|
||||
print("body:$jsonObject");
|
||||
}
|
||||
var response = await postJsonForResponse(url, jsonObject, token: token, queryParameters: queryParameters, headers: _headers, retryTimes: retryTimes);
|
||||
try {
|
||||
var jsonData = jsonDecode(response.body);
|
||||
return factoryConstructor(jsonData);
|
||||
} catch (ex) {
|
||||
throw APIException(APIException.BAD_RESPONSE_FORMAT, arguments: ex);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Response> postJsonForResponse<T>(String url, T jsonObject, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0}) async {
|
||||
String? requestBody;
|
||||
if (jsonObject != null) {
|
||||
requestBody = jsonEncode(jsonObject);
|
||||
if (headers == null) {
|
||||
headers = {'Content-Type': 'application/json'};
|
||||
} else {
|
||||
headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
}
|
||||
|
||||
return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes);
|
||||
}
|
||||
|
||||
Future<Response> _postForResponse(String url, requestBody, {String? token, Map<String, dynamic>? queryParameters, Map<String, String>? headers, int retryTimes = 0}) async {
|
||||
try {
|
||||
var _headers = <String, String>{};
|
||||
if (token != null) {
|
||||
_headers['Authorization'] = 'Bearer $token';
|
||||
}
|
||||
|
||||
if (headers != null && headers.isNotEmpty) {
|
||||
_headers.addAll(headers);
|
||||
}
|
||||
|
||||
if (queryParameters != null) {
|
||||
var queryString = new Uri(queryParameters: queryParameters).query;
|
||||
url = url + '?' + queryString;
|
||||
}
|
||||
var response = await _post(Uri.parse(url), body: requestBody, headers: _headers).timeout(Duration(seconds: 15));
|
||||
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
return response;
|
||||
} else {
|
||||
throw _throwAPIException(response);
|
||||
}
|
||||
} on SocketException catch (e) {
|
||||
if (retryTimes > 0) {
|
||||
print('will retry after 3 seconds...');
|
||||
await Future.delayed(Duration(seconds: 3));
|
||||
return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
|
||||
} else {
|
||||
throw APIException(APIException.OTHER, arguments: e);
|
||||
}
|
||||
} on HttpException catch (e) {
|
||||
if (retryTimes > 0) {
|
||||
print('will retry after 3 seconds...');
|
||||
await Future.delayed(Duration(seconds: 3));
|
||||
return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
|
||||
} else {
|
||||
throw APIException(APIException.OTHER, arguments: e);
|
||||
}
|
||||
} on TimeoutException catch (e) {
|
||||
throw APIException(APIException.TIMEOUT, arguments: e);
|
||||
} on ClientException catch (e) {
|
||||
if (retryTimes > 0) {
|
||||
print('will retry after 3 seconds...');
|
||||
await Future.delayed(Duration(seconds: 3));
|
||||
return await _postForResponse(url, requestBody, token: token, queryParameters: queryParameters, headers: headers, retryTimes: retryTimes - 1);
|
||||
} else {
|
||||
throw APIException(APIException.OTHER, arguments: e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool _certificateCheck(X509Certificate cert, String host, int port) => true;
|
||||
|
||||
Future<T> _withClient<T>(Future<T> Function(Client) fn) async {
|
||||
var httpClient = HttpClient()..badCertificateCallback = _certificateCheck;
|
||||
var client = IOClient(httpClient);
|
||||
try {
|
||||
return await fn(client);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
Future<Response> _post(url, {Map<String, String>? headers, body, Encoding? encoding}) => _withClient((client) => client.post(url, headers: headers, body: body, encoding: encoding));
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:car_customer_app/classes/consts.dart';
|
||||
import 'package:car_customer_app/models/content_info_model.dart';
|
||||
import 'package:car_customer_app/models/member_model.dart';
|
||||
import 'package:car_customer_app/models/surah_model.dart';
|
||||
|
||||
import 'api_client.dart';
|
||||
|
||||
class TangheemUserApiClient {
|
||||
static final TangheemUserApiClient _instance = TangheemUserApiClient._internal();
|
||||
|
||||
TangheemUserApiClient._internal();
|
||||
|
||||
factory TangheemUserApiClient() => _instance;
|
||||
|
||||
Future<SurahModel> getSurahs() async {
|
||||
String url = "${ApiConsts.tangheemUsers}AlSuar_Get";
|
||||
var postParams = {};
|
||||
return await ApiClient().postJsonForObject((json) => SurahModel.fromJson(json), url, postParams);
|
||||
}
|
||||
|
||||
Future<MemberModel> getMembers() async {
|
||||
String url = "${ApiConsts.tangheemUsers}Committee_Get";
|
||||
var postParams = {};
|
||||
return await ApiClient().postJsonForObject((json) => MemberModel.fromJson(json), url, postParams);
|
||||
}
|
||||
|
||||
Future<ContentInfoModel> getContentInfo(int contentId) async {
|
||||
String url = "${ApiConsts.tangheemUsers}ContentInfo_Get";
|
||||
var postParams = {"contentTypeId": contentId};
|
||||
return await ApiClient().postJsonForObject((json) => ContentInfoModel.fromJson(json), url, postParams);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
import 'package:car_customer_app/models/content_info_model.dart';
|
||||
import 'package:car_customer_app/models/surah_model.dart';
|
||||
|
||||
class AppState {
|
||||
static final AppState _instance = AppState._internal();
|
||||
|
||||
AppState._internal();
|
||||
|
||||
factory AppState() => _instance;
|
||||
|
||||
SurahModel? _surahModel;
|
||||
|
||||
SurahModel? get getSurahModel => _surahModel;
|
||||
|
||||
void setSurahModel(SurahModel _surahModel) {
|
||||
this._surahModel = _surahModel;
|
||||
}
|
||||
|
||||
ContentInfoDataModel? _copyRight;
|
||||
|
||||
ContentInfoDataModel? get getContentInfoModel => _copyRight;
|
||||
|
||||
void setContentInfoModel(ContentInfoDataModel _copyRight) {
|
||||
this._copyRight = _copyRight;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class MyColors {
|
||||
static const Color primaryColor = Colors.white;
|
||||
static const Color accentColor = Colors.blue;
|
||||
static const Color darkIconColor = Color(0xff28323A);
|
||||
static const Color darkTextColor = Color(0xff2B353E);
|
||||
static const Color normalTextColor = Color(0xff5A5A5A);
|
||||
static const Color lightTextColor = Color(0xffBFBFBF);
|
||||
static const Color gradiantStartColor = Color(0xff33c0a5);
|
||||
static const Color gradiantEndColor = Color(0xff259db7 );
|
||||
static const Color textMixColor = Color(0xff2BB8A6);
|
||||
static const Color backgroundColor = Color(0xffF8F8F8);
|
||||
static const Color grey57Color = Color(0xff575757);
|
||||
static const Color grey77Color = Color(0xff777777);
|
||||
static const Color grey70Color = Color(0xff707070);
|
||||
static const Color greyACColor = Color(0xffACACAC);
|
||||
static const Color grey98Color = Color(0xff989898);
|
||||
static const Color lightGreyEFColor = Color(0xffEFEFEF);
|
||||
static const Color lightGreyEDColor = Color(0xffEDEDED);
|
||||
static const Color lightGreyEAColor = Color(0xffEAEAEA);
|
||||
static const Color darkWhiteColor = Color(0xffE0E0E0);
|
||||
static const Color redColor = Color(0xffD02127);
|
||||
static const Color yellowColor = Color(0xffF4E31C);
|
||||
static const Color backgroundBlackColor = Color(0xff202529);
|
||||
static const Color black = Color(0xff000000);
|
||||
static const Color white = Color(0xffffffff);
|
||||
static const Color green = Color(0xffffffff);
|
||||
static const Color borderColor = Color(0xffE8E8E8);
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
class ApiConsts {
|
||||
//static String baseUrl = "http://10.200.204.20:2801/"; // Local server
|
||||
static String baseUrl = "http://20.203.25.82"; // production server
|
||||
static String baseUrlServices = baseUrl + "/services/"; // production server
|
||||
// static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server
|
||||
static String authentication = baseUrlServices + "api/Authentication/";
|
||||
static String tangheemUsers = baseUrlServices + "api/TangheemUsers/";
|
||||
static String adminConfiguration = baseUrlServices + "api/AdminConfiguration/";
|
||||
static String user = baseUrlServices + "api/User/";
|
||||
}
|
||||
|
||||
class GlobalConsts {
|
||||
static String isRememberMe = "remember_me";
|
||||
static String email = "email";
|
||||
static String password = "password";
|
||||
static String bookmark = "bookmark";
|
||||
static String fontZoomSize = "font_zoom_size";
|
||||
static String welcomeVideoUrl = "welcomeVideoUrl";
|
||||
static String doNotShowWelcomeVideo = "doNotShowWelcomeVideo";
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:car_customer_app/exceptions/api_exception.dart';
|
||||
|
||||
class Utils {
|
||||
static bool _isLoadingVisible = false;
|
||||
|
||||
static bool get isLoading => _isLoadingVisible;
|
||||
|
||||
static void showToast(String message) {
|
||||
// Fluttertoast.showToast(
|
||||
// msg: message, toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.BOTTOM, timeInSecForIosWeb: 1, backgroundColor: Colors.black54, textColor: Colors.white, fontSize: 16.0);
|
||||
}
|
||||
|
||||
static dynamic getNotNullValue(List<dynamic> list, int index) {
|
||||
try {
|
||||
return list[index];
|
||||
} catch (ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static int stringToHex(String colorCode) {
|
||||
try {
|
||||
return int.parse(colorCode.replaceAll("#", "0xff"));
|
||||
} catch (ex) {
|
||||
return (0xff000000);
|
||||
}
|
||||
}
|
||||
|
||||
static void showLoading(BuildContext context) {
|
||||
WidgetsBinding.instance?.addPostFrameCallback((_) {
|
||||
_isLoadingVisible = true;
|
||||
// showDialog(
|
||||
// context: context,
|
||||
// barrierColor: ColorConsts.primaryBlack.withOpacity(0.5),
|
||||
// builder: (BuildContext context) => LoadingDialog(),
|
||||
// ).then((value) {
|
||||
// _isLoadingVisible = false;
|
||||
// });
|
||||
});
|
||||
}
|
||||
|
||||
static void hideLoading(BuildContext context) {
|
||||
if (_isLoadingVisible) {
|
||||
_isLoadingVisible = false;
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
_isLoadingVisible = false;
|
||||
}
|
||||
|
||||
static void handleException(dynamic exception, Function(String)? onErrorMessage) {
|
||||
String errorMessage;
|
||||
if (exception is APIException) {
|
||||
if (exception.message == APIException.UNAUTHORIZED) {
|
||||
return;
|
||||
} else {
|
||||
errorMessage = exception.error?.errorMessage ?? exception.message;
|
||||
}
|
||||
} else {
|
||||
errorMessage = APIException.UNKNOWN;
|
||||
}
|
||||
if (onErrorMessage != null) {
|
||||
onErrorMessage(errorMessage);
|
||||
} else {
|
||||
showToast(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
//class which loads components "in the background", i.e. ui does not depend on it
|
||||
|
||||
import 'package:car_customer_app/services/shared_preferences.dart';
|
||||
import 'package:injector/injector.dart';
|
||||
//import 'package:revocheckapp/services/firebase_service.dart';
|
||||
|
||||
|
||||
class BackgroundLoader {
|
||||
Future loadBackgroundData() async {
|
||||
//init notification setting
|
||||
try {
|
||||
/*
|
||||
final isPromotionNotificationEnabled = await Injector.appInstance
|
||||
.getDependency<ISharedPreferences>()
|
||||
.promotionNotificationsEnabled;
|
||||
if (isPromotionNotificationEnabled == null) {
|
||||
await Injector.appInstance
|
||||
.getDependency<ISharedPreferences>()
|
||||
.setPromotionNotificationEnabled(true);
|
||||
Injector.appInstance
|
||||
.getDependency<IFirebaseService>()
|
||||
.subscribeForPromotions();
|
||||
} */
|
||||
} catch (_) {
|
||||
//something wend wrong, set it to true
|
||||
await Injector.appInstance
|
||||
.getDependency<ISharedPreferences>()
|
||||
.setPromotionNotificationEnabled(true);
|
||||
/*Injector.appInstance
|
||||
.getDependency<IFirebaseService>()
|
||||
.subscribeForPromotions();*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
// import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||||
// import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:car_customer_app/repo/account_repository.dart';
|
||||
import 'package:injector/injector.dart';
|
||||
|
||||
import 'background_loader.dart';
|
||||
|
||||
|
||||
class AppDependencies {
|
||||
static void addDependencies() {
|
||||
Injector injector = Injector.appInstance;
|
||||
|
||||
//add dependencies as needed
|
||||
injector.registerSingleton<IAcRepository>(() => AcRepository());
|
||||
|
||||
// injector.registerSingleton<IAcRepository>((injector) => AcRepository());
|
||||
|
||||
_addCrashlytics();
|
||||
_loadBackgroundTasksNonBlocking();
|
||||
}
|
||||
|
||||
static void _addCrashlytics() {
|
||||
// Set `enableInDevMode` to true to see reports while in debug mode
|
||||
// This is only to be used for confirming that reports are being
|
||||
// submitted as expected. It is not intended to be used for everyday
|
||||
// development.
|
||||
//Crashlytics.instance.enableInDevMode = true;
|
||||
|
||||
// Pass all uncaught errors from the framework to Crashlytics.
|
||||
// FlutterError.onError = Crashlytics.instance.recordFlutterError;
|
||||
}
|
||||
|
||||
static void _loadBackgroundTasksNonBlocking() {
|
||||
final backgroundLoader = BackgroundLoader();
|
||||
backgroundLoader.loadBackgroundData();
|
||||
}
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
|
||||
class AppLocalizations {
|
||||
static const Iterable<LocalizationsDelegate<dynamic>> localizationsDelegates =
|
||||
[
|
||||
// ... app-specific localization delegate[s] here
|
||||
// S.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate
|
||||
];
|
||||
|
||||
static const List<Locale> supportedLocales = [
|
||||
const Locale("en", "US")
|
||||
];
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:car_customer_app/api/api_client.dart';
|
||||
|
||||
class APIException implements Exception {
|
||||
static const String BAD_REQUEST = 'api_common_bad_request';
|
||||
static const String UNAUTHORIZED = 'api_common_unauthorized';
|
||||
static const String FORBIDDEN = 'api_common_forbidden';
|
||||
static const String NOT_FOUND = 'api_common_not_found';
|
||||
static const String INTERNAL_SERVER_ERROR = 'api_common_internal_server_error';
|
||||
static const String UPGRADE_REQUIRED = 'api_common_upgrade_required';
|
||||
static const String BAD_RESPONSE_FORMAT = 'api_common_bad_response_format';
|
||||
static const String OTHER = 'api_common_http_error';
|
||||
static const String TIMEOUT = 'api_common_http_timeout';
|
||||
static const String UNKNOWN = 'unexpected_error';
|
||||
|
||||
final String message;
|
||||
final APIError? error;
|
||||
final arguments;
|
||||
|
||||
const APIException(this.message, {this.arguments, this.error});
|
||||
|
||||
Map<String, dynamic> toJson() => {'message': message, 'error': error, 'arguments': '$arguments'};
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return jsonEncode(this);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
extension IntExtensions on int {
|
||||
Widget get height => SizedBox(height: toDouble());
|
||||
|
||||
Widget get width => SizedBox(width: toDouble());
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:car_customer_app/classes/colors.dart';
|
||||
|
||||
extension EmailValidator on String {
|
||||
Widget get toWidget => Text(this);
|
||||
|
||||
Widget toText({Color? color, bool isBold = false,double? fontSize}) => Text(
|
||||
this,
|
||||
style: TextStyle(fontSize: fontSize??10, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.4),
|
||||
);
|
||||
|
||||
Widget toText10({Color? color, bool isBold = false}) => Text(
|
||||
this,
|
||||
style: TextStyle(fontSize: 10, fontWeight: isBold ? FontWeight.bold : FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.4),
|
||||
);
|
||||
|
||||
Widget toText11({Color? color, bool isUnderLine = false, bool isBold = false}) => Text(
|
||||
this,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontWeight: isBold ? FontWeight.bold : FontWeight.w600,
|
||||
color: color ?? MyColors.darkTextColor,
|
||||
letterSpacing: -0.33,
|
||||
decoration: isUnderLine ? TextDecoration.underline : null),
|
||||
);
|
||||
|
||||
Widget toText12({Color? color, bool isUnderLine = false, bool isBold = false, bool isCenter = false, int maxLine = 0}) => Text(
|
||||
this,
|
||||
textAlign: isCenter ? TextAlign.center : null,
|
||||
maxLines: (maxLine > 0) ? maxLine : null,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: isBold ? FontWeight.bold : FontWeight.w600,
|
||||
color: color ?? MyColors.darkTextColor,
|
||||
letterSpacing: -0.72,
|
||||
decoration: isUnderLine ? TextDecoration.underline : null),
|
||||
);
|
||||
|
||||
Widget toText13({Color? color, bool isUnderLine = false}) => Text(
|
||||
this,
|
||||
style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: color ?? MyColors.darkTextColor, letterSpacing: -0.52, decoration: isUnderLine ? TextDecoration.underline : null),
|
||||
);
|
||||
|
||||
Widget toText14({Color? color, bool isBold = false}) => Text(
|
||||
this,
|
||||
style: TextStyle(color: color ?? MyColors.darkTextColor, fontSize: 14, letterSpacing: -0.48, fontWeight: isBold ? FontWeight.bold : FontWeight.w600),
|
||||
);
|
||||
|
||||
Widget toText16({Color? color, bool isBold = false}) => Text(
|
||||
this,
|
||||
style: TextStyle(color: color ?? MyColors.darkTextColor, fontSize: 16, letterSpacing: -0.64, fontWeight: isBold ? FontWeight.bold : FontWeight.w600),
|
||||
);
|
||||
|
||||
Widget toText17({Color? color, bool isBold = false}) => Text(
|
||||
this,
|
||||
style: TextStyle(color: color ?? MyColors.darkTextColor, fontSize: 17, letterSpacing: -0.68, fontWeight: isBold ? FontWeight.bold : FontWeight.w600),
|
||||
);
|
||||
|
||||
Widget toText22({Color? color, bool isBold = false}) => Text(
|
||||
this,
|
||||
style: TextStyle(height: 1, color: color ?? MyColors.darkTextColor, fontSize: 22, letterSpacing: -1.44, fontWeight: isBold ? FontWeight.bold : FontWeight.w600),
|
||||
);
|
||||
|
||||
Widget toText24({Color? color, bool isBold = false}) => Text(
|
||||
this,
|
||||
style: TextStyle(height: 23 / 24, color: color ?? MyColors.darkTextColor, fontSize: 24, letterSpacing: -1.44, fontWeight: isBold ? FontWeight.bold : FontWeight.w600),
|
||||
);
|
||||
|
||||
Widget toText32({Color? color, bool isBold = false}) => Text(
|
||||
this,
|
||||
style: TextStyle(height: 32 / 32, color: color ?? MyColors.darkTextColor, fontSize: 32, letterSpacing: -1.92, fontWeight: isBold ? FontWeight.bold : FontWeight.w600),
|
||||
);
|
||||
|
||||
bool isValidEmail() {
|
||||
return RegExp(r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$').hasMatch(this);
|
||||
}
|
||||
|
||||
String toFormattedDate() {
|
||||
String date = this.split("T")[0];
|
||||
String time = this.split("T")[1];
|
||||
var dates = date.split("-");
|
||||
return "${dates[2]} ${getMonth(int.parse(dates[1]))} ${dates[0]} ${DateFormat('hh:mm a').format(DateFormat('hh:mm:ss').parse(time))}";
|
||||
}
|
||||
|
||||
getMonth(int month) {
|
||||
switch (month) {
|
||||
case 1:
|
||||
return "January";
|
||||
case 2:
|
||||
return "February";
|
||||
case 3:
|
||||
return "March";
|
||||
case 4:
|
||||
return "April";
|
||||
case 5:
|
||||
return "May";
|
||||
case 6:
|
||||
return "June";
|
||||
case 7:
|
||||
return "July";
|
||||
case 8:
|
||||
return "August";
|
||||
case 9:
|
||||
return "September";
|
||||
case 10:
|
||||
return "October";
|
||||
case 11:
|
||||
return "November";
|
||||
case 12:
|
||||
return "December";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
extension WidgetExtensions on Widget {
|
||||
Widget onPress(VoidCallback onTap) => InkWell(onTap: onTap, child: this);
|
||||
|
||||
Widget paddingAll(double _value) => Padding(padding: EdgeInsets.all(_value), child: this);
|
||||
|
||||
Widget paddingOnly({double left = 0.0, double right = 0.0, double top = 0.0, double bottom = 0.0}) =>
|
||||
Padding(padding: EdgeInsets.only(left: left, right: right, top: top, bottom: bottom), child: this);
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
class ContentInfoModel {
|
||||
int? totalItemsCount;
|
||||
int? statusCode;
|
||||
String? message;
|
||||
List<ContentInfoDataModel>? data;
|
||||
|
||||
ContentInfoModel({this.totalItemsCount, this.statusCode, this.message, this.data});
|
||||
|
||||
ContentInfoModel.fromJson(Map<String, dynamic> json) {
|
||||
totalItemsCount = json['totalItemsCount'];
|
||||
statusCode = json['statusCode'];
|
||||
message = json['message'];
|
||||
if (json['data'] != null) {
|
||||
data = [];
|
||||
json['data'].forEach((v) {
|
||||
data?.add(new ContentInfoDataModel.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['totalItemsCount'] = this.totalItemsCount;
|
||||
data['statusCode'] = this.statusCode;
|
||||
data['message'] = this.message;
|
||||
if (this.data != null) {
|
||||
data['data'] = this.data?.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class ContentInfoDataModel {
|
||||
int? contentInfoId;
|
||||
int? contentTypeId;
|
||||
String? content;
|
||||
String? contentTypeNameEn;
|
||||
String? contentTypeNameAr;
|
||||
String? fileName;
|
||||
String? exposeFilePath;
|
||||
|
||||
ContentInfoDataModel({this.contentInfoId, this.contentTypeId, this.content, this.contentTypeNameEn, this.contentTypeNameAr, this.fileName, this.exposeFilePath});
|
||||
|
||||
ContentInfoDataModel.fromJson(Map<String, dynamic> json) {
|
||||
contentInfoId = json['contentInfoId'];
|
||||
contentTypeId = json['contentTypeId'];
|
||||
content = json['content'];
|
||||
contentTypeNameEn = json['contentTypeNameEn'];
|
||||
contentTypeNameAr = json['contentTypeNameAr'];
|
||||
fileName = json['fileName'];
|
||||
exposeFilePath = json['exposeFilePath'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['contentInfoId'] = this.contentInfoId;
|
||||
data['contentTypeId'] = this.contentTypeId;
|
||||
data['content'] = this.content;
|
||||
data['contentTypeNameEn'] = this.contentTypeNameEn;
|
||||
data['contentTypeNameAr'] = this.contentTypeNameAr;
|
||||
data['fileName'] = this.fileName;
|
||||
data['exposeFilePath'] = this.exposeFilePath;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
class MemberModel {
|
||||
int? totalItemsCount;
|
||||
int? statusCode;
|
||||
String? message;
|
||||
List<MemberDataModel>? data;
|
||||
|
||||
MemberModel({this.totalItemsCount, this.statusCode, this.message, this.data});
|
||||
|
||||
MemberModel.fromJson(Map<String, dynamic> json) {
|
||||
totalItemsCount = json['totalItemsCount'];
|
||||
statusCode = json['statusCode'];
|
||||
message = json['message'];
|
||||
if (json['data'] != null) {
|
||||
data = [];
|
||||
json['data'].forEach((v) {
|
||||
data?.add(new MemberDataModel.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['totalItemsCount'] = this.totalItemsCount;
|
||||
data['statusCode'] = this.statusCode;
|
||||
data['message'] = this.message;
|
||||
if (this.data != null) {
|
||||
data['data'] = this.data?.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class MemberDataModel {
|
||||
int? committeeId;
|
||||
String? firstName;
|
||||
String? lastName;
|
||||
String? description;
|
||||
String? picture;
|
||||
int? orderNo;
|
||||
|
||||
MemberDataModel({this.committeeId, this.firstName, this.lastName, this.description, this.picture, this.orderNo});
|
||||
|
||||
MemberDataModel.fromJson(Map<String, dynamic> json) {
|
||||
committeeId = json['committeeId'];
|
||||
firstName = json['firstName'];
|
||||
lastName = json['lastName'];
|
||||
description = json['description'];
|
||||
picture = json['picture'];
|
||||
orderNo = json['orderNo'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['committeeId'] = this.committeeId;
|
||||
data['firstName'] = this.firstName;
|
||||
data['lastName'] = this.lastName;
|
||||
data['description'] = this.description;
|
||||
data['picture'] = this.picture;
|
||||
data['orderNo'] = this.orderNo;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
class SurahModel {
|
||||
int? totalItemsCount;
|
||||
int? statusCode;
|
||||
String? message;
|
||||
List<SurahModelData>? data;
|
||||
|
||||
SurahModel({this.totalItemsCount, this.statusCode, this.message, this.data});
|
||||
|
||||
SurahModel.fromJson(Map<String, dynamic> json) {
|
||||
totalItemsCount = json['totalItemsCount'];
|
||||
statusCode = json['statusCode'];
|
||||
message = json['message'];
|
||||
if (json['data'] != null) {
|
||||
data = [];
|
||||
json['data'].forEach((v) {
|
||||
data?.add(SurahModelData.fromJson(v));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['totalItemsCount'] = totalItemsCount;
|
||||
data['statusCode'] = statusCode;
|
||||
data['message'] = message;
|
||||
if (this.data != null) {
|
||||
data['data'] = this.data?.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class SurahModelData {
|
||||
int? id;
|
||||
int? surahID;
|
||||
String? nameAR;
|
||||
String? nameEN;
|
||||
int? numberOfAyahs;
|
||||
String? englishNameTranslation;
|
||||
int? revelationID;
|
||||
String? revelationType;
|
||||
int? startPageNo;
|
||||
int? endPageNo;
|
||||
|
||||
SurahModelData({this.id, this.surahID, this.nameAR, this.nameEN, this.numberOfAyahs, this.englishNameTranslation, this.revelationID, this.revelationType, this.startPageNo, this.endPageNo});
|
||||
|
||||
SurahModelData.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
surahID = json['surahID'];
|
||||
nameAR = json['nameAR'];
|
||||
nameEN = json['nameEN'];
|
||||
numberOfAyahs = json['numberOfAyahs'];
|
||||
englishNameTranslation = json['englishNameTranslation'];
|
||||
revelationID = json['revelation_ID'];
|
||||
revelationType = json['revelationType'];
|
||||
startPageNo = json['startPageNo'];
|
||||
endPageNo = json['endPageNo'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['id'] = this.id;
|
||||
data['surahID'] = this.surahID;
|
||||
data['nameAR'] = this.nameAR;
|
||||
data['nameEN'] = this.nameEN;
|
||||
data['numberOfAyahs'] = this.numberOfAyahs;
|
||||
data['englishNameTranslation'] = this.englishNameTranslation;
|
||||
data['revelation_ID'] = this.revelationID;
|
||||
data['revelationType'] = this.revelationType;
|
||||
data['startPageNo'] = this.startPageNo;
|
||||
data['endPageNo'] = this.endPageNo;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Counter with ChangeNotifier, DiagnosticableTreeMixin {
|
||||
int _count = 0;
|
||||
|
||||
int get count => _count;
|
||||
|
||||
void increment() {
|
||||
_count++;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Makes `Counter` readable inside the devtools by listing all of its properties
|
||||
@override
|
||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||
super.debugFillProperties(properties);
|
||||
properties.add(IntProperty('count', count));
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:car_customer_app/models/account.dart';
|
||||
import 'package:car_customer_app/models/response_models.dart';
|
||||
import 'package:car_customer_app/services/backend_service.dart';
|
||||
import 'package:injector/injector.dart';
|
||||
|
||||
|
||||
|
||||
abstract class IAcRepository {
|
||||
Future<Account> getAccountList();
|
||||
|
||||
Future<BackendResponse> updateAccount(String dataAsJson);
|
||||
}
|
||||
|
||||
class AcRepository implements IAcRepository {
|
||||
static const String ACCOUNT_API_CONTROLLER_MOBILE =
|
||||
"AccountApiControllerMobile/";
|
||||
|
||||
static const String ACCOUNT_LIST = ACCOUNT_API_CONTROLLER_MOBILE + "list";
|
||||
static const String UPDATE_LIST =
|
||||
ACCOUNT_API_CONTROLLER_MOBILE + "saveaccountselected";
|
||||
|
||||
@override
|
||||
Future<Account> getAccountList() async {
|
||||
BackendResponse response = await Injector.appInstance
|
||||
.getDependency<IBackendApiService>()
|
||||
.getAuthenticatedAPI(ACCOUNT_LIST);
|
||||
|
||||
if (response != null && response.isOk) {
|
||||
return Account.fromJson(response.result);
|
||||
} else {
|
||||
throw Exception();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BackendResponse> updateAccount(String dataAsJson) async {
|
||||
BackendResponse response = await Injector.appInstance
|
||||
.getDependency<IBackendApiService>()
|
||||
.postAuthenticatedAPI(UPDATE_LIST, dataAsJson);
|
||||
|
||||
if (response != null && response.isOk) {
|
||||
//if parsing failed, throw exception
|
||||
return response;
|
||||
} else {
|
||||
throw Exception();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,127 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:car_customer_app/models/response_models.dart';
|
||||
import 'package:car_customer_app/services/secure_storage.dart';
|
||||
import 'package:http/http.dart';
|
||||
import 'package:injector/injector.dart';
|
||||
|
||||
import 'http_service.dart';
|
||||
import 'network_service.dart';
|
||||
|
||||
abstract class IBackendApiService {
|
||||
Future<BackendResponse> getUnauthenticatedAPI(String route);
|
||||
|
||||
Future<BackendResponse> getAuthenticatedAPI(String route);
|
||||
|
||||
Future<BackendResponse> postUnauthenticatedAPI(
|
||||
String route, String dataAsJson);
|
||||
|
||||
Future<BackendResponse> postAuthenticatedAPI(String route, String dataAsJson);
|
||||
|
||||
Future<BackendResponse> deleteAuthenticatedAPI(String route, String id);
|
||||
}
|
||||
|
||||
class BackendApiService implements IBackendApiService {
|
||||
static String _homeUrl = "https://check.revotec.eu/check2/";
|
||||
static String _serverApiBaseUrl = _homeUrl + "mapi/v1/";
|
||||
|
||||
static String get homeUrl => _homeUrl;
|
||||
|
||||
final ISecureStorage _secureStorage =
|
||||
Injector.appInstance.getDependency<ISecureStorage>();
|
||||
final IHttpService _httpService =
|
||||
Injector.appInstance.getDependency<IHttpService>();
|
||||
|
||||
///internal helper functions which executes the given api call
|
||||
///and wraps the response
|
||||
Future<BackendResponse> _callApi(Future<dynamic> callback) async {
|
||||
Response response;
|
||||
try {
|
||||
//execute future
|
||||
response = await callback;
|
||||
//check response code, and if not ok return isOk = false
|
||||
//200 for Get
|
||||
//201 for Post
|
||||
|
||||
// print("res121: " +
|
||||
// response.statusCode.toString() +
|
||||
// " Body:" +
|
||||
// response.body.toString());
|
||||
//if delete request sent so server is returning 204 in case of success.
|
||||
if (response.statusCode == 204)
|
||||
return BackendResponse(id: 1, isOk: true, result: null);
|
||||
|
||||
if (response.statusCode != 200 && response.statusCode != 201)
|
||||
return BackendResponse(id: -1, isOk: false, result: null);
|
||||
//if response code is good then parse message and return parsed response
|
||||
return BackendResponse.fromJson(json.decode(response.body));
|
||||
//return BackendResponse.fromJson(dioResponse.body);
|
||||
} catch (e) {
|
||||
return BackendResponse(id: -1, isOk: false, result: null);
|
||||
// try {
|
||||
// return BackendResponse.fromJson(json.decode(response.body));
|
||||
// } catch (e) {
|
||||
// return BackendResponse(id:-1, isOk:false,result: null);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BackendResponse> getAuthenticatedAPI(String route) async {
|
||||
await checkConnection();
|
||||
final token = await _secureStorage.readBearerToken();
|
||||
return _callApi(_httpService.get(_serverApiBaseUrl + route, headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': '*/*',
|
||||
HttpHeaders.authorizationHeader: "Bearer $token"
|
||||
}));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BackendResponse> getUnauthenticatedAPI(String route) async {
|
||||
await checkConnection();
|
||||
return _callApi(_httpService.get(_serverApiBaseUrl + route,
|
||||
headers: {'Content-Type': 'application/json', 'Accept': '*/*'}));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BackendResponse> postAuthenticatedAPI(
|
||||
String route, String dataAsJson) async {
|
||||
await checkConnection();
|
||||
final token = await _secureStorage.readBearerToken();
|
||||
// print("res121: " + _serverApiBaseUrl + route);
|
||||
return _callApi(_httpService
|
||||
.post(_serverApiBaseUrl + route, body: dataAsJson, headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': '*/*',
|
||||
HttpHeaders.authorizationHeader: "Bearer $token"
|
||||
}));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BackendResponse> postUnauthenticatedAPI(
|
||||
String route, String dataAsJson) async {
|
||||
await checkConnection();
|
||||
return _callApi(_httpService.post(_serverApiBaseUrl + route,
|
||||
body: dataAsJson, headers: {'Content-Type': 'application/json'}));
|
||||
}
|
||||
|
||||
Future<void> checkConnection() async {
|
||||
if (!(await Injector.appInstance
|
||||
.getDependency<INetworkService>()
|
||||
.isHostAvailable(_homeUrl))) throw NetworkException();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<BackendResponse> deleteAuthenticatedAPI(
|
||||
String route, String id) async {
|
||||
await checkConnection();
|
||||
final token = await _secureStorage.readBearerToken();
|
||||
return _callApi(
|
||||
_httpService.delete(_serverApiBaseUrl + route + "/" + id, headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': '*/*',
|
||||
HttpHeaders.authorizationHeader: "Bearer $token"
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -1,180 +0,0 @@
|
||||
/*
|
||||
import 'dart:io' show Platform;
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
|
||||
abstract class IFirebaseService {
|
||||
Future<String> get token;
|
||||
|
||||
Future<dynamic> backgroundMessageHandler(Map<String, dynamic> message);
|
||||
|
||||
Future<dynamic> messageHandler(Map<String, dynamic> message);
|
||||
|
||||
Future<dynamic> onLaunch(Map<String, dynamic> message);
|
||||
|
||||
Future<dynamic> onResume(Map<String, dynamic> message);
|
||||
|
||||
void subscribeForPromotions();
|
||||
|
||||
void unsubscribeFromPromotions();
|
||||
}
|
||||
|
||||
//https://medium.com/@SebastianEngel/easy-push-notifications-with-flutter-and-firebase-cloud-messaging-d96084f5954f
|
||||
class FirebaseService implements IFirebaseService {
|
||||
FirebaseMessaging _firebaseMessaging;
|
||||
|
||||
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin;
|
||||
|
||||
FirebaseService() {.
|
||||
_firebaseMessaging = FirebaseMessaging();
|
||||
|
||||
//https://github.com/FirebaseExtended/flutterfire/issues/1695
|
||||
_firebaseMessaging.configure(
|
||||
onMessage: messageHandler,
|
||||
onBackgroundMessage:
|
||||
Platform.isAndroid ? myBackgroundMessageHandler : null,
|
||||
onLaunch: onLaunch,
|
||||
onResume: onResume,
|
||||
);
|
||||
|
||||
//monitor firebase token changes
|
||||
//https://firebase.google.com/docs/cloud-messaging/android/client#sample-register
|
||||
///The registration token may change when:
|
||||
//
|
||||
//The app deletes Instance ID
|
||||
//The app is restored on a new device
|
||||
//The user uninstalls/reinstall the app
|
||||
//The user clears app data.
|
||||
///
|
||||
|
||||
//for the first release we don't care about token refreshes
|
||||
/*Stream<String> fcmStream = _firebaseMessaging.onTokenRefresh;
|
||||
fcmStream.listen((token) {
|
||||
|
||||
});*/
|
||||
|
||||
//ios specific settings
|
||||
//taken from https://github.com/FirebaseExtended/flutterfire/blob/master/packages/firebase_messaging/example/lib/main.dart
|
||||
_firebaseMessaging.requestNotificationPermissions(
|
||||
const IosNotificationSettings(
|
||||
sound: true, badge: true, alert: true, provisional: true));
|
||||
_firebaseMessaging.onIosSettingsRegistered
|
||||
.listen((IosNotificationSettings settings) {
|
||||
print("Settings registered: $settings");
|
||||
});
|
||||
|
||||
var initializationSettingsAndroid =
|
||||
AndroidInitializationSettings('app_icon');
|
||||
var initializationSettingsIOS =
|
||||
IOSInitializationSettings(onDidReceiveLocalNotification: onDidReceiveLocalNotification);
|
||||
var initializationSettings = InitializationSettings(
|
||||
initializationSettingsAndroid, initializationSettingsIOS);
|
||||
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
||||
flutterLocalNotificationsPlugin.initialize(initializationSettings,
|
||||
onSelectNotification: selectNotification);
|
||||
}
|
||||
|
||||
Future<dynamic> onDidReceiveLocalNotification(int id, String title, String body, String payload) async{
|
||||
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
|
||||
'new_message_channel_id',
|
||||
'Neue Nachricht',
|
||||
'Channel für neue Nachrichten',
|
||||
importance: Importance.Max,
|
||||
priority: Priority.High,
|
||||
ticker: 'ticker');
|
||||
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
|
||||
var platformChannelSpecifics = NotificationDetails(
|
||||
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
0,
|
||||
title,
|
||||
body,
|
||||
platformChannelSpecifics);
|
||||
}
|
||||
|
||||
@override
|
||||
Future backgroundMessageHandler(Map<String, dynamic> message) async {
|
||||
await myBackgroundMessageHandler(message);
|
||||
}
|
||||
|
||||
@override
|
||||
Future messageHandler(Map<String, dynamic> message) async {
|
||||
print("onMessage: $message");
|
||||
|
||||
// initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
|
||||
|
||||
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
|
||||
'new_message_channel_id',
|
||||
'Neue Nachricht',
|
||||
'Channel für neue Nachrichten',
|
||||
importance: Importance.Max,
|
||||
priority: Priority.High,
|
||||
ticker: 'ticker');
|
||||
var iOSPlatformChannelSpecifics = IOSNotificationDetails();
|
||||
var platformChannelSpecifics = NotificationDetails(
|
||||
androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
|
||||
|
||||
if(Platform.isAndroid) {
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
0,
|
||||
message["notification"]["title"],
|
||||
message["notification"]["body"],
|
||||
platformChannelSpecifics);
|
||||
}else if(Platform.isIOS){
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
0,
|
||||
message["aps"]["alert"]["title"],
|
||||
message["aps"]["alert"]["body"],
|
||||
platformChannelSpecifics);
|
||||
}
|
||||
}
|
||||
|
||||
Future selectNotification(String payload) async {
|
||||
if (payload != null) {
|
||||
debugPrint('notification payload: ' + payload);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future onLaunch(Map<String, dynamic> message) async {
|
||||
print("onLaunch: $message");
|
||||
}
|
||||
|
||||
@override
|
||||
Future onResume(Map<String, dynamic> message) async {
|
||||
print("onResume: $message");
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> get token => _firebaseMessaging.getToken();
|
||||
|
||||
@override
|
||||
void subscribeForPromotions() {
|
||||
_firebaseMessaging.subscribeToTopic("promotions");
|
||||
}
|
||||
|
||||
@override
|
||||
void unsubscribeFromPromotions() {
|
||||
_firebaseMessaging.unsubscribeFromTopic("promotions");
|
||||
}
|
||||
}
|
||||
|
||||
Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) {
|
||||
debugPrint("BACKGROUND MESSAGE RECEIVED");
|
||||
print("BACKGROUND MESSAGE RECEIVED");
|
||||
return Future.value(() => true);
|
||||
|
||||
/*if (message.containsKey('data')) {
|
||||
// Handle data message
|
||||
final dynamic data = message['data'];
|
||||
}
|
||||
|
||||
if (message.containsKey('notification')) {
|
||||
// Handle notification message
|
||||
final dynamic notification = message['notification'];
|
||||
}*/
|
||||
|
||||
// Or do other work.
|
||||
}
|
||||
*/
|
||||
@ -1,36 +0,0 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:async';
|
||||
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/http.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:injector/injector.dart';
|
||||
|
||||
abstract class IHttpService {
|
||||
Future<Response> post(url,
|
||||
{Map<String, String> headers, body, Encoding encoding});
|
||||
|
||||
Future<Response> get(url, {Map<String, String> headers});
|
||||
|
||||
Future<Response> delete(url, {Map<String, String> headers});
|
||||
}
|
||||
|
||||
class HttpService implements IHttpService {
|
||||
@override
|
||||
Future<Response> delete(url, {Map<String, String>? headers}) {
|
||||
return http.delete(url, headers: headers);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Response> get(url, {Map<String, String>? headers}) {
|
||||
return http.get(url, headers: headers);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Response> post(url,
|
||||
{Map<String, String>? headers, body, Encoding? encoding}) {
|
||||
return http.post(url, headers: headers, body: body, encoding: encoding);
|
||||
}
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
// import 'dart:io';
|
||||
//
|
||||
// import 'package:image_picker/image_picker.dart';
|
||||
//
|
||||
// abstract class IMediaService {
|
||||
// Future<File?> takePicture();
|
||||
//
|
||||
// Future<File?> openImageFromGallery();
|
||||
// }
|
||||
//
|
||||
// class MediaService implements IMediaService {
|
||||
// @override
|
||||
// Future<File?> openImageFromGallery() async {
|
||||
// final pickedFile =
|
||||
// await ImagePicker().getImage(source: ImageSource.gallery);
|
||||
// if (pickedFile == null) return null;
|
||||
// return File(pickedFile.path);
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// Future<File?> takePicture() async {
|
||||
// final pickedFile = await ImagePicker().getImage(source: ImageSource.camera);
|
||||
// if (pickedFile == null) return null;
|
||||
// return File(pickedFile.path);
|
||||
// }
|
||||
// }
|
||||
@ -1,25 +0,0 @@
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
abstract class INetworkService {
|
||||
Future<bool> isHostAvailable(String endpoint);
|
||||
}
|
||||
|
||||
class NetworkService implements INetworkService{
|
||||
@override
|
||||
Future<bool> isHostAvailable(String endpoint) async {
|
||||
try {
|
||||
final result = await InternetAddress.lookup(endpoint.substring(endpoint.indexOf('//')+2).substring(0,endpoint.substring(endpoint.indexOf('//')+2).indexOf('/')));
|
||||
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
|
||||
return true;
|
||||
} else{
|
||||
return false;
|
||||
}
|
||||
} on SocketException catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class NetworkException implements Exception {
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
abstract class ISecureStorage {
|
||||
Future<String> readBearerToken();
|
||||
|
||||
Future<void> clearUserCredentials();
|
||||
}
|
||||
|
||||
class SecureStorage implements ISecureStorage {
|
||||
///return bearer token if present, or null if not
|
||||
@override
|
||||
Future<String> readBearerToken() async {
|
||||
try {
|
||||
return "";
|
||||
} catch (_) {
|
||||
//an error occured returning null
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
///returns true if write was successful, false otherwise
|
||||
@override
|
||||
Future<bool> writeBearerToken(String token) async {
|
||||
try {
|
||||
await "";
|
||||
return true;
|
||||
} catch (_) {
|
||||
//an error occured returning false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clearUserCredentials() async {}
|
||||
}
|
||||
@ -1,119 +0,0 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:car_customer_app/models/config_model.dart';
|
||||
|
||||
import 'package:shared_preferences/shared_preferences.dart'
|
||||
as SharedPrefsPlugin;
|
||||
|
||||
///
|
||||
/// Taken from AlarmGuide Project
|
||||
///
|
||||
|
||||
abstract class ISharedPreferences {
|
||||
Future<int?> get authState;
|
||||
|
||||
Future<void> setAuthState(int authState);
|
||||
|
||||
Future<int?> get configState;
|
||||
|
||||
Future<void> setConfigState(int confState);
|
||||
|
||||
Future<ConfigModel?> get config;
|
||||
|
||||
Future<void> setConfig(ConfigModel config);
|
||||
|
||||
Future<bool?> get promotionNotificationsEnabled;
|
||||
|
||||
Future<void> setPromotionNotificationEnabled(bool newSetting);
|
||||
|
||||
Future<bool?> get helpAlreadyShown;
|
||||
|
||||
Future<void> setHelpAlreadyShown();
|
||||
|
||||
Future<int?> get useS3;
|
||||
|
||||
Future<void> setUseS3(int value);
|
||||
}
|
||||
|
||||
class SharedPreferences implements ISharedPreferences {
|
||||
static const String _AUTH_STATE_KEY = "auth_key";
|
||||
static const String _CONFIG_KEY = "config";
|
||||
static const String _CONFIG_STATE_KEY = "config_key";
|
||||
static const String _PROMOTION_NOTIFICATION_KEY = "promotion";
|
||||
static const String _HELP_ALREADY_SHOWN = "help_shown";
|
||||
static const String _USE_S3 = "s3";
|
||||
|
||||
@override
|
||||
Future<int?> get authState async {
|
||||
final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance();
|
||||
return sharedPrefs.getInt(_AUTH_STATE_KEY);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setAuthState(int authState) async {
|
||||
final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance();
|
||||
sharedPrefs.setInt(_AUTH_STATE_KEY, authState);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ConfigModel?> get config async {
|
||||
final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance();
|
||||
final configAsJson = sharedPrefs.getString(_CONFIG_KEY);
|
||||
return ConfigModel.fromJson(jsonDecode(configAsJson!));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setConfig(ConfigModel config) async {
|
||||
final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance();
|
||||
sharedPrefs.setString(_CONFIG_KEY, jsonEncode(config));
|
||||
setConfigState(1);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool?> get promotionNotificationsEnabled async {
|
||||
final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance();
|
||||
return sharedPrefs.getBool(_PROMOTION_NOTIFICATION_KEY);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setPromotionNotificationEnabled(bool newSetting) async {
|
||||
final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance();
|
||||
sharedPrefs.setBool(_PROMOTION_NOTIFICATION_KEY, newSetting);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool?> get helpAlreadyShown async {
|
||||
final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance();
|
||||
return sharedPrefs.getBool(_HELP_ALREADY_SHOWN);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setHelpAlreadyShown() async {
|
||||
final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance();
|
||||
sharedPrefs.setBool(_HELP_ALREADY_SHOWN, true);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int?> get configState async {
|
||||
final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance();
|
||||
return sharedPrefs.getInt(_CONFIG_STATE_KEY);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setConfigState(int confState) async {
|
||||
final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance();
|
||||
sharedPrefs.setInt(_CONFIG_STATE_KEY, confState);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setUseS3(int value) async {
|
||||
final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance();
|
||||
sharedPrefs.setInt(_USE_S3, value);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<int?> get useS3 async {
|
||||
final sharedPrefs = await SharedPrefsPlugin.SharedPreferences.getInstance();
|
||||
return sharedPrefs.getInt(_USE_S3);
|
||||
}
|
||||
}
|
||||
@ -1,170 +0,0 @@
|
||||
// import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:car_customer_app/theme/colors.dart';
|
||||
import 'package:car_customer_app/utils/utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sizer/sizer.dart';
|
||||
|
||||
enum TxtType {
|
||||
small,
|
||||
normal,
|
||||
heading1,
|
||||
heading2,
|
||||
heading3,
|
||||
appBar,
|
||||
}
|
||||
|
||||
class Txt extends StatelessWidget {
|
||||
String text;
|
||||
int? maxLines;
|
||||
double? fontSize;
|
||||
Color? color;
|
||||
bool? bold;
|
||||
bool? isUnderline;
|
||||
bool? isFlatButton;
|
||||
double? pedding;
|
||||
TextAlign? textAlign;
|
||||
FontWeight? fontWeight;
|
||||
Function? onTap;
|
||||
TxtType txtType;
|
||||
|
||||
Txt(this.text, {this.maxLines, this.color, this.bold, this.fontSize, this.isUnderline, this.isFlatButton, this.pedding, this.textAlign, this.fontWeight, this.onTap, this.txtType = TxtType.normal});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (isFlatButton != null)
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(right: pedding ?? 0, left: pedding ?? 0),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
onTap!();
|
||||
},
|
||||
customBorder: inkWellCorner(r: 4),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 14,
|
||||
right: 14,
|
||||
top: 6,
|
||||
bottom: 6,
|
||||
),
|
||||
child: getText(),
|
||||
),
|
||||
),
|
||||
);
|
||||
else
|
||||
return getText();
|
||||
}
|
||||
|
||||
Widget getText() {
|
||||
return Material(
|
||||
type: MaterialType.transparency,
|
||||
child: Text(
|
||||
text,
|
||||
maxLines: maxLines,
|
||||
textAlign: textAlign,
|
||||
overflow: maxLines != null ? TextOverflow.ellipsis : null,
|
||||
style: TextStyle(
|
||||
fontSize: fontSize ??
|
||||
(txtType == TxtType.small
|
||||
? 8.sp
|
||||
: txtType == TxtType.normal
|
||||
? 10.sp
|
||||
: txtType == TxtType.heading1
|
||||
? 11.sp
|
||||
: txtType == TxtType.heading2
|
||||
? 12.sp
|
||||
: txtType == TxtType.heading3
|
||||
? 13.sp
|
||||
: txtType == TxtType.appBar
|
||||
? 14.sp
|
||||
: 8.sp),
|
||||
color: color ??
|
||||
(txtType == TxtType.appBar
|
||||
? Colors.black
|
||||
: txtType == TxtType.heading1
|
||||
? headingColor
|
||||
: txtType == TxtType.heading2
|
||||
? headingColor
|
||||
: txtType == TxtType.heading3
|
||||
? headingColor
|
||||
: null),
|
||||
fontWeight: (fontWeight != null)
|
||||
? fontWeight
|
||||
: ((bold != null)
|
||||
? FontWeight.bold
|
||||
: (txtType == TxtType.appBar
|
||||
? FontWeight.bold
|
||||
: txtType == TxtType.heading1
|
||||
? FontWeight.bold
|
||||
: txtType == TxtType.heading2
|
||||
? FontWeight.bold
|
||||
: txtType == TxtType.heading3
|
||||
? FontWeight.bold
|
||||
: null)),
|
||||
decoration: (isUnderline != null) ? TextDecoration.underline : null,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// class TxtAuto extends StatelessWidget {
|
||||
// String text;
|
||||
// int? maxLines;
|
||||
// double? fontSize;
|
||||
// Color? color;
|
||||
// bool? bold;
|
||||
// bool? isUnderline;
|
||||
// bool? isFlatButton;
|
||||
// double? pedding;
|
||||
// TextAlign? textAlign;
|
||||
//
|
||||
// TxtAuto(
|
||||
// this.text, {
|
||||
// this.maxLines,
|
||||
// this.color,
|
||||
// this.bold,
|
||||
// this.fontSize,
|
||||
// this.isUnderline,
|
||||
// this.isFlatButton,
|
||||
// this.pedding,
|
||||
// this.textAlign,
|
||||
// });
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// if (isFlatButton != null)
|
||||
// return Padding(
|
||||
// padding: EdgeInsets.only(right: pedding ?? 0, left: pedding ?? 0),
|
||||
// child: InkWell(
|
||||
// onTap: () {},
|
||||
// customBorder: inkWellCorner(r: 4),
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.only(
|
||||
// left: 14,
|
||||
// right: 14,
|
||||
// top: 6,
|
||||
// bottom: 6,
|
||||
// ),
|
||||
// child: getText(),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// else
|
||||
// return getText();
|
||||
// }
|
||||
//
|
||||
// Widget getText() {
|
||||
// return AutoSizeText(
|
||||
// text,
|
||||
// maxLines: maxLines,
|
||||
// textAlign: textAlign,
|
||||
// overflow: maxLines != null ? TextOverflow.ellipsis : null,
|
||||
// style: TextStyle(
|
||||
// fontSize: fontSize,
|
||||
// color: color,
|
||||
// fontWeight: (bold != null) ? FontWeight.bold : null,
|
||||
// decoration: (isUnderline != null) ? TextDecoration.underline : null,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
Loading…
Reference in New Issue