diff --git a/Jenkinsfile b/Jenkinsfile index 1874d3f..2ae4da0 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -10,6 +10,7 @@ pipeline { string(name: 'APP_PACKAGE_ID', defaultValue: 'comptaplan.app', description: 'Application package id used as android identifier') string(name: 'APP_BUNDLE_ID', defaultValue: 'comptaplan_app', description: 'Application bundle id used as ios identifier') string(name: 'APP_TITLE', defaultValue: 'My Comptaplan', description: 'Application title') + string(name: 'APP_URI', defaultValue: 'https://my.comptaplan.be', description: 'Application uri') string(name: 'APP_COLOR', defaultValue: 'blue', description: 'Application color (blue, teal, ...)') string(name: 'BUILD_MODE', defaultValue: 'debug', description: 'Flutter build mode (debug/release)') string(name: 'ANDROID_SIGNING_KEYSTORE_CREDENTIAL', defaultValue: 'jenkins-gestemps-android-service-secret-keystore') @@ -38,6 +39,7 @@ pipeline { env.APP_PACKAGE_ID= params.APP_PACKAGE_ID env.APP_BUNDLE_ID= params.APP_BUNDLE_ID env.APP_TITLE= params.APP_TITLE + env.APP_URI= params.APP_URI env.APP_COLOR= params.APP_COLOR env.BUILD_MODE= params.BUILD_MODE env.SSH_KNOWN_HOSTS_FILE= params.SSH_KNOWN_HOSTS_FILE diff --git a/lib/main.dart b/lib/main.dart index f666b70..ee8a969 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,25 +1,33 @@ import 'package:comptaplan_app/winbooks_migration_widget.dart'; +import 'package:comptaplan_app/webview_widget.dart'; import 'package:flutter/material.dart'; void main() { const title = String.fromEnvironment("APP_TITLE"); + const uri = String.fromEnvironment("APP_URI"); const playStoreUri = 'https://play.google.com/store/apps/details?id=com.winbooks.connect'; + const appStoreUri = 'https://apps.apple.com/be/app/winbooks-connect/id1534550954'; const color = String.fromEnvironment("APP_COLOR"); - runApp(const MyApp(title, playStoreUri, color)); + runApp(const MyApp(title, uri, playStoreUri, appStoreUri, color)); } class MyApp extends StatelessWidget { final String _title; final String _uri; + final String _playstoreUri; + final String _appStoreUri; final String _color; - const MyApp(this._title, this._uri, this._color, {Key? key}) : super(key: key); + const MyApp(this._title, this._uri, this._playstoreUri, this._appStoreUri, this._color, {Key? key}) : super(key: key); // This widget is the root of your application. @override Widget build(BuildContext context) { MaterialColor materialColor = _getMaterialColor(_color); - return MaterialApp(title: _title, theme: ThemeData(primarySwatch: materialColor), home: WinbooksMigrationWidget(_title, _uri)); + return MaterialApp(title: _title, theme: ThemeData(primarySwatch: materialColor), initialRoute: '/migrate', routes: { + '/migrate': (context) => WinbooksMigrationWidget(_title, _playstoreUri, _appStoreUri), + '/web': (context) => WebViewWidget(_uri), + }); } MaterialColor _getMaterialColor(String colorString) { diff --git a/lib/webview_widget.dart b/lib/webview_widget.dart new file mode 100644 index 0000000..a16e0c1 --- /dev/null +++ b/lib/webview_widget.dart @@ -0,0 +1,47 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_webview_pro/webview_flutter.dart'; + +class WebViewWidget extends StatefulWidget { + final String _initialUrl; + + const WebViewWidget(this._initialUrl, {Key? key}) : super(key: key); + + @override + WebViewWidgetState createState() => WebViewWidgetState(); +} + +class WebViewWidgetState extends State { + WebViewWidgetState(); + + @override + void initState() { + super.initState(); + // Enable hybrid composition. + if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView(); + } + + @override + Widget build(BuildContext context) { + return WebView( + initialUrl: widget._initialUrl, + javascriptMode: JavascriptMode.unrestricted, + javascriptChannels: { + _toasterJavascriptChannel(context), + }, + gestureNavigationEnabled: true, + ); + } + + JavascriptChannel _toasterJavascriptChannel(BuildContext context) { + return JavascriptChannel( + name: 'Toaster', + onMessageReceived: (JavascriptMessage message) { + // ignore: deprecated_member_use + Scaffold.of(context).showSnackBar( + SnackBar(content: Text(message.message)), + ); + }); + } +} diff --git a/lib/winbooks_migration_widget.dart b/lib/winbooks_migration_widget.dart index 0dafbfb..7c9db6e 100644 --- a/lib/winbooks_migration_widget.dart +++ b/lib/winbooks_migration_widget.dart @@ -2,12 +2,14 @@ import 'dart:io'; import 'package:android_intent_plus/android_intent.dart'; import 'package:flutter/material.dart'; +import 'package:url_launcher/url_launcher.dart'; class WinbooksMigrationWidget extends StatefulWidget { final String _playStoreUrl; + final String _appStoreUrl; final String _title; - const WinbooksMigrationWidget(this._title, this._playStoreUrl, {Key? key}) : super(key: key); + const WinbooksMigrationWidget(this._title, this._playStoreUrl, this._appStoreUrl, {Key? key}) : super(key: key); @override WinbooksMigrationWidgetState createState() => WinbooksMigrationWidgetState(); @@ -50,7 +52,7 @@ class WinbooksMigrationWidgetState extends State { child: Row(children: [ Image.asset('images/winbooks_connect.png', bundle: assetBundle, width: 50.0, height: 50.0), const SizedBox(width: 10), - const Text('Télécharger WinBooks Connect') + const Flexible(child: Text('Télécharger WinBooks Connect', textAlign: TextAlign.left, softWrap: true)) ]), onPressed: () async { return _onWinbooksConnectPress(); @@ -65,6 +67,23 @@ class WinbooksMigrationWidgetState extends State { textAlign: TextAlign.left, style: smallerTextStyle), ), + Center( + child: Container( + margin: const EdgeInsets.all(10.0), + child: ElevatedButton( + style: ElevatedButton.styleFrom(textStyle: smallerTextStyle, padding: const EdgeInsets.all(10.0)), + child: const Text('Vers My Comptaplan', softWrap: true), + onPressed: () async { + return _onMyComptaplanPress(); + }, + ), + ), + ), + Container( + margin: const EdgeInsets.all(10.0), + child: Text("L'accès à My Comptaplan risque de ne plus fonctionner prochainement.", + textAlign: TextAlign.left, style: smallerTextStyle), + ), ]) ], )); @@ -77,7 +96,13 @@ class WinbooksMigrationWidgetState extends State { data: widget._playStoreUrl, package: 'com.android.vending', ); - return intent.launch(); + await intent.launch(); + } else if (Platform.isIOS) { + await launch(widget._appStoreUrl); } } + + Future _onMyComptaplanPress() async { + await Navigator.pushNamed(context, '/web'); + } } diff --git a/pubspec.lock b/pubspec.lock index 102305b..58342f5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -81,6 +81,11 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" flutter_webview_pro: dependency: "direct main" description: @@ -88,6 +93,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.3" lints: dependency: transitive description: @@ -123,6 +135,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" sky_engine: dependency: transitive description: flutter @@ -177,6 +196,62 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.18" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.14" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.14" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.6" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" vector_math: dependency: transitive description: @@ -186,4 +261,4 @@ packages: version: "2.1.1" sdks: dart: ">=2.14.0 <3.0.0" - flutter: ">=1.22.0" + flutter: ">=2.5.0" diff --git a/pubspec.yaml b/pubspec.yaml index ff10bb1..b3e5078 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -37,6 +37,7 @@ dependencies: #webview_flutter: ^2.3.1 flutter_webview_pro: ^1.0.0 android_intent_plus: ^3.0.2 + url_launcher: ^6.0.18 dev_dependencies: flutter_test: diff --git a/test/widget_test.dart b/test/widget_test.dart deleted file mode 100644 index 6fb8836..0000000 --- a/test/widget_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:comptaplan_app/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp('test', 'test', 'blue')); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -}