Init core module
This commit is contained in:
+124
@@ -0,0 +1,124 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.lock
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# Visual Studio Code related
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
.vscode/
|
||||
|
||||
# Flutter repo-specific
|
||||
/bin/cache/
|
||||
/bin/mingit/
|
||||
/dev/benchmarks/mega_gallery/
|
||||
/dev/bots/.recipe_deps
|
||||
/dev/bots/android_tools/
|
||||
/dev/devicelab/ABresults*.json
|
||||
/dev/docs/doc/
|
||||
/dev/docs/flutter.docs.zip
|
||||
/dev/docs/lib/
|
||||
/dev/docs/pubspec.yaml
|
||||
/dev/integration_tests/**/xcuserdata
|
||||
/dev/integration_tests/**/Pods
|
||||
/packages/flutter/coverage/
|
||||
version
|
||||
analysis_benchmark.json
|
||||
|
||||
# packages file containing multi-root paths
|
||||
.packages.generated
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
**/generated_plugin_registrant.dart
|
||||
.packages
|
||||
.pub-cache/
|
||||
.pub/
|
||||
build/
|
||||
flutter_*.png
|
||||
linked_*.ds
|
||||
unlinked.ds
|
||||
unlinked_spec.ds
|
||||
|
||||
# Android related
|
||||
**/android/.gradle
|
||||
**/android/captures/
|
||||
**/android/local.properties
|
||||
**/android/**/GeneratedPluginRegistrant.java
|
||||
**/android/key.properties
|
||||
*.jks
|
||||
|
||||
# iOS/XCode related
|
||||
**/ios/**/*.mode1v3
|
||||
**/ios/**/*.mode2v3
|
||||
**/ios/**/*.moved-aside
|
||||
**/ios/**/*.pbxuser
|
||||
**/ios/**/*.perspectivev3
|
||||
**/ios/**/*sync/
|
||||
**/ios/**/.sconsign.dblite
|
||||
**/ios/**/.tags*
|
||||
**/ios/**/.vagrant/
|
||||
**/ios/**/DerivedData/
|
||||
**/ios/**/Icon?
|
||||
**/ios/**/Pods/
|
||||
**/ios/**/.symlinks/
|
||||
**/ios/**/profile
|
||||
**/ios/**/xcuserdata
|
||||
**/ios/.generated/
|
||||
**/ios/Flutter/.last_build_id
|
||||
**/ios/Flutter/App.framework
|
||||
**/ios/Flutter/Flutter.framework
|
||||
**/ios/Flutter/Flutter.podspec
|
||||
**/ios/Flutter/Generated.xcconfig
|
||||
**/ios/Flutter/app.flx
|
||||
**/ios/Flutter/app.zip
|
||||
**/ios/Flutter/flutter_assets/
|
||||
**/ios/Flutter/flutter_export_environment.sh
|
||||
**/ios/ServiceDefinitions.json
|
||||
**/ios/Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# macOS
|
||||
**/macos/Flutter/GeneratedPluginRegistrant.swift
|
||||
**/macos/Flutter/Flutter-Debug.xcconfig
|
||||
**/macos/Flutter/Flutter-Release.xcconfig
|
||||
**/macos/Flutter/Flutter-Profile.xcconfig
|
||||
|
||||
# Coverage
|
||||
coverage/
|
||||
|
||||
# Symbols
|
||||
app.*.symbols
|
||||
|
||||
# Exceptions to above rules.
|
||||
!**/ios/**/default.mode1v3
|
||||
!**/ios/**/default.mode2v3
|
||||
!**/ios/**/default.pbxuser
|
||||
!**/ios/**/default.perspectivev3
|
||||
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
|
||||
!/dev/ci/**/Gemfile.lock
|
||||
|
||||
#generated file
|
||||
*.g.dart
|
||||
messages_all.dart
|
||||
messages_en.dart
|
||||
messages_fr.dart
|
||||
messages_messages.dart
|
||||
messages_ru.dart
|
||||
messages_vi.dart
|
||||
@@ -0,0 +1,10 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: d79295af24c3ed621c33713ecda14ad196fd9c31
|
||||
channel: stable
|
||||
|
||||
project_type: module
|
||||
@@ -0,0 +1,3 @@
|
||||
# core
|
||||
|
||||
Core Module
|
||||
@@ -0,0 +1,40 @@
|
||||
library core;
|
||||
|
||||
// Extensions
|
||||
export 'presentation/extensions/color_extension.dart';
|
||||
export 'presentation/extensions/url_extension.dart';
|
||||
|
||||
// Utils
|
||||
export 'presentation/utils/theme_utils.dart';
|
||||
export 'presentation/utils/responsive_utils.dart';
|
||||
export 'presentation/utils/keyboard_utils.dart';
|
||||
export 'presentation/utils/style_utils.dart';
|
||||
export 'presentation/extensions/list_extensions.dart';
|
||||
|
||||
// Views
|
||||
export 'presentation/views/text/slogan_builder.dart';
|
||||
export 'presentation/views/text/text_field_builder.dart';
|
||||
export 'presentation/views/text/input_decoration_builder.dart';
|
||||
export 'presentation/views/text/text_builder.dart';
|
||||
export 'presentation/views/responsive/responsive_widget.dart';
|
||||
export 'presentation/views/list/tree_view.dart';
|
||||
|
||||
// Resources
|
||||
export 'presentation/resources/assets_paths.dart';
|
||||
export 'presentation/resources/image_paths.dart';
|
||||
|
||||
// Constants
|
||||
export 'presentation/constants/constants_ui.dart';
|
||||
export 'data/constants/constant.dart';
|
||||
|
||||
// Network
|
||||
export 'data/network/config/authorization_interceptors.dart';
|
||||
export 'data/network/config/dynamic_url_interceptors.dart';
|
||||
export 'data/network/config/endpoint.dart';
|
||||
export 'data/network/config/service_path.dart';
|
||||
export 'data/network/dio_client.dart';
|
||||
|
||||
// State
|
||||
export 'presentation/state/success.dart';
|
||||
export 'presentation/state/failure.dart';
|
||||
export 'presentation/state/app_state.dart';
|
||||
@@ -0,0 +1,7 @@
|
||||
class Constant {
|
||||
static const userId = '_id';
|
||||
static const firstName = 'firstname';
|
||||
static const lastName = 'lastname';
|
||||
static const acceptHeaderDefault = 'application/json';
|
||||
static const contentTypeHeaderDefault = 'application/json';
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
class AuthorizationInterceptors extends InterceptorsWrapper {
|
||||
String? _authorization;
|
||||
|
||||
void changeAuthorization(String? userName, String? password) {
|
||||
_authorization = base64Encode(utf8.encode('$userName:$password'));
|
||||
}
|
||||
|
||||
@override
|
||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||
if (_authorization != null) {
|
||||
options.headers['Authorization'] = 'Basic $_authorization';
|
||||
}
|
||||
super.onRequest(options, handler);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
class DynamicUrlInterceptors extends InterceptorsWrapper {
|
||||
String? _baseUrl;
|
||||
|
||||
void changeBaseUrl(String? url) {
|
||||
_baseUrl = url;
|
||||
}
|
||||
|
||||
@override
|
||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
|
||||
if (_baseUrl != null) {
|
||||
options.baseUrl = _baseUrl!;
|
||||
}
|
||||
super.onRequest(options, handler);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import 'package:core/data/network/config/service_path.dart';
|
||||
|
||||
class Endpoint {
|
||||
static final ServicePath authentication = ServicePath('/api/login');
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
class ServicePath {
|
||||
final String path;
|
||||
|
||||
ServicePath(this.path);
|
||||
}
|
||||
|
||||
extension ServicePathExtension on ServicePath {
|
||||
String generateEndpointPath() {
|
||||
return '$path';
|
||||
}
|
||||
|
||||
String generateAuthenticationUrl(Uri? baseUrl) {
|
||||
if (baseUrl == null) {
|
||||
return generateEndpointPath();
|
||||
} else {
|
||||
return baseUrl.origin + generateEndpointPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
class DioClient {
|
||||
final Dio _dio;
|
||||
|
||||
DioClient(this._dio);
|
||||
|
||||
Map<String, dynamic> getHeaders() => Map.from(_dio.options.headers);
|
||||
|
||||
Future<dynamic> get(
|
||||
String path, {
|
||||
Map<String, dynamic>? queryParameters,
|
||||
Options? options,
|
||||
CancelToken? cancelToken,
|
||||
ProgressCallback? onReceiveProgress,
|
||||
}) async {
|
||||
return await _dio.get(
|
||||
path,
|
||||
queryParameters: queryParameters,
|
||||
options: options,
|
||||
cancelToken: cancelToken,
|
||||
onReceiveProgress: onReceiveProgress)
|
||||
.then((value) => value.data)
|
||||
.catchError((error) => throw error);
|
||||
}
|
||||
|
||||
Future<dynamic> post(
|
||||
String path, {
|
||||
data,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
Options? options,
|
||||
CancelToken? cancelToken,
|
||||
ProgressCallback? onSendProgress,
|
||||
ProgressCallback? onReceiveProgress,
|
||||
}) async {
|
||||
return await _dio.post(path,
|
||||
data: data,
|
||||
queryParameters: queryParameters,
|
||||
options: options,
|
||||
cancelToken: cancelToken,
|
||||
onSendProgress: onSendProgress,
|
||||
onReceiveProgress: onReceiveProgress)
|
||||
.then((value) => value.data)
|
||||
.catchError((error) => throw error);
|
||||
}
|
||||
|
||||
Future<dynamic> delete(
|
||||
String path, {
|
||||
data,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
Options? options,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
return await _dio.delete(
|
||||
path,
|
||||
data: data,
|
||||
queryParameters: queryParameters,
|
||||
options: options,
|
||||
cancelToken: cancelToken)
|
||||
.then((value) => value.data)
|
||||
.catchError((error) => throw(error));
|
||||
}
|
||||
|
||||
Future<dynamic> put(
|
||||
String path, {
|
||||
data,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
Options? options,
|
||||
CancelToken? cancelToken,
|
||||
ProgressCallback? onSendProgress,
|
||||
ProgressCallback? onReceiveProgress
|
||||
}) async {
|
||||
return await _dio.put(
|
||||
path,
|
||||
data: data,
|
||||
queryParameters: queryParameters,
|
||||
options: options,
|
||||
cancelToken: cancelToken,
|
||||
onSendProgress: onSendProgress,
|
||||
onReceiveProgress: onReceiveProgress)
|
||||
.then((value) => value.data)
|
||||
.catchError((error) => throw(error));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
class ConstantsUI {
|
||||
static const fontApp = 'CircularStd';
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import 'dart:ui' show Color;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
extension AppColor on Color {
|
||||
static const primaryColor = Color(0xFF837DFF);
|
||||
static const primaryDarkColor = Color(0xFF1C1C1C);
|
||||
static const primaryLightColor = Color(0xFFFFFFFF);
|
||||
static const baseTextColor = Color(0xFF7E869B);
|
||||
static const textFieldTextColor = Color(0xFF7E869B);
|
||||
static const textFieldLabelColor = Color(0xFF7E869B);
|
||||
static const textFieldHintColor = Color(0xFF757575);
|
||||
static const textFieldBorderColor = Color(0xfff2f1fd);
|
||||
static const textFieldFocusedBorderColor = Color(0xFF837DFF);
|
||||
static const textFieldErrorBorderColor = Color(0xffFF5858);
|
||||
static const buttonColor = Color(0xFF837DFF);
|
||||
static const appColor = Color(0xFF3840F7);
|
||||
static const nameUserColor = Color(0xFF182952);
|
||||
static const emailUserColor = Color(0xFF7E869B);
|
||||
static const userInformationBackgroundColor = Color(0xFFF5F5F7);
|
||||
static const searchBorderColor = Color(0xFFEAEAEA);
|
||||
static const searchHintTextColor = Color(0xFF7E869B);
|
||||
static const mailboxSelectedBackgroundColor = Color(0xFFE6E5FF);
|
||||
static const mailboxBackgroundColor = Color(0xFFFFFFFF);
|
||||
static const mailboxSelectedTextColor = Color(0xFF3840F7);
|
||||
static const mailboxTextColor = Color(0xFF182952);
|
||||
static const mailboxSelectedTextNumberColor = Color(0xFF182952);
|
||||
static const mailboxTextNumberColor = Color(0xFF837DFF);
|
||||
static const mailboxSelectedIconColor = Color(0xFF3840F7);
|
||||
static const mailboxIconColor = Color(0xFF7E869B);
|
||||
static const storageBackgroundColor = Color(0xFFF5F5F7);
|
||||
static const storageTitleColor = Color(0xFF7E869B);
|
||||
static const storageMaxSizeColor = Color(0xFF101D43);
|
||||
static const storageUseSizeColor = Color(0xFF2D0CFF);
|
||||
static const myFolderTitleColor = Color(0xFF7E869B);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:built_collection/built_collection.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
extension ListExtensions<T> on List<T> {
|
||||
Tuple2<List<T>, List<T>> split(bool test(T element)) {
|
||||
final validBuilder = ListBuilder<T>();
|
||||
final invalidBuilder = ListBuilder<T>();
|
||||
forEach((element) {
|
||||
if (test(element)) {
|
||||
validBuilder.add(element);
|
||||
} else {
|
||||
invalidBuilder.add(element);
|
||||
}
|
||||
});
|
||||
return Tuple2(
|
||||
validBuilder.build().toList(),
|
||||
validBuilder.build().toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
extension URLExtension on String {
|
||||
static final String prefixUrlHttps = 'https://';
|
||||
static final String prefixUrlHttp = 'http://';
|
||||
|
||||
String formatURLValid() {
|
||||
if (startsWith(prefixUrlHttps)) {
|
||||
return this;
|
||||
} else if (startsWith(prefixUrlHttp)) {
|
||||
return kReleaseMode ? replaceAll(prefixUrlHttp, prefixUrlHttps) : this;
|
||||
} else {
|
||||
return '$prefixUrlHttps${this}';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
class AssetsPaths {
|
||||
static const images = 'assets/images/';
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:core/presentation/resources/assets_paths.dart';
|
||||
|
||||
class ImagePaths {
|
||||
String get icTMailLogo => _getImagePath('tmail_logo.svg');
|
||||
String get icCloseMailbox => _getImagePath('ic_close.svg');
|
||||
String get icSearch => _getImagePath('ic_search.svg');
|
||||
String get icNextArrow => _getImagePath('ic_next_arrow.svg');
|
||||
String get icMailboxInbox => _getImagePath('ic_mailbox_inbox.svg');
|
||||
String get icMailboxTrash => _getImagePath('ic_mailbox_trash.svg');
|
||||
String get icMailboxAllMail => _getImagePath('ic_mailbox_allmail.svg');
|
||||
String get icMailboxDrafts => _getImagePath('ic_mailbox_draft.svg');
|
||||
String get icMailboxSent => _getImagePath('ic_mailbox_sent.svg');
|
||||
String get icMailboxSpam => _getImagePath('ic_mailbox_spam.svg');
|
||||
String get icMailboxTemplate => _getImagePath('ic_mailbox_template.svg');
|
||||
String get icMailboxFolder => _getImagePath('ic_mailbox_folder.svg');
|
||||
String get icMailboxNewFolder => _getImagePath('ic_mailbox_new_folder.svg');
|
||||
String get icFolderArrow => _getImagePath('ic_folder_arrow.svg');
|
||||
String get icExpandFolder => _getImagePath('ic_expand_folder.svg');
|
||||
|
||||
String _getImagePath(String imageName) {
|
||||
return AssetsPaths.images + imageName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import 'package:core/core.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
@immutable
|
||||
abstract class AppState with EquatableMixin {
|
||||
final Either<Failure, Success> viewState;
|
||||
|
||||
AppState(this.viewState);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [viewState];
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class Failure extends Equatable {}
|
||||
|
||||
abstract class FeatureFailure extends Failure {}
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class Success with EquatableMixin {}
|
||||
|
||||
abstract class ViewState extends Success {}
|
||||
|
||||
class UIState extends ViewState {
|
||||
static final idle = UIState();
|
||||
static final loading = UIState();
|
||||
|
||||
UIState() : super();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class KeyboardUtils {
|
||||
void hideKeyboard(BuildContext context) {
|
||||
FocusScopeNode currentFocus = FocusScope.of(context);
|
||||
if (!currentFocus.hasPrimaryFocus) {
|
||||
currentFocus.unfocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class ResponsiveUtils {
|
||||
|
||||
static const int _minLargeWidth = 950;
|
||||
static const int _minMediumWidth = 600;
|
||||
|
||||
static const double _loginTextFieldWidthSmallScreen = 280.0;
|
||||
static const double _loginTextFieldWidthLargeScreen = 320.0;
|
||||
static const double _loginButtonWidth = 240.0;
|
||||
|
||||
double getSizeWidthScreen(BuildContext context) {
|
||||
return MediaQuery.of(context).size.width;
|
||||
}
|
||||
|
||||
double getSizeHeightScreen(BuildContext context) {
|
||||
return MediaQuery.of(context).size.height;
|
||||
}
|
||||
|
||||
bool isLargeScreen(BuildContext context) {
|
||||
return getSizeWidthScreen(context) >= _minLargeWidth;
|
||||
}
|
||||
|
||||
bool isSmallScreen(BuildContext context) {
|
||||
return getSizeWidthScreen(context) < _minMediumWidth;
|
||||
}
|
||||
|
||||
bool isMediumScreen(BuildContext context) {
|
||||
return getSizeWidthScreen(context) >= _minMediumWidth && getSizeWidthScreen(context) < _minLargeWidth;
|
||||
}
|
||||
|
||||
double getWidthLoginTextField(BuildContext context) => isSmallScreen(context)
|
||||
? _loginTextFieldWidthSmallScreen
|
||||
: _loginTextFieldWidthLargeScreen;
|
||||
|
||||
double getWidthLoginButton() => _loginButtonWidth;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CommonTextStyle {
|
||||
static final textStyleNormal = TextStyle(
|
||||
color: AppColor.primaryColor,
|
||||
fontSize: 14,
|
||||
fontStyle: FontStyle.normal,
|
||||
fontWeight: FontWeight.normal,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import 'package:core/presentation/constants/constants_ui.dart';
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
ThemeData appTheme() {
|
||||
return ThemeData(
|
||||
scaffoldBackgroundColor: Colors.white,
|
||||
fontFamily: ConstantsUI.fontApp,
|
||||
appBarTheme: appBarTheme(),
|
||||
textTheme: textTheme(),
|
||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||
);
|
||||
}
|
||||
|
||||
InputDecorationTheme inputDecorationTheme() {
|
||||
OutlineInputBorder outlineInputBorder = OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(28),
|
||||
borderSide: BorderSide(color: AppColor.baseTextColor),
|
||||
gapPadding: 10,
|
||||
);
|
||||
return InputDecorationTheme(
|
||||
floatingLabelBehavior: FloatingLabelBehavior.always,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 42, vertical: 20),
|
||||
enabledBorder: outlineInputBorder,
|
||||
focusedBorder: outlineInputBorder,
|
||||
border: outlineInputBorder,
|
||||
);
|
||||
}
|
||||
|
||||
TextTheme textTheme() {
|
||||
return TextTheme(
|
||||
bodyText1: TextStyle(color: AppColor.baseTextColor),
|
||||
bodyText2: TextStyle(color: AppColor.baseTextColor),
|
||||
);
|
||||
}
|
||||
|
||||
AppBarTheme appBarTheme() {
|
||||
return AppBarTheme(
|
||||
color: Colors.white,
|
||||
elevation: 0,
|
||||
brightness: Brightness.light,
|
||||
iconTheme: IconThemeData(color: Colors.black),
|
||||
textTheme: TextTheme(
|
||||
headline6: TextStyle(color: Color(0XFF8B8B8B), fontSize: 18),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
|
||||
class TreeView extends InheritedWidget {
|
||||
final List<Widget> children;
|
||||
final bool startExpanded;
|
||||
|
||||
TreeView({
|
||||
Key? key,
|
||||
required List<Widget> children,
|
||||
bool startExpanded = false,
|
||||
}) : this.children = children, this.startExpanded = startExpanded, super (
|
||||
key: key,
|
||||
child: _TreeViewData(
|
||||
children: children,
|
||||
),
|
||||
);
|
||||
|
||||
static TreeView of(BuildContext context) {
|
||||
return context.dependOnInheritedWidgetOfExactType<TreeView>()!;
|
||||
}
|
||||
|
||||
@override
|
||||
bool updateShouldNotify(TreeView oldWidget) {
|
||||
if (oldWidget.children == this.children &&
|
||||
oldWidget.startExpanded == this.startExpanded) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class _TreeViewData extends StatelessWidget {
|
||||
final List<Widget> children;
|
||||
|
||||
const _TreeViewData({
|
||||
required this.children,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
primary: false,
|
||||
itemCount: children.length,
|
||||
itemBuilder: (context, index) {
|
||||
return children.elementAt(index);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TreeViewChild extends StatefulWidget {
|
||||
final bool? startExpanded;
|
||||
final Widget parent;
|
||||
final List<Widget> children;
|
||||
final VoidCallback? onTap;
|
||||
|
||||
TreeViewChild({
|
||||
required this.parent,
|
||||
required this.children,
|
||||
this.startExpanded,
|
||||
this.onTap,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
TreeViewChildState createState() => TreeViewChildState();
|
||||
|
||||
TreeViewChild copyWith(
|
||||
TreeViewChild source, {
|
||||
bool? startExpanded,
|
||||
Widget? parent,
|
||||
List<Widget>? children,
|
||||
VoidCallback? onTap,
|
||||
}) {
|
||||
return TreeViewChild(
|
||||
parent: parent ?? source.parent,
|
||||
children: children ?? source.children,
|
||||
startExpanded: startExpanded ?? source.startExpanded,
|
||||
onTap: onTap ?? source.onTap,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TreeViewChildState extends State<TreeViewChild> {
|
||||
bool? isExpanded;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
isExpanded = widget.startExpanded;
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
isExpanded = widget.startExpanded ?? TreeView.of(context).startExpanded;
|
||||
super.didChangeDependencies();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
GestureDetector(
|
||||
child: widget.parent,
|
||||
onTap: () {
|
||||
if (widget.onTap != null) {
|
||||
widget.onTap!();
|
||||
}
|
||||
toggleExpanded();
|
||||
},
|
||||
),
|
||||
AnimatedContainer(
|
||||
duration: Duration(milliseconds: 400),
|
||||
child: isExpanded!
|
||||
? Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: widget.children,
|
||||
)
|
||||
: Offstage(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void toggleExpanded() {
|
||||
setState(() {
|
||||
this.isExpanded = !this.isExpanded!;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import 'package:core/presentation/utils/responsive_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ResponsiveWidget extends StatelessWidget {
|
||||
final Widget? largeScreen;
|
||||
final Widget mediumScreen;
|
||||
final Widget? smallScreen;
|
||||
|
||||
final ResponsiveUtils responsiveUtils;
|
||||
|
||||
const ResponsiveWidget({
|
||||
Key? key,
|
||||
this.largeScreen,
|
||||
required this.mediumScreen,
|
||||
this.smallScreen,
|
||||
required this.responsiveUtils,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(builder: (context, constraints) {
|
||||
if (responsiveUtils.isLargeScreen(context)) {
|
||||
return largeScreen ?? mediumScreen;
|
||||
} else if (responsiveUtils.isMediumScreen(context)) {
|
||||
return mediumScreen;
|
||||
} else {
|
||||
return smallScreen ?? mediumScreen;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
abstract class InputDecorationBuilder {
|
||||
String? prefixText;
|
||||
String? labelText;
|
||||
TextStyle? labelStyle;
|
||||
String? hintText;
|
||||
TextStyle? hintStyle;
|
||||
EdgeInsets? contentPadding;
|
||||
OutlineInputBorder? enabledBorder;
|
||||
|
||||
InputDecorationBuilder setPrefixText(String newPrefixText) {
|
||||
prefixText = newPrefixText;
|
||||
return this;
|
||||
}
|
||||
|
||||
InputDecorationBuilder setLabelText(String newLabelText) {
|
||||
labelText = newLabelText;
|
||||
return this;
|
||||
}
|
||||
|
||||
InputDecorationBuilder setLabelStyle(TextStyle newLabelStyle) {
|
||||
labelStyle = newLabelStyle;
|
||||
return this;
|
||||
}
|
||||
|
||||
InputDecorationBuilder setHintText(String newHintText) {
|
||||
hintText = newHintText;
|
||||
return this;
|
||||
}
|
||||
|
||||
InputDecorationBuilder setHintStyle(TextStyle newHintStyle) {
|
||||
hintStyle = newHintStyle;
|
||||
return this;
|
||||
}
|
||||
|
||||
InputDecorationBuilder setContentPadding(EdgeInsets newContentPadding) {
|
||||
contentPadding = newContentPadding;
|
||||
return this;
|
||||
}
|
||||
|
||||
InputDecorationBuilder setEnabledBorder(OutlineInputBorder newEnabledBorder) {
|
||||
enabledBorder = newEnabledBorder;
|
||||
return this;
|
||||
}
|
||||
|
||||
InputDecoration build() {
|
||||
return InputDecoration(
|
||||
prefixText: prefixText,
|
||||
labelText: labelText,
|
||||
labelStyle: labelStyle,
|
||||
hintText: hintText,
|
||||
hintStyle: hintStyle,
|
||||
contentPadding: contentPadding,
|
||||
enabledBorder: enabledBorder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
/// A builder which builds a reusable slogan widget.
|
||||
/// This contains the logo and the slogan text.
|
||||
/// The elements are arranged in a column.
|
||||
class SloganBuilder {
|
||||
Key? _key;
|
||||
String? _text;
|
||||
TextStyle? _textStyle;
|
||||
TextAlign? _textAlign;
|
||||
String? _logo;
|
||||
|
||||
SloganBuilder key(Key key) {
|
||||
_key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
SloganBuilder setSloganText(String text) {
|
||||
_text = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
SloganBuilder setSloganTextStyle(TextStyle textStyle) {
|
||||
_textStyle = textStyle;
|
||||
return this;
|
||||
}
|
||||
|
||||
SloganBuilder setSloganTextAlign(TextAlign textAlign) {
|
||||
_textAlign = textAlign;
|
||||
return this;
|
||||
}
|
||||
|
||||
SloganBuilder setLogo(String logo) {
|
||||
_logo = logo;
|
||||
return this;
|
||||
}
|
||||
|
||||
Widget build() {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
_logo != null ? SvgPicture.asset(_logo!, width: 150, height: 150) : SizedBox.shrink(),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 16, left: 16, right: 16),
|
||||
child: Text(_text ?? '', key: _key, style: _textStyle, textAlign: _textAlign),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import 'package:core/presentation/utils/style_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class TextBuilder {
|
||||
String? _text;
|
||||
TextStyle? _textStyle;
|
||||
TextAlign? _textAlign;
|
||||
Key? _key;
|
||||
|
||||
TextBuilder key(Key key) {
|
||||
_key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
TextBuilder text(String text) {
|
||||
_text = text;
|
||||
return this;
|
||||
}
|
||||
|
||||
TextBuilder textStyle(TextStyle textStyle) {
|
||||
_textStyle = textStyle;
|
||||
return this;
|
||||
}
|
||||
|
||||
TextBuilder textAlign(TextAlign textAlign) {
|
||||
_textAlign = textAlign;
|
||||
return this;
|
||||
}
|
||||
|
||||
Text build() {
|
||||
return Text(_text ?? '', key: _key ?? Key('TextBuilder'), style: _textStyle ?? CommonTextStyle.textStyleNormal, textAlign: _textAlign ?? TextAlign.center);
|
||||
}
|
||||
}
|
||||
|
||||
class CenterTextBuilder extends TextBuilder {
|
||||
@override
|
||||
Text build() {
|
||||
return Text(_text ?? '', key: _key ?? Key('TextBuilder'), style: _textStyle, textAlign: TextAlign.center);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class TextFieldBuilder {
|
||||
Key? _key;
|
||||
ValueChanged<String>? _onTextChange;
|
||||
TextStyle? _textStyle;
|
||||
TextInputAction? _textInputAction;
|
||||
InputDecoration? _inputDecoration;
|
||||
bool? _obscureText;
|
||||
|
||||
TextFieldBuilder key(Key key) {
|
||||
_key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
TextFieldBuilder onChange(ValueChanged<String> onChange) {
|
||||
_onTextChange = onChange;
|
||||
return this;
|
||||
}
|
||||
|
||||
TextFieldBuilder textStyle(TextStyle style) {
|
||||
_textStyle = style;
|
||||
return this;
|
||||
}
|
||||
|
||||
TextFieldBuilder textInputAction(TextInputAction inputAction) {
|
||||
_textInputAction = inputAction;
|
||||
return this;
|
||||
}
|
||||
|
||||
TextFieldBuilder textDecoration(InputDecoration inputDecoration) {
|
||||
_inputDecoration = inputDecoration;
|
||||
return this;
|
||||
}
|
||||
|
||||
TextFieldBuilder obscureText(bool obscureText) {
|
||||
_obscureText = obscureText;
|
||||
return this;
|
||||
}
|
||||
|
||||
TextField build() {
|
||||
return TextField(
|
||||
key: _key ?? Key('TextFieldBuilder'),
|
||||
onChanged: _onTextChange,
|
||||
cursorColor: AppColor.primaryColor,
|
||||
textInputAction: _textInputAction,
|
||||
decoration: _inputDecoration,
|
||||
style: _textStyle ?? TextStyle(color: AppColor.textFieldTextColor),
|
||||
obscureText: _obscureText ?? false,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
name: core
|
||||
description: Core Module
|
||||
|
||||
# The following defines the version and build number for your application.
|
||||
# A version number is three numbers separated by dots, like 1.2.43
|
||||
# followed by an optional build number separated by a +.
|
||||
# Both the version and the builder number may be overridden in flutter
|
||||
# build by specifying --build-name and --build-number, respectively.
|
||||
# In Android, build-name is used as versionName while build-number used as versionCode.
|
||||
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
#
|
||||
# This version is used _only_ for the Runner app, which is used if you just do
|
||||
# a `flutter run` or a `flutter make-host-app-editable`. It has no impact
|
||||
# on any other native host app that you embed your Flutter project into.
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ">=2.12.0 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
cupertino_icons: ^1.0.2
|
||||
|
||||
# flutter_svg
|
||||
flutter_svg: 0.22.0
|
||||
|
||||
# Http client
|
||||
dio: 4.0.0
|
||||
|
||||
# dartz
|
||||
dartz: 0.10.0-nullsafety.2
|
||||
|
||||
# equatable
|
||||
equatable: 2.0.3
|
||||
|
||||
built_collection: 5.1.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
||||
build_runner: 2.0.5
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
flutter:
|
||||
# The following line ensures that the Material Icons font is
|
||||
# included with your application, so that you can use the icons in
|
||||
# the material Icons class.
|
||||
uses-material-design: true
|
||||
|
||||
# To add Flutter specific assets to your application, add an assets section,
|
||||
# like this:
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
||||
|
||||
# For details regarding adding assets from package dependencies, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
|
||||
# To add Flutter specific custom fonts to your application, add a fonts
|
||||
# section here, in this "flutter" section. Each entry in this list should
|
||||
# have a "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
# - asset: fonts/TrajanPro.ttf
|
||||
# - asset: fonts/TrajanPro_Bold.ttf
|
||||
# weight: 700
|
||||
#
|
||||
# For details regarding fonts from package dependencies,
|
||||
# see https://flutter.dev/custom-fonts/#from-packages
|
||||
|
||||
|
||||
# This section identifies your Flutter project as a module meant for
|
||||
# embedding in a native host app. These identifiers should _not_ ordinarily
|
||||
# be changed after generation - they are used to ensure that the tooling can
|
||||
# maintain consistency when adding or modifying assets and plugins.
|
||||
# They also do not have any bearing on your native host application's
|
||||
# identifiers, which may be completely independent or the same as these.
|
||||
Reference in New Issue
Block a user