TF-3260 Load & Display App Grid Linagora Ecosystem

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2024-12-09 12:40:57 +07:00
committed by Dat H. Pham
parent 95f05c4715
commit dce74b43e9
48 changed files with 894 additions and 435 deletions
+1
View File
@@ -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';
+2
View File
@@ -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();
}
}
}
+4
View File
@@ -69,4 +69,8 @@ class StringConvert {
throw const UnsupportedCharsetException();
}
}
static String toUrlScheme(String hostScheme) {
return '$hostScheme://';
}
}