TF-3260 Load & Display App Grid Linagora Ecosystem
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -96,6 +96,7 @@ export 'presentation/views/container/tmail_container_widget.dart';
|
||||
export 'presentation/views/clipper/side_arrow_clipper.dart';
|
||||
export 'presentation/views/avatar/gradient_circle_avatar_icon.dart';
|
||||
export 'presentation/views/loading/cupertino_loading_widget.dart';
|
||||
export 'presentation/views/image/image_loader_mixin.dart';
|
||||
|
||||
// Resources
|
||||
export 'presentation/resources/assets_paths.dart';
|
||||
|
||||
@@ -14,4 +14,6 @@ class Constant {
|
||||
static const attachmentScheme = 'attachment';
|
||||
static const emlPreviewerScheme = 'eml-previewer';
|
||||
static const htmlExtension = '.html';
|
||||
static const slashCharacter = '/';
|
||||
static const andCharacter = '&';
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
mixin ImageLoaderMixin {
|
||||
|
||||
Widget buildImage({
|
||||
required String imagePath,
|
||||
double? imageSize
|
||||
}) {
|
||||
if (isImageNetworkLink(imagePath) && isImageSVG(imagePath)) {
|
||||
return SvgPicture.network(
|
||||
imagePath,
|
||||
width: imageSize ?? 150,
|
||||
height: imageSize ?? 150,
|
||||
fit: BoxFit.fill,
|
||||
placeholderBuilder: (_) {
|
||||
return const CupertinoActivityIndicator();
|
||||
},
|
||||
);
|
||||
} else if (isImageNetworkLink(imagePath)) {
|
||||
return Image.network(
|
||||
imagePath,
|
||||
fit: BoxFit.fill,
|
||||
width: imageSize ?? 150,
|
||||
height: imageSize ?? 150,
|
||||
loadingBuilder: (_, child, loadingProgress) {
|
||||
if (loadingProgress != null &&
|
||||
loadingProgress.cumulativeBytesLoaded != loadingProgress.expectedTotalBytes) {
|
||||
return const Center(
|
||||
child: CupertinoActivityIndicator(),
|
||||
);
|
||||
}
|
||||
return child;
|
||||
},
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
logError('ImageLoaderMixin::buildImage:Exception = $error');
|
||||
return Container(
|
||||
width: imageSize ?? 150,
|
||||
height: imageSize ?? 150,
|
||||
alignment: Alignment.center,
|
||||
child: const Icon(Icons.error_outline),
|
||||
);
|
||||
},
|
||||
);
|
||||
} else if (isImageSVG(imagePath)) {
|
||||
return SvgPicture.asset(
|
||||
imagePath,
|
||||
width: imageSize ?? 150,
|
||||
height: imageSize ?? 150,
|
||||
);
|
||||
} else {
|
||||
return Image.asset(
|
||||
imagePath,
|
||||
fit: BoxFit.fill,
|
||||
width: imageSize ?? 150,
|
||||
height: imageSize ?? 150,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool isImageNetworkLink(String imagePath) {
|
||||
return imagePath.startsWith('http') == true ||
|
||||
imagePath.startsWith('https') == true;
|
||||
}
|
||||
|
||||
bool isImageSVG(String imagePath) => imagePath.endsWith('svg') == true;
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/presentation/utils/style_utils.dart';
|
||||
import 'package:core/presentation/views/image/image_loader_mixin.dart';
|
||||
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.
|
||||
@@ -9,14 +7,13 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
typedef OnTapCallback = void Function();
|
||||
|
||||
class SloganBuilder extends StatelessWidget {
|
||||
class SloganBuilder extends StatelessWidget with ImageLoaderMixin {
|
||||
|
||||
final bool arrangedByHorizontal;
|
||||
final String? text;
|
||||
final TextStyle? textStyle;
|
||||
final TextAlign? textAlign;
|
||||
final String? logo;
|
||||
final Uri? publicLogoUri;
|
||||
final double? sizeLogo;
|
||||
final OnTapCallback? onTapCallback;
|
||||
final EdgeInsetsGeometry? paddingText;
|
||||
@@ -33,7 +30,6 @@ class SloganBuilder extends StatelessWidget {
|
||||
this.textStyle,
|
||||
this.textAlign,
|
||||
this.logo,
|
||||
this.publicLogoUri,
|
||||
this.sizeLogo,
|
||||
this.onTapCallback,
|
||||
this.padding,
|
||||
@@ -45,82 +41,64 @@ class SloganBuilder extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!arrangedByHorizontal) {
|
||||
return InkWell(
|
||||
onTap: onTapCallback,
|
||||
hoverColor: hoverColor,
|
||||
borderRadius: BorderRadius.all(Radius.circular(hoverRadius ?? 8)),
|
||||
child: Padding(
|
||||
padding: padding ?? EdgeInsets.zero,
|
||||
child: Column(children: [
|
||||
_logoApp(),
|
||||
Padding(
|
||||
padding: paddingText ?? const EdgeInsetsDirectional.only(top: 16, start: 16, end: 16),
|
||||
child: Text(
|
||||
text ?? '',
|
||||
style: textStyle,
|
||||
textAlign: textAlign,
|
||||
overflow: enableOverflow ? CommonTextStyle.defaultTextOverFlow : null,
|
||||
softWrap: enableOverflow ? CommonTextStyle.defaultSoftWrap : null,
|
||||
maxLines: enableOverflow ? 1 : null,
|
||||
return Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
onTap: onTapCallback,
|
||||
hoverColor: hoverColor,
|
||||
borderRadius: BorderRadius.all(Radius.circular(hoverRadius ?? 8)),
|
||||
child: Padding(
|
||||
padding: padding ?? EdgeInsets.zero,
|
||||
child: Column(children: [
|
||||
if (logo != null)
|
||||
buildImage(
|
||||
imagePath: logo!,
|
||||
imageSize: sizeLogo,
|
||||
),
|
||||
Padding(
|
||||
padding: paddingText ?? const EdgeInsetsDirectional.only(top: 16, start: 16, end: 16),
|
||||
child: Text(
|
||||
text ?? '',
|
||||
style: textStyle,
|
||||
textAlign: textAlign,
|
||||
overflow: enableOverflow ? TextOverflow.ellipsis : null,
|
||||
maxLines: enableOverflow ? 1 : null,
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
]),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return InkWell(
|
||||
onTap: onTapCallback,
|
||||
hoverColor: hoverColor,
|
||||
radius: hoverRadius ?? 8,
|
||||
borderRadius: BorderRadius.all(Radius.circular(hoverRadius ?? 8)),
|
||||
child: Padding(
|
||||
padding: padding ?? EdgeInsets.zero,
|
||||
child: Row(children: [
|
||||
_logoApp(),
|
||||
Padding(
|
||||
padding: paddingText ?? const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Text(
|
||||
text ?? '',
|
||||
style: textStyle,
|
||||
textAlign: textAlign,
|
||||
overflow: enableOverflow ? CommonTextStyle.defaultTextOverFlow : null,
|
||||
softWrap: enableOverflow ? CommonTextStyle.defaultSoftWrap : null,
|
||||
maxLines: enableOverflow ? 1 : null,
|
||||
return Material(
|
||||
type: MaterialType.transparency,
|
||||
child: InkWell(
|
||||
onTap: onTapCallback,
|
||||
hoverColor: hoverColor,
|
||||
radius: hoverRadius ?? 8,
|
||||
borderRadius: BorderRadius.all(Radius.circular(hoverRadius ?? 8)),
|
||||
child: Padding(
|
||||
padding: padding ?? EdgeInsets.zero,
|
||||
child: Row(children: [
|
||||
if (logo != null)
|
||||
buildImage(
|
||||
imagePath: logo!,
|
||||
imageSize: sizeLogo,
|
||||
),
|
||||
Padding(
|
||||
padding: paddingText ?? const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Text(
|
||||
text ?? '',
|
||||
style: textStyle,
|
||||
textAlign: textAlign,
|
||||
overflow: enableOverflow ? TextOverflow.ellipsis : null,
|
||||
maxLines: enableOverflow ? 1 : null,
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _logoApp() {
|
||||
if (logo != null && logo!.endsWith('svg')) {
|
||||
return SvgPicture.asset(
|
||||
logo!,
|
||||
width: sizeLogo ?? 150,
|
||||
height: sizeLogo ?? 150);
|
||||
} else if (logo != null) {
|
||||
return Image(
|
||||
image: AssetImage(logo!),
|
||||
fit: BoxFit.fill,
|
||||
width: sizeLogo ?? 150,
|
||||
height: sizeLogo ?? 150);
|
||||
} else if (publicLogoUri != null) {
|
||||
return Image.network(
|
||||
publicLogoUri.toString(),
|
||||
fit: BoxFit.fill,
|
||||
width: sizeLogo ?? 150,
|
||||
height: sizeLogo ?? 150,
|
||||
errorBuilder: (_, error, stackTrace) {
|
||||
return Container(
|
||||
width: sizeLogo ?? 150,
|
||||
height: sizeLogo ?? 150,
|
||||
color: AppColor.textFieldHintColor,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,4 +69,8 @@ class StringConvert {
|
||||
throw const UnsupportedCharsetException();
|
||||
}
|
||||
}
|
||||
|
||||
static String toUrlScheme(String hostScheme) {
|
||||
return '$hostScheme://';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user