Skip to content

Commit

Permalink
Merge branch 'master' into Display-Limits-of-Email-Recovery
Browse files Browse the repository at this point in the history
  • Loading branch information
florentos17 authored Nov 18, 2024
2 parents 57777f7 + 45581e4 commit 7ba818f
Show file tree
Hide file tree
Showing 98 changed files with 2,463 additions and 709 deletions.
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
## [0.14.0] - 2024-11-09
### Added
- #2387 TWP Registration from mobile
- #3157 Web socket to replace FCM in web app
- #2953 Mobile integration test with Patrol

### Fixed
- #3244 `To` filter should apply also for `cc` `bcc`
- #3243 some tags still be in sanitizing
- #3178 Only Space in Name verification for Identity, Rule Filter, Vacation
- 3D links not work on mobile
- Focus problem in `tab` in Basic Auth login form
- #3225 Print button blink blink
- #3222 Hide reply calendar event action button
- #3247 Cc is lost if open email from Quick search result
- #3200 Update option menu for personal folders
- Support German

## [0.13.6] - 2024-11-07
### Fixed
- Remove app grid in mobile

## [0.13.5] - 2024-10-24
### Fixed
- Sanitize html
Expand Down
18 changes: 12 additions & 6 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,6 @@
<data android:scheme="mailto"/>
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
Expand All @@ -98,6 +92,18 @@
</intent-filter>
</activity>

<activity
android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
android:exported="true">
<intent-filter android:label="flutter_web_auth_2">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="twakemail.mobile"
android:host="redirect" />
</intent-filter>
</activity>

<provider android:authorities="${applicationId}.firebaseinitprovider"
android:name="com.google.firebase.provider.FirebaseInitProvider"
android:exported="false"
Expand Down
48 changes: 48 additions & 0 deletions assets/images/ic_logo_twake_welcome.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions backend-docker/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ services:
- ./mailetcontainer.xml:/root/conf/mailetcontainer.xml
- ./imapserver.xml:/root/conf/imapserver.xml
- ./jmap.properties:/root/conf/jmap.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:
- "80:80"
environment:
Expand Down
1 change: 1 addition & 0 deletions core/lib/core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export 'presentation/extensions/capitalize_extension.dart';
export 'presentation/extensions/list_extensions.dart';
export 'presentation/extensions/list_nullable_extensions.dart';
export 'domain/extensions/datetime_extension.dart';
export 'domain/extensions/list_datetime_extension.dart';
export 'presentation/extensions/html_extension.dart';
export 'presentation/extensions/compare_string_extension.dart';
export 'presentation/extensions/compare_list_extensions.dart';
Expand Down
2 changes: 2 additions & 0 deletions core/lib/data/constants/constant.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ class Constant {
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';
}
21 changes: 21 additions & 0 deletions core/lib/domain/extensions/list_datetime_extension.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

