diff --git a/lib/data/web_client.dart b/lib/data/web_client.dart index 8a0762d10..c979d162b 100644 --- a/lib/data/web_client.dart +++ b/lib/data/web_client.dart @@ -109,7 +109,7 @@ class WebClient { .timeout(const Duration(seconds: 30)); } - print('response: ${response.body}'); + //print('response: ${response.body}'); if (response.statusCode >= 300) { print('==== FAILED ===='); @@ -170,7 +170,7 @@ class WebClient { }, ); - print('response: ${response.body}'); + //print('response: ${response.body}'); if (response.statusCode >= 300) { print('==== FAILED ===='); diff --git a/lib/main.dart b/lib/main.dart index f8d10326b..5654da773 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -48,7 +48,8 @@ import 'package:invoiceninja_flutter/redux/quote/quote_actions.dart'; import 'package:invoiceninja_flutter/redux/quote/quote_middleware.dart'; // STARTER: import - do not remove comment -void main() async { +void main({bool isTesting = false}) async { + final SentryClient _sentry = Config.SENTRY_DNS.isEmpty ? null : SentryClient( @@ -68,6 +69,7 @@ void main() async { enableDarkMode: enableDarkMode, requireAuthentication: requireAuthentication, layout: AppLayout.tablet, + isTesting: isTesting, ), middleware: [] ..addAll(createStoreAuthMiddleware()) @@ -86,7 +88,9 @@ void main() async { ..addAll(createStoreSettingsMiddleware()) // STARTER: middleware - do not remove comment ..addAll([ - LoggingMiddleware.printer(), + LoggingMiddleware.printer( + formatter: LoggingMiddleware.multiLineFormatter, + ), ])); Future _reportError(dynamic error, dynamic stackTrace) async { diff --git a/lib/redux/app/app_reducer.dart b/lib/redux/app/app_reducer.dart index 087bf920d..3dca77a46 100644 --- a/lib/redux/app/app_reducer.dart +++ b/lib/redux/app/app_reducer.dart @@ -13,7 +13,8 @@ AppState appReducer(AppState state, dynamic action) { if (action is UserLogout) { return AppState().rebuild((b) => b ..authState.replace(state.authState) - ..uiState.enableDarkMode = state.uiState.enableDarkMode); + ..uiState.enableDarkMode = state.uiState.enableDarkMode + ..uiState.isTesting = state.uiState.isTesting); } else if (action is LoadStateSuccess) { return action.state.rebuild((b) => b ..isLoading = false diff --git a/lib/redux/app/app_state.dart b/lib/redux/app/app_state.dart index 22ea686b3..609d13a65 100644 --- a/lib/redux/app/app_state.dart +++ b/lib/redux/app/app_state.dart @@ -41,6 +41,7 @@ abstract class AppState implements Built { bool enableDarkMode, bool requireAuthentication, AppLayout layout, + bool isTesting, }) { return _$AppState._( isLoading: false, @@ -58,6 +59,7 @@ abstract class AppState implements Built { enableDarkMode: enableDarkMode, requireAuthentication: requireAuthentication, layout: layout ?? AppLayout.mobile, + isTesting: isTesting, ), ); } @@ -264,6 +266,7 @@ abstract class AppState implements Built { @override String toString() { - return 'Route: ${uiState.currentRoute}, Previous: ${uiState.previousRoute}, Layout: ${uiState.layout}, Menu: ${uiState.isMenuVisible}, History: ${uiState.isHistoryVisible}'; + return 'Is Testing: ${uiState.isTesting}'; + //return 'Route: ${uiState.currentRoute}, Previous: ${uiState.previousRoute}, Layout: ${uiState.layout}, Menu: ${uiState.isMenuVisible}, History: ${uiState.isHistoryVisible}'; } } diff --git a/lib/redux/ui/ui_state.dart b/lib/redux/ui/ui_state.dart index 6b85d6954..c9495a3f7 100644 --- a/lib/redux/ui/ui_state.dart +++ b/lib/redux/ui/ui_state.dart @@ -26,12 +26,18 @@ import 'package:invoiceninja_flutter/redux/quote/quote_state.dart'; part 'ui_state.g.dart'; abstract class UIState implements Built { - factory UIState(CompanyEntity company, - {bool enableDarkMode, bool requireAuthentication, AppLayout layout}) { + factory UIState( + CompanyEntity company, { + bool enableDarkMode, + bool requireAuthentication, + AppLayout layout, + bool isTesting, + }) { return _$UIState._( selectedCompanyIndex: 0, //layout: layout ?? AppLayout.mobile, layout: layout ?? AppLayout.tablet, + isTesting: isTesting ?? false, isMenuVisible: true, isHistoryVisible: false, currentRoute: LoginScreen.route, @@ -60,6 +66,8 @@ abstract class UIState implements Built { AppLayout get layout; + bool get isTesting; + bool get isMenuVisible; bool get isHistoryVisible; diff --git a/lib/redux/ui/ui_state.g.dart b/lib/redux/ui/ui_state.g.dart index 50a5d2821..da8fca6d7 100644 --- a/lib/redux/ui/ui_state.g.dart +++ b/lib/redux/ui/ui_state.g.dart @@ -66,6 +66,9 @@ class _$UIStateSerializer implements StructuredSerializer { 'layout', serializers.serialize(object.layout, specifiedType: const FullType(AppLayout)), + 'isTesting', + serializers.serialize(object.isTesting, + specifiedType: const FullType(bool)), 'isMenuVisible', serializers.serialize(object.isMenuVisible, specifiedType: const FullType(bool)), @@ -154,6 +157,10 @@ class _$UIStateSerializer implements StructuredSerializer { result.layout = serializers.deserialize(value, specifiedType: const FullType(AppLayout)) as AppLayout; break; + case 'isTesting': + result.isTesting = serializers.deserialize(value, + specifiedType: const FullType(bool)) as bool; + break; case 'isMenuVisible': result.isMenuVisible = serializers.deserialize(value, specifiedType: const FullType(bool)) as bool; @@ -289,6 +296,8 @@ class _$UIState extends UIState { @override final AppLayout layout; @override + final bool isTesting; + @override final bool isMenuVisible; @override final bool isHistoryVisible; @@ -338,6 +347,7 @@ class _$UIState extends UIState { _$UIState._( {this.layout, + this.isTesting, this.isMenuVisible, this.isHistoryVisible, this.selectedCompanyIndex, @@ -364,6 +374,9 @@ class _$UIState extends UIState { if (layout == null) { throw new BuiltValueNullFieldError('UIState', 'layout'); } + if (isTesting == null) { + throw new BuiltValueNullFieldError('UIState', 'isTesting'); + } if (isMenuVisible == null) { throw new BuiltValueNullFieldError('UIState', 'isMenuVisible'); } @@ -441,6 +454,7 @@ class _$UIState extends UIState { if (identical(other, this)) return true; return other is UIState && layout == other.layout && + isTesting == other.isTesting && isMenuVisible == other.isMenuVisible && isHistoryVisible == other.isHistoryVisible && selectedCompanyIndex == other.selectedCompanyIndex && @@ -485,7 +499,7 @@ class _$UIState extends UIState { $jc( $jc( $jc( - $jc($jc($jc($jc($jc(0, layout.hashCode), isMenuVisible.hashCode), isHistoryVisible.hashCode), selectedCompanyIndex.hashCode), + $jc($jc($jc($jc($jc($jc(0, layout.hashCode), isTesting.hashCode), isMenuVisible.hashCode), isHistoryVisible.hashCode), selectedCompanyIndex.hashCode), currentRoute.hashCode), previousRoute.hashCode), enableDarkMode.hashCode), @@ -511,6 +525,7 @@ class _$UIState extends UIState { String toString() { return (newBuiltValueToStringHelper('UIState') ..add('layout', layout) + ..add('isTesting', isTesting) ..add('isMenuVisible', isMenuVisible) ..add('isHistoryVisible', isHistoryVisible) ..add('selectedCompanyIndex', selectedCompanyIndex) @@ -544,6 +559,10 @@ class UIStateBuilder implements Builder { AppLayout get layout => _$this._layout; set layout(AppLayout layout) => _$this._layout = layout; + bool _isTesting; + bool get isTesting => _$this._isTesting; + set isTesting(bool isTesting) => _$this._isTesting = isTesting; + bool _isMenuVisible; bool get isMenuVisible => _$this._isMenuVisible; set isMenuVisible(bool isMenuVisible) => @@ -667,6 +686,7 @@ class UIStateBuilder implements Builder { UIStateBuilder get _$this { if (_$v != null) { _layout = _$v.layout; + _isTesting = _$v.isTesting; _isMenuVisible = _$v.isMenuVisible; _isHistoryVisible = _$v.isHistoryVisible; _selectedCompanyIndex = _$v.selectedCompanyIndex; @@ -714,6 +734,7 @@ class UIStateBuilder implements Builder { _$result = _$v ?? new _$UIState._( layout: layout, + isTesting: isTesting, isMenuVisible: isMenuVisible, isHistoryVisible: isHistoryVisible, selectedCompanyIndex: selectedCompanyIndex, diff --git a/lib/ui/app/app_drawer.dart b/lib/ui/app/app_drawer.dart index 4bfcef496..347cf50fd 100644 --- a/lib/ui/app/app_drawer.dart +++ b/lib/ui/app/app_drawer.dart @@ -1,5 +1,6 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +import 'package:invoiceninja_flutter/ui/app/resources/cached_image.dart'; import 'package:redux/redux.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:invoiceninja_flutter/constants.dart'; @@ -17,7 +18,6 @@ import 'package:invoiceninja_flutter/utils/keys.dart'; import 'package:invoiceninja_flutter/utils/localization.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:invoiceninja_flutter/utils/platforms.dart'; -import 'package:cached_network_image/cached_network_image.dart'; import 'package:invoiceninja_flutter/redux/expense/expense_actions.dart'; import 'package:invoiceninja_flutter/redux/vendor/vendor_actions.dart'; import 'package:invoiceninja_flutter/redux/task/task_actions.dart'; @@ -60,16 +60,10 @@ class AppDrawer extends StatelessWidget { height: 30, ) : company.logoUrl != null && company.logoUrl.isNotEmpty - ? CachedNetworkImage( + ? CachedImage( width: 32, height: 30, - key: ValueKey(company.logoUrl), - imageUrl: company.logoUrl, - placeholder: (context, url) => CircularProgressIndicator(), - errorWidget: (context, url, error) => Image.asset( - 'assets/images/logo.png', - width: 32, - height: 30), + url: company.logoUrl, ) : Image.asset('assets/images/logo.png', width: 32, height: 30), SizedBox(width: 28, height: 50), @@ -104,17 +98,10 @@ class AppDrawer extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, children: [ company.logoUrl != null && company.logoUrl.isNotEmpty - ? CachedNetworkImage( + ? CachedImage( width: 32, height: 30, - key: ValueKey(company.logoUrl), - imageUrl: company.logoUrl, - placeholder: (context, url) => - CircularProgressIndicator(), - errorWidget: (context, url, error) => Image.asset( - 'assets/images/logo.png', - width: 32, - height: 30), + url: company.logoUrl, ) : Image.asset('assets/images/logo.png', width: 32, height: 30), diff --git a/lib/ui/app/resources/cached_image.dart b/lib/ui/app/resources/cached_image.dart new file mode 100644 index 000000000..c8b7da21b --- /dev/null +++ b/lib/ui/app/resources/cached_image.dart @@ -0,0 +1,39 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_redux/flutter_redux.dart'; +import 'package:invoiceninja_flutter/redux/app/app_state.dart'; + +class CachedImage extends StatelessWidget { + + const CachedImage({this.url, this.width, this.height, this.showNinjaOnError = true}); + final String url; + final bool showNinjaOnError; + final double width; + final double height; + + @override + Widget build(BuildContext context) { + final store = StoreProvider.of(context); + final uiState = store.state.uiState; + + // TODO remove this workaround + if (uiState.isTesting) { + return SizedBox( + width: width, + height: height, + ); + } + + return CachedNetworkImage( + width: 32, + height: 30, + key: ValueKey(url), + imageUrl: url, + placeholder: (context, url) => CircularProgressIndicator(), + errorWidget: (context, url, error) => Image.asset( + 'assets/images/logo.png', + width: 32, + height: 30), + ); + } +} diff --git a/lib/utils/keys.dart b/lib/utils/keys.dart index 55b990acd..55400e07f 100644 --- a/lib/utils/keys.dart +++ b/lib/utils/keys.dart @@ -1,7 +1,6 @@ class AppKeys { static const String openAppDrawer = 'Open navigation menu'; static const String dashboardScreen = 'DashboardScreen'; - static const String successfullyCreated = 'Successfully created'; } class AppTooltips { diff --git a/test_driver/login_it.dart b/test_driver/login_it.dart index a0098506d..bf300dcf3 100644 --- a/test_driver/login_it.dart +++ b/test_driver/login_it.dart @@ -6,5 +6,5 @@ import 'package:invoiceninja_flutter/main.dart' as app; void main() { // This line enables the extension enableFlutterDriverExtension(); - app.main(); + app.main(isTesting: true); } \ No newline at end of file diff --git a/test_driver/utils/common_actions.dart b/test_driver/utils/common_actions.dart index 147e6bd04..a5664a69a 100644 --- a/test_driver/utils/common_actions.dart +++ b/test_driver/utils/common_actions.dart @@ -31,7 +31,7 @@ Future login(FlutterDriver driver, Future logout(FlutterDriver driver, TestLocalization localization) async { // Go to Settings Screen await driver.tap(find.byTooltip(AppKeys.openAppDrawer)); - await driver.scrollUntilVisible(find.byType('Drawer'), find.byValueKey(SettingsKeys.drawer)); + //await driver.scrollUntilVisible(find.byType('Drawer'), find.byValueKey(SettingsKeys.drawer)); await driver.tap(find.byValueKey(SettingsKeys.drawer)); // Tap on Log Out