Init core module
This commit is contained in:
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user