extension ListDateTimeExtension on List<DateTime> {

bool isSortedByMostRecent() {
for (int i = 0; i < length - 1; i++) {
if (this[i].isBefore(this[i + 1])) {
return false;
}
}
return true;
}

bool isSortedByOldestFirst() {
for (int i = 0; i < length - 1; i++) {
if (this[i].isAfter(this[i + 1])) {
return false;
}
}
return true;
}
}
1 change: 1 addition & 0 deletions core/lib/presentation/resources/image_paths.dart
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ class ImagePaths {
String get icGoodSignature => _getImagePath('ic_good_signature.svg');
String get icBadSignature => _getImagePath('ic_bad_signature.svg');
String get icDeleteSelection => _getImagePath('ic_delete_selection.svg');
String get icLogoTwakeWelcome => _getImagePath('ic_logo_twake_welcome.svg');

String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class StandardizeHtmlSanitizingTransformers extends TextTransformer {
'center',
'style',
'body',
'section',
];

const StandardizeHtmlSanitizingTransformers();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import 'package:pointer_interceptor/pointer_interceptor.dart';
class CupertinoActionSheetBuilder {

final BuildContext _context;
final Key? key;
final List<Widget> _actionTiles = [];

Widget? _titleWidget;
Widget? _messageWidget;
Widget? _cancelWidget;

CupertinoActionSheetBuilder(this._context);
CupertinoActionSheetBuilder(this._context, {this.key});

void title(Widget? titleWidget) {
_titleWidget = titleWidget;
Expand All @@ -35,6 +36,7 @@ class CupertinoActionSheetBuilder {
context: _context,
barrierColor: AppColor.colorDefaultCupertinoActionSheet,
builder: (context) => PointerInterceptor(child: CupertinoActionSheet(
key: key,
title: _titleWidget,
message: _messageWidget,
actions: _actionTiles,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ void main() {
];

const listHTMLTags = [
'div', 'span', 'p', 'a', 'u', 'i', 'table'
'div', 'span', 'p', 'a', 'u', 'i', 'table', 'section'
];

for (var tag in listHTMLTags) {
Expand Down
4 changes: 2 additions & 2 deletions docs/adr/0036-mailto-uri-chemes-to-interact-twake-mail.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ Summary of URI schemes that can interact with Twake Mail:

- `/[email protected]`
- `/mailto/?uri=mailto:[email protected]&subject=TwakeMail&body=HelloWorld`
- `/mailto/?uri=mailto:[email protected],[email protected],[email protected]&subject=TwakeMail&body=HelloWorld`
- `/mailto/?uri=mailto:[email protected],[email protected],[email protected]&[email protected],[email protected],[email protected]&[email protected],[email protected],[email protected]&[email protected],[email protected],[email protected]&subject=TwakeMail&body=HelloWorld`

2. URI scheme encoded

- `%2Fmailto%3Furi%3Duser%40example.com`
- `%2Fmailto%2F%3Furi%3Dmailto%3Auser%40example.com%26subject%3DTwakeMail%26body%3DHelloWorld`
- `%2Fmailto%2F%3Furi%3Dmailto%3Auser1%40example.com%2Cuser2%40example.com%2Cuser3%40example.com%26subject%3DTwakeMail%26body%3DHelloWorld`
- `%2Fmailto%2F%3Furi%3Dmailto%3Auser1%40example.com%2Cuser2%40example.com%2Cuser3%40example.com%26to=user1%40example.com%2Cuser2%40example.com%2Cuser3%40example.com%26cc=user1%40example.com%2Cuser2%40example.com%2Cuser3%40example.com%26bcc=user1%40example.com%2Cuser2%40example.com%2Cuser3%40example.com%26subject%3DTwakeMail%26body%3DHelloWorld`

## Consequences

Expand Down
6 changes: 6 additions & 0 deletions integration_test/base/base_scenario.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:patrol/patrol.dart';

abstract class BaseScenario {
Expand All @@ -6,4 +7,9 @@ abstract class BaseScenario {
const BaseScenario(this.$);

Future<void> execute();

Future<void> expectViewVisible(PatrolFinder patrolFinder) async {
await $.waitUntilVisible(patrolFinder);
expect(patrolFinder, findsWidgets);
}
}
6 changes: 0 additions & 6 deletions integration_test/base/core_robot.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:patrol/patrol.dart';

abstract class CoreRobot {
final PatrolIntegrationTester $;

CoreRobot(this.$);

Future<void> ensureViewVisible(PatrolFinder patrolFinder) async {
await $.waitUntilVisible(patrolFinder);
expect(patrolFinder, findsWidgets);
}

dynamic ignoreException() => $.tester.takeException();
}
4 changes: 0 additions & 4 deletions integration_test/robots/composer_robot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ class ComposerRobot extends CoreRobot {
.tap();
}

Future<void> expectSendEmailSuccessToast() async {
expect($('Message has been sent successfully'), findsOneWidget);
}

Future<void> grantContactPermission() async {
if (await $.native.isPermissionDialogVisible(timeout: const Duration(seconds: 5))) {
await $.native.grantPermissionWhenInUse();
Expand Down
13 changes: 12 additions & 1 deletion integration_test/robots/login_robot.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
import 'package:core/presentation/views/text/type_ahead_form_field_builder.dart';
import 'package:flutter/material.dart';
import 'package:patrol/patrol.dart';
import 'package:tmail_ui_user/features/login/domain/model/recent_login_username.dart';
import 'package:tmail_ui_user/features/login/presentation/login_view.dart';
import 'package:tmail_ui_user/features/login/presentation/widgets/login_text_input_builder.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';

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

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

Future<void> expectLoginViewVisible() => ensureViewVisible($(LoginView));
Future<void> grantNotificationPermission(NativeAutomator nativeAutomator) async {
if (await nativeAutomator.isPermissionDialogVisible(timeout: const Duration(seconds: 5))) {
await nativeAutomator.grantPermissionWhenInUse();
}
}

Future<void> tapOnUseCompanyServer() async {
await $.pumpAndSettle();
await $(AppLocalizations().useCompanyServer).tap();
}

Future<void> enterEmail(String email) async {
final finder = $(LoginView).$(TextField);
Expand Down
30 changes: 30 additions & 0 deletions integration_test/robots/search_robot.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

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

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

Future<void> enterQueryString(String queryString) async {
await $(#search_email_text_field).enterText(queryString);
}

Future<void> scrollToEndListSearchFilter() async {
await $.scrollUntilVisible(
finder: $(#mobile_sortBy_search_filter_button),
view: $(#search_filter_list_view),
scrollDirection: AxisDirection.right,
delta: 300,
);
}

Future<void> openSortOrderBottomDialog() async {
await $(#mobile_sortBy_search_filter_button).tap();
}

Future<void> selectSortOrder(String sortOrderName) async {
await $(find.text(sortOrderName)).tap();
await $.pump(const Duration(seconds: 2));
}
}
9 changes: 4 additions & 5 deletions integration_test/robots/thread_robot.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import 'package:core/presentation/views/search/search_bar_view.dart';
import 'package:flutter/material.dart';
import 'package:tmail_ui_user/features/base/widget/compose_floating_button.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_view.dart';
import 'package:tmail_ui_user/features/thread/presentation/thread_view.dart';

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

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

Future<void> expectThreadViewVisible() => ensureViewVisible($(ThreadView));

Future<void> openComposer() async {
await $(ComposeFloatingButton).$(InkWell).tap();
}

Future<void> expectComposerViewVisible() => ensureViewVisible($(ComposerView));
Future<void> openSearchView() async {
await $(SearchBarView).$(InkWell).tap();
}
}
Loading

0 comments on commit 7ba818f

Please sign in to comment.