Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TF-3260 Appgrid the right way #3329

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
<uses-sdk tools:overrideLibrary="io.flutter.plugins.webviewflutter, com.pichillilorenzo.flutter_inappwebview" />

<queries>
<package android:name="com.linagora.android.linshare" />

<intent>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
Expand Down
3 changes: 2 additions & 1 deletion backend-docker/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ version: "3"

services:
tmail-backend:
image: linagora/tmail-backend:memory-1.0.0
image: linagora/tmail-backend:memory-1.0.1-rc1
container_name: tmail-backend
volumes:
- ./jwt_publickey:/root/conf/jwt_publickey
- ./jwt_privatekey:/root/conf/jwt_privatekey
- ./mailetcontainer.xml:/root/conf/mailetcontainer.xml
- ./imapserver.xml:/root/conf/imapserver.xml
- ./jmap.properties:/root/conf/jmap.properties
- ./linagora-ecosystem.properties:/root/conf/linagora-ecosystem.properties
- ../provisioning/integration_test/search_email_with_sort_order/provisioning.sh:/root/conf/integration_test/search_email_with_sort_order/provisioning.sh
- ../provisioning/integration_test/search_email_with_sort_order/eml:/root/conf/integration_test/search_email_with_sort_order/eml
ports:
Expand Down
11 changes: 11 additions & 0 deletions backend-docker/linagora-ecosystem.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Twake_Drive.appName=Twake Drive
Twake_Drive.logoURL=https://sign-up.stg.lin-saas.com/images/tdrive.svg
Twake_Drive.webLink=https://drive.stg.lin-saas.com/
mobileApps.Twake_Chat.appName=Twake Chat
mobileApps.Twake_Chat.logoURL=https://sign-up.stg.lin-saas.com/images/twakechat.svg
mobileApps.Twake_Chat.androidPackageId=app.twake.android.chat
mobileApps.Twake_Chat.iosUrlScheme=twake.chat
mobileApps.Twake_Chat.iosAppStoreLink=itms-apps://itunes.apple.com/us/app/twake-chat/id6473384641
mobileApps.Twake_Sync.appName=Twake Sync
mobileApps.Twake_Sync.logoURL=https://twake.app/tild3364-6130-4763-b634-343435643861__twp-logo_1.svg
mobileApps.Twake_Sync.androidPackageId=com.twake.android.sync
10 changes: 5 additions & 5 deletions backend-docker/mailetcontainer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@
<name>bcc</name>
<onMailetException>ignore</onMailetException>
</mailet>
<mailet match="All" class="RemoveMimeHeader">
<name>X-SMIME-Status</name>
<onMailetException>ignore</onMailetException>
</mailet>
<mailet match="All" class="RecipientRewriteTable">
<errorProcessor>rrt-error</errorProcessor>
</mailet>
Expand All @@ -88,9 +92,6 @@
<mailet match="All" class="Sieve"/>
<mailet match="All" class="AddDeliveredToHeader"/>
<mailet match="All" class="org.apache.james.jmap.mailet.filter.JMAPFiltering"/>
<mailet match="SenderIsLocal" class="com.linagora.tmail.mailets.ContactsCollection">
<attribute>ContactAttribute1</attribute>
</mailet>
<mailet match="All" class="com.linagora.tmail.mailets.TmailLocalDelivery"/>
</processor>

Expand Down Expand Up @@ -151,5 +152,4 @@

</processors>

</mailetcontainer>

</mailetcontainer>
1 change: 1 addition & 0 deletions core/lib/core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,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';
Expand Down
22 changes: 12 additions & 10 deletions core/lib/data/constants/constant.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
class Constant {
static const acceptHeaderDefault = 'application/json';
static const contentTypeHeaderDefault = 'application/json';
static const pdfMimeType = 'application/pdf';
static const base64Charset = 'base64';
static const textHtmlMimeType = 'text/html';
static const octetStreamMimeType = 'application/octet-stream';
static const pdfExtension = '.pdf';
static const imageType = 'image';
static const textVCardMimeType = 'text/x-vcard';
static const textPlainMimeType = 'text/plain';
static const String acceptHeaderDefault = 'application/json';
static const String contentTypeHeaderDefault = 'application/json';
static const String pdfMimeType = 'application/pdf';
static const String base64Charset = 'base64';
static const String textHtmlMimeType = 'text/html';
static const String octetStreamMimeType = 'application/octet-stream';
static const String pdfExtension = '.pdf';
static const String imageType = 'image';
static const String textVCardMimeType = 'text/x-vcard';
static const String textPlainMimeType = 'text/plain';
static const String slashCharacter = '/';
static const String andCharacter = '&';
}
70 changes: 70 additions & 0 deletions core/lib/presentation/views/image/image_loader_mixin.dart
Original file line number Diff line number Diff line change
@@ -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(
tddang-linagora marked this conversation as resolved.
Show resolved Hide resolved
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;
}
128 changes: 53 additions & 75 deletions core/lib/presentation/views/text/slogan_builder.dart
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
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.
/// The elements are arranged in a column or row.

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;
Expand All @@ -33,7 +30,6 @@ class SloganBuilder extends StatelessWidget {
this.textStyle,
this.textAlign,
this.logo,
this.publicLogoUri,
this.sizeLogo,
this.onTapCallback,
this.padding,
Expand All @@ -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 changes: 4 additions & 0 deletions core/lib/utils/string_convert.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ class StringConvert {
return text;
}
}

static String toUrlScheme(String hostScheme) {
return '$hostScheme://';
}
}
4 changes: 4 additions & 0 deletions integration_test/base/base_scenario.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,8 @@ abstract class BaseScenario {
await $.waitUntilVisible(patrolFinder);
expect(patrolFinder, findsWidgets);
}

Future<void> expectViewInVisible(PatrolFinder patrolFinder) async {
expect(patrolFinder, findsNothing);
}
}
12 changes: 12 additions & 0 deletions integration_test/robots/app_grid_robot.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

import 'package:flutter_test/flutter_test.dart';

import '../base/core_robot.dart';

class AppGridRobot extends CoreRobot {
AppGridRobot(super.$);

Future<void> openAppInAppGridByAppName(String appName) async {
await $(find.text(appName)).tap();
}
}
10 changes: 10 additions & 0 deletions integration_test/robots/mailbox_menu_robot.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

import '../base/core_robot.dart';

class MailboxMenuRobot extends CoreRobot {
MailboxMenuRobot(super.$);

Future<void> openAppGrid() async {
await $(#toggle_app_grid_button).tap();
}
}
4 changes: 4 additions & 0 deletions integration_test/robots/thread_robot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ class ThreadRobot extends CoreRobot {
Future<void> tapOnSearchField() async {
await $(ThreadView).$(SearchBarView).tap();
}

Future<void> openMailbox() async {
await $(#mobile_mailbox_menu_button).tap();
}
}
Loading
Loading