pubspec.yaml : add flushbar dependencie | lib : delete HomeLog.dart, add endi.dart (start only if deeplink is clicked), add bloc.dart (manage deeplink fonctionnality) | ios/Runner/info.plist : add endi URIs | android/app/src/main/AndroidManifest.xml : add endi URIs | android/app/src/main/kotlin/fr.astrolabe.astronote_app/MainActivity.kt : update to manage deeplink fonctionnality
This commit is contained in:
parent
4576c7898b
commit
355b71d775
@ -1,6 +1,69 @@
|
|||||||
package fr.astrolabe.astronote_app
|
package fr.astrolabe.astronote_app
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import androidx.annotation.NonNull
|
||||||
import io.flutter.embedding.android.FlutterActivity
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
|
import io.flutter.embedding.engine.FlutterEngine
|
||||||
|
import io.flutter.plugin.common.EventChannel
|
||||||
|
import io.flutter.plugin.common.EventChannel.EventSink
|
||||||
|
import io.flutter.plugin.common.MethodChannel
|
||||||
|
import io.flutter.plugins.GeneratedPluginRegistrant
|
||||||
|
|
||||||
class MainActivity: FlutterActivity() {
|
class MainActivity : FlutterActivity() {
|
||||||
|
|
||||||
|
private val CHANNEL = "https://demo.endi.coop"
|
||||||
|
private val EVENTS = "https://demo.endi.coop/login?nextpage=%2F"
|
||||||
|
private var startString: String? = null
|
||||||
|
private var linksReceiver: BroadcastReceiver? = null
|
||||||
|
|
||||||
|
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
|
||||||
|
GeneratedPluginRegistrant.registerWith(flutterEngine)
|
||||||
|
|
||||||
|
MethodChannel(flutterEngine.dartExecutor, CHANNEL).setMethodCallHandler { call, result ->
|
||||||
|
if (call.method == "initialLink") {
|
||||||
|
if (startString != null) {
|
||||||
|
result.success(startString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EventChannel(flutterEngine.dartExecutor, EVENTS).setStreamHandler(
|
||||||
|
object : EventChannel.StreamHandler {
|
||||||
|
override fun onListen(args: Any?, events: EventSink) {
|
||||||
|
linksReceiver = createChangeReceiver(events)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCancel(args: Any?) {
|
||||||
|
linksReceiver = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
val intent = getIntent()
|
||||||
|
startString = intent.data?.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNewIntent(intent: Intent) {
|
||||||
|
super.onNewIntent(intent)
|
||||||
|
if (intent.action === Intent.ACTION_VIEW) {
|
||||||
|
linksReceiver?.onReceive(this.applicationContext, intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createChangeReceiver(events: EventSink): BroadcastReceiver? {
|
||||||
|
return object : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) { // assuming intent.getAction() is Intent.ACTION_VIEW
|
||||||
|
val dataString = intent.dataString
|
||||||
|
?: events.error("UNAVAILABLE", "Link unavailable", null)
|
||||||
|
events.success(dataString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,5 +41,9 @@
|
|||||||
</array>
|
</array>
|
||||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
<false/>
|
<false/>
|
||||||
|
<key>com.apple.developer.associated-domains</key>
|
||||||
|
<array>
|
||||||
|
<string>applinks:demo.endi.coop</string>
|
||||||
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
48
lib/bloc.dart
Normal file
48
lib/bloc.dart
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
abstract class Bloc {
|
||||||
|
void dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
class DeepLinkBloc extends Bloc {
|
||||||
|
//Event Channel creation
|
||||||
|
static const stream =
|
||||||
|
const EventChannel('https://demo.endi.coop/login?nextpage=%2F');
|
||||||
|
|
||||||
|
//Method channel creation
|
||||||
|
static const platform = const MethodChannel('https://demo.endi.coop');
|
||||||
|
|
||||||
|
StreamController<String> _stateController = StreamController();
|
||||||
|
|
||||||
|
Stream<String> get state => _stateController.stream;
|
||||||
|
|
||||||
|
Sink<String> get stateSink => _stateController.sink;
|
||||||
|
|
||||||
|
//Adding the listener into contructor
|
||||||
|
DeepLinkBloc() {
|
||||||
|
//Checking application start by deep link
|
||||||
|
startUri().then(_onRedirected);
|
||||||
|
//Checking broadcast stream, if deep link was clicked in opened appication
|
||||||
|
stream.receiveBroadcastStream().listen((d) => _onRedirected(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
_onRedirected(String uri) {
|
||||||
|
// Throw deep link URI into the BloC's stream
|
||||||
|
stateSink.add(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_stateController.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String> startUri() async {
|
||||||
|
try {
|
||||||
|
return platform.invokeMethod('initialLink');
|
||||||
|
} on PlatformException catch (e) {
|
||||||
|
return "Failed to Invoke: '${e.message}'.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,48 +1,57 @@
|
|||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'bloc.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
import 'package:flushbar/flushbar.dart';
|
||||||
|
|
||||||
class HomeLog extends StatefulWidget {
|
class EndiLog extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_HomeLogState createState() => _HomeLogState();
|
_EndiLogState createState() => _EndiLogState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _HomeLogState extends State<HomeLog> {
|
class _EndiLogState extends State<EndiLog> {
|
||||||
TextStyle style = TextStyle(fontFamily: 'Varela Round', fontSize: 20.0);
|
TextStyle style = TextStyle(fontFamily: 'Varela Round', fontSize: 20.0);
|
||||||
final GlobalKey<ScaffoldState> _globalKey = GlobalKey<ScaffoldState>();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
DeepLinkBloc _bloc = Provider.of<DeepLinkBloc>(context);
|
||||||
key: _globalKey,
|
return StreamBuilder<String>(
|
||||||
body: SingleChildScrollView(
|
stream: _bloc.state,
|
||||||
child: Container(
|
builder: (context, snapshot) {
|
||||||
height: MediaQuery.of(context).size.height,
|
if (!snapshot.hasData) {
|
||||||
color: Colors.white,
|
return Container(
|
||||||
child: Padding(
|
child: Center(child: Text('No deep link was used ')));
|
||||||
padding: EdgeInsets.all(50),
|
} else {
|
||||||
child: Column(
|
return SingleChildScrollView(
|
||||||
children: <Widget>[
|
child: Container(
|
||||||
SizedBox(height: 40),
|
height: MediaQuery.of(context).size.height,
|
||||||
_logoApp(),
|
color: Colors.white,
|
||||||
_titleApp(),
|
child: Padding(
|
||||||
SizedBox(height: 90),
|
padding: EdgeInsets.all(50),
|
||||||
_emailField(),
|
child: Column(
|
||||||
SizedBox(height: 30),
|
children: <Widget>[
|
||||||
_passwordField(),
|
// SizedBox(height: 40),
|
||||||
SizedBox(height: 50),
|
_logoApp(),
|
||||||
_logButton(),
|
_titleApp(),
|
||||||
SizedBox(height: 70),
|
SizedBox(height: 80),
|
||||||
_enDIUrl(),
|
_emailField(),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 30),
|
||||||
_astrolabeUrl()
|
_passwordField(),
|
||||||
],
|
SizedBox(height: 50),
|
||||||
),
|
_logButton(),
|
||||||
),
|
SizedBox(height: 70),
|
||||||
),
|
_enDIUrl(),
|
||||||
),
|
SizedBox(height: 5),
|
||||||
);
|
_astrolabeUrl()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _logoApp() {
|
Widget _logoApp() {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: 100.0,
|
height: 100.0,
|
||||||
@ -67,7 +76,7 @@ class _HomeLogState extends State<HomeLog> {
|
|||||||
contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
|
contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
|
||||||
labelText: "E-mail",
|
labelText: "E-mail",
|
||||||
border:
|
border:
|
||||||
OutlineInputBorder(borderRadius: BorderRadius.circular(32.0))),
|
OutlineInputBorder(borderRadius: BorderRadius.circular(32.0))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +88,7 @@ class _HomeLogState extends State<HomeLog> {
|
|||||||
contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
|
contentPadding: EdgeInsets.fromLTRB(20.0, 15.0, 20.0, 15.0),
|
||||||
labelText: "Mot de passe",
|
labelText: "Mot de passe",
|
||||||
border:
|
border:
|
||||||
OutlineInputBorder(borderRadius: BorderRadius.circular(32.0))),
|
OutlineInputBorder(borderRadius: BorderRadius.circular(32.0))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,18 +108,22 @@ class _HomeLogState extends State<HomeLog> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void showErrorFlushbar(BuildContext context) {
|
||||||
|
Flushbar(
|
||||||
|
message: "Impossible d'ouvrir le lien",
|
||||||
|
backgroundColor: Colors.red[300],
|
||||||
|
duration: Duration(seconds: 3),
|
||||||
|
// Show it with a cascading operator
|
||||||
|
)..show(context);
|
||||||
|
}
|
||||||
|
|
||||||
void _launchLinkEnDI() async {
|
void _launchLinkEnDI() async {
|
||||||
const url = "https://endi.coop";
|
const url = "https://endi.coop";
|
||||||
|
|
||||||
if (await canLaunch(url)) {
|
if (await canLaunch(url)) {
|
||||||
await launch(url);
|
await launch(url);
|
||||||
} else {
|
} else {
|
||||||
final snack = SnackBar(
|
showErrorFlushbar(context);
|
||||||
content: Text("Impossible de lancer le lien"),
|
|
||||||
duration: Duration(seconds: 4),
|
|
||||||
backgroundColor: Colors.red[300],
|
|
||||||
);
|
|
||||||
_globalKey.currentState.showSnackBar(snack);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,12 +133,7 @@ class _HomeLogState extends State<HomeLog> {
|
|||||||
if (await canLaunch(url)) {
|
if (await canLaunch(url)) {
|
||||||
await launch(url);
|
await launch(url);
|
||||||
} else {
|
} else {
|
||||||
final snack = SnackBar(
|
showErrorFlushbar(context);
|
||||||
content: Text("Impossible de lancer le lien"),
|
|
||||||
duration: Duration(seconds: 4),
|
|
||||||
backgroundColor: Colors.red[300],
|
|
||||||
);
|
|
||||||
_globalKey.currentState.showSnackBar(snack);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,5 +162,4 @@ class _HomeLogState extends State<HomeLog> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'views/HomeLog.dart';
|
import 'bloc.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'endi.dart';
|
||||||
|
|
||||||
void main() => runApp(MyApp());
|
void main() => runApp(MyApp());
|
||||||
|
|
||||||
@ -7,11 +9,14 @@ class MyApp extends StatelessWidget {
|
|||||||
// This widget is the root of your application.
|
// This widget is the root of your application.
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
DeepLinkBloc _bloc = DeepLinkBloc();
|
||||||
|
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
home: HomeLog(),
|
debugShowCheckedModeBanner: false,
|
||||||
debugShowCheckedModeBanner: false,
|
home: Scaffold(
|
||||||
);
|
body: Provider<DeepLinkBloc>(
|
||||||
|
create: (context) => _bloc,
|
||||||
|
dispose: (context, bloc) => bloc.dispose(),
|
||||||
|
child: EndiLog())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,13 +64,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.3"
|
version: "0.1.3"
|
||||||
email_validator:
|
flushbar:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: email_validator
|
name: flushbar
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.5"
|
version: "1.10.4"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -267,5 +267,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.6.1"
|
version: "3.6.1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.7.0 <3.0.0"
|
dart: ">=2.7.2 <3.0.0"
|
||||||
flutter: ">=1.16.0 <2.0.0"
|
flutter: ">=1.16.0 <2.0.0"
|
||||||
|
@ -24,7 +24,7 @@ dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
provider: ^4.3.1
|
provider: ^4.3.1
|
||||||
email_validator: '^1.0.0'
|
flushbar: ^1.10.4
|
||||||
url_launcher: ^5.5.0
|
url_launcher: ^5.5.0
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
|
Loading…
Reference in New Issue
Block a user