Commit e41fc4fe authored by DatHV's avatar DatHV
Browse files

init

parent d87cb75e
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Mypoint Flutter App</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>mypoint_flutter_app</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
#import "GeneratedPluginRegistrant.h"
import Flutter
import UIKit
import XCTest
class RunnerTests: XCTestCase {
func testExample() {
// If you add code to the Runner application, consider adding tests here.
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
}
}
abstract class BaseModel {
BaseModel.fromJson(Map<String, dynamic> json);
BaseModel();
}
\ No newline at end of file
import 'package:json_annotation/json_annotation.dart';
part 'base_response_model.g.dart';
@JsonSerializable(genericArgumentFactories: true)
class BaseResponseModel<T> {
final int? code;
final String? status;
@JsonKey(name: "error_message")
final String? errorMessage;
final String? message;
final T? data;
bool get isSuccess {
final _code = code ?? 0;
if (_code >= 200 && _code < 299) return true;
return status == "success";
}
const BaseResponseModel({this.code, this.status, this.errorMessage, this.message, this.data});
factory BaseResponseModel.fromJson(Map<String, dynamic> json, T Function(Object? json) fromJsonT) {
return _$BaseResponseModelFromJson<T>(json, fromJsonT);
}
Map<String, dynamic> toJson(Object? Function(T value) toJsonT) => _$BaseResponseModelToJson<T>(this, toJsonT);
}
\ No newline at end of file
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'base_response_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
BaseResponseModel<T> _$BaseResponseModelFromJson<T>(
Map<String, dynamic> json,
T Function(Object? json) fromJsonT,
) => BaseResponseModel<T>(
code: (json['code'] as num?)?.toInt(),
status: json['status'] as String?,
errorMessage: json['error_message'] as String?,
message: json['message'] as String?,
data: _$nullableGenericFromJson(json['data'], fromJsonT),
);
Map<String, dynamic> _$BaseResponseModelToJson<T>(
BaseResponseModel<T> instance,
Object? Function(T value) toJsonT,
) => <String, dynamic>{
'code': instance.code,
'status': instance.status,
'error_message': instance.errorMessage,
'message': instance.message,
'data': _$nullableGenericToJson(instance.data, toJsonT),
};
T? _$nullableGenericFromJson<T>(
Object? input,
T Function(Object? json) fromJson,
) => input == null ? null : fromJson(input);
Object? _$nullableGenericToJson<T>(
T? input,
Object? Function(T value) toJson,
) => input == null ? null : toJson(input);
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get/get.dart';
import '../dio_http_service/dio_http_service.dart';
class BaseViewModel extends GetxController with WidgetsBindingObserver {
var isShowLoading = false;
RxBool isShowKey = false.obs;
FToast fToast = FToast();
@override
void onInit() {
super.onInit();
WidgetsBinding.instance.addObserver(this);
}
@override
void onClose() {
WidgetsBinding.instance.removeObserver(this);
super.onClose();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeMetrics() {
final bottomInset = WidgetsBinding.instance.platformDispatcher.views.first.viewInsets.bottom;
final newValue = bottomInset > 0.0;
if (newValue != isShowKey.value) {
isShowKey.value = newValue;
}
}
showLoading({int timeout = receiveTimeout}) {
Future.delayed(Duration(seconds: timeout), () {
hideLoading();
});
Future.delayed(Duration.zero, () {
if (isShowLoading) return;
isShowLoading = true;
Get.dialog(
Center(
child: SizedBox(
width: 40,
height: 80,
child: Stack(
children: [
CircularProgressIndicator(),
],
),
),
),
barrierDismissible: false,
);
});
}
hideLoading() {
if (isShowLoading) {
isShowLoading = false;
Get.back();
}
}
showMessage(BuildContext context, String message) {
fToast.init(context);
Widget toast = Container(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25.0),
color: Colors.black.withValues(alpha: 0.8),
),
child: Text(
message,
style: TextStyle(color: Colors.white),
),
);
fToast.showToast(
child: toast,
gravity: ToastGravity.BOTTOM,
toastDuration: Duration(seconds: 2),
);
}
}
import 'package:mypoint_flutter_app/networking/restful_api.dart';
import '../dio_http_service/dio_http_service.dart';
import 'base_view_model.dart';
class RestfulApiViewModel extends BaseViewModel {
final RestfulAPIClient _apiService = RestfulAPIClient(DioHttpService().getDio());
RestfulAPIClient get client => _apiService;
@override
void onInit() {
super.onInit();
}
}
\ No newline at end of file
class APIPaths {
static const String baseUrl = "https://api.mypoint.com.vn/8854/gup2start/rest";
static const String checkUpdate = "/version-management-service/api/v1.0/check-customer-software-update";
}
typedef CallbackActionBool = Callback<bool>;
typedef CallbackActionString = Callback<String>;
typedef Callback<T> = CallbackReturn<void, T>;
typedef CallbackReturn<R, I> = R Function(I data);
\ No newline at end of file
class Constants {
static get commonError => "Có lỗi xảy ra. Vui lòng thử lại!";
}
\ No newline at end of file
class EvnConfig {
// static final EvnConfig _instance = EvnConfig._internal();
}
\ No newline at end of file
import 'package:dio/dio.dart';
import 'dio_http_service.dart';
mixin ApiHelper {
final DioHttpService _api = DioHttpService();
initNetWork(String baseUrl) {
_api.init();
_api.setBaseUrl(baseUrl);
}
Dio getDio() {
return _api.getDio();
}
String getBaseUrl() {
return _api.getDio().options.baseUrl;
}
}
\ No newline at end of file
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'exception_interceptor.dart';
import 'logger_interceptor.dart';
import 'modify_request_interceptor.dart';
const int connectTimeout = 10; // seconds
const int receiveTimeout = 15; // second
class DioHttpService {
static final DioHttpService _instance = DioHttpService._internal();
late Dio _dio;
String domain = '';
factory DioHttpService() {
return _instance;
}
void init() async {
final Map<String, String> defaultHeaders = {'Accept': '*/*', 'Content-type': 'application/json'};
// Set default configs
_dio.options.connectTimeout = const Duration(seconds: connectTimeout); //10s
_dio.options.receiveTimeout = const Duration(seconds: receiveTimeout);
_dio.options.headers = defaultHeaders;
_dio.interceptors.add(ModifyRequestInterceptor());
if(kDebugMode) {
_dio.interceptors.add(LoggerInterceptor());
}
_dio.interceptors.add(ExceptionInterceptor());
}
void setBaseUrl(String newUrl) {
_dio.options.baseUrl = newUrl;
}
DioHttpService._internal() {
// Initialize Dio instance with default configurations
_dio = Dio(BaseOptions(
baseUrl: domain,
connectTimeout: Duration(seconds: connectTimeout),
receiveTimeout: Duration(seconds: receiveTimeout),
));
}
Dio getDio() {
return _dio;
}
}
\ No newline at end of file
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:mypoint_flutter_app/shared/e_grab_navigate.dart';
class ExceptionInterceptor extends Interceptor with navigateHelper {
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
switch (err.type) {
case DioExceptionType.connectionTimeout:
case DioExceptionType.receiveTimeout:
case DioExceptionType.connectionError:
showPopupErrorMessage("Kết nối mạng không ổn định.\nVui lòng thử lại!");
break;
default:
return super.onError(err, handler);
}
}
_handleStatusCode(int? statusCode) {
switch (statusCode) {
case 400:
//FIXME
print('Bad request.');
break;
case 401:
//FIXME
break;
case 500:
showPopupErrorMessage("Lỗi không xác định");
break;
default:
if (kDebugMode) {
print('Something went wrong');
}
break;
}
}
}
import 'package:dio/dio.dart';
import 'package:logger/logger.dart';
class LoggerInterceptor extends Interceptor {
Logger logger = Logger(
// Customize the printer
printer: PrettyPrinter(
methodCount: 0,
lineLength: 5000,
printTime: false,
),
);
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
final options = err.requestOptions;
final requestPath = '${options.baseUrl}${options.path}';
logger.e('${options.method} request => $requestPath\nError: ${err.error}, Message: ${err.message}');
return super.onError(err, handler);
}
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
final requestBody = options.data;
final requestPath = '${options.baseUrl}${options.path}';
final requestQuery = '${options.queryParameters}';
final header = options.headers;
logger.i('${options.method} request => $requestPath\nheader ===> $header\nquery ===> $requestQuery\nbody ==> $requestBody'); // Info log
return super.onRequest(options, handler);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
final options = response.requestOptions;
final requestPath = '${options.baseUrl}${options.path}';
logger.d('HTTPCode: ${response.statusCode}, URL: ${requestPath}\nData: ===> \n${response.data}'); // Debug log
return super.onResponse(response, handler);
}
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment