Skip to content

Commit

Permalink
Config intent plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
PrimozRatej committed May 27, 2024
1 parent 8ae0586 commit 9459277
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 16 deletions.
4 changes: 2 additions & 2 deletions lib/app_flavored.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:humhub/flavored/models/humhub.f.dart';
import 'package:humhub/flavored/util/intent_plugin.f.dart';
import 'package:humhub/flavored/util/router.f.dart';
import 'package:humhub/util/intent/intent_plugin.dart';
import 'package:humhub/util/loading_provider.dart';
import 'package:humhub/util/notifications/plugin.dart';
import 'package:humhub/util/override_locale.dart';
Expand All @@ -21,7 +21,7 @@ class FlavoredAppState extends ConsumerState<FlavoredApp> {
@override
Widget build(BuildContext context) {
SecureStorageService.clearSecureStorageOnReinstall();
return IntentPlugin(
return IntentPluginF(
child: NotificationPlugin(
child: PushPlugin(
child: OverrideLocale(
Expand Down
137 changes: 137 additions & 0 deletions lib/flavored/util/intent_plugin.f.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:humhub/flavored/util/router.f.dart';
import 'package:humhub/flavored/web_view.f.dart';
import 'package:humhub/util/loading_provider.dart';
import 'package:loggy/loggy.dart';
import 'package:receive_sharing_intent/receive_sharing_intent.dart';
import 'package:uni_links/uni_links.dart';

bool _initialUriIsHandled = false;

class IntentPluginF extends ConsumerStatefulWidget {
final Widget child;

const IntentPluginF({
Key? key,
required this.child,
}) : super(key: key);

@override
IntentPluginFState createState() => IntentPluginFState();
}

class IntentPluginFState extends ConsumerState<IntentPluginF> {
StreamSubscription? intentDataStreamSubscription;
List<SharedMediaFile>? sharedFiles;
Object? _err;
Uri? _initialUri;
Uri? _latestUri;
StreamSubscription? _sub;

@override
void initState() {
logInfo([_err, _initialUri, _latestUri, _sub]);
super.initState();
intentDataStreamSubscription = ReceiveSharingIntent.getMediaStream().listen((List<SharedMediaFile> value) {
setState(() {
sharedFiles = value;
});
});

// For sharing images coming from outside the app while the app is closed
ReceiveSharingIntent.getInitialMedia().then((List<SharedMediaFile> value) {
setState(() {
sharedFiles = value;
});
});
_handleInitialUri();
_handleIncomingLinks();
}

@override
Widget build(BuildContext context) {
return widget.child;
}

/// Handle incoming links - the ones that the app will recieve from the OS
/// while already started.
Future<void> _handleIncomingLinks() async {
if (!kIsWeb) {
// It will handle app links while the app is already started - be it in
// the foreground or in the background.
_sub = uriLinkStream.listen((Uri? uri) async {
if (!mounted) return;
_latestUri = uri;
String? redirectUrl = uri?.toString();
if (redirectUrl != null && navigatorKeyF.currentState != null) {
tryNavigateWithOpener(redirectUrl);
}
_err = null;
}, onError: (err) {
if (kDebugMode) {
print(err);
}
});
}
}

/// Handle the initial Uri - the one the app was started with
///
/// **ATTENTION**: `getInitialLink`/`getInitialUri` should be handled
/// ONLY ONCE in your app's lifetime, since it is not meant to change
/// throughout your app's life.
///
/// We handle all exceptions, since it is called from initState.
Future<void> _handleInitialUri() async {
// In this example app this is an almost useless guard, but it is here to
// show we are not going to call getInitialUri multiple times, even if this
// was a widget that will be disposed of (ex. a navigation route change).

if (!_initialUriIsHandled) {
_initialUriIsHandled = true;
try {
final uri = await getInitialUri();
if (uri == null || !mounted) return;
setState(() => _initialUri = uri);
if (!mounted) {
return;
}
_latestUri = uri;
String? redirectUrl = uri.queryParameters['url'];
if (redirectUrl != null && navigatorKeyF.currentState != null) {
tryNavigateWithOpener(redirectUrl);
} else {
if (redirectUrl != null) {
navigatorKeyF.currentState!.pushNamed(WebViewF.path, arguments: redirectUrl);
return;
}
}
} on PlatformException {
// Platform messages may fail but we ignore the exception
logError('Failed to get initial uri');
} on FormatException catch (err) {
if (!mounted) return;
logError('Malformed initial uri');
setState(() => _err = err);
}
}
}

Future<bool> tryNavigateWithOpener(String redirectUrl) async {
LoadingProvider.of(ref).showLoading();
bool isNewRouteSameAsCurrent = false;
navigatorKeyF.currentState!.popUntil((route) {
if (route.settings.name == WebViewF.path) {
isNewRouteSameAsCurrent = true;
}
return true;
});
navigatorKeyF.currentState!.pushNamed(WebViewF.path, arguments: redirectUrl);
return isNewRouteSameAsCurrent;
}
}
2 changes: 1 addition & 1 deletion lib/pages/opener.dart
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ class OpenerState extends ConsumerState<Opener> with SingleTickerProviderStateMi
await controlLer.initHumHub();
if (controlLer.allOk) {
ref.read(humHubProvider).getInstance().then((value) {
Navigator.pushNamed(ref.context, WebViewApp.path, arguments: value.manifest);
Navigator.pushNamed(ref.context, WebView.path, arguments: value.manifest);
});
}
}
Expand Down
6 changes: 3 additions & 3 deletions lib/pages/web_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';

import '../util/web_view_global_controller.dart';

class WebViewApp extends ConsumerStatefulWidget {
const WebViewApp({super.key});
class WebView extends ConsumerStatefulWidget {
const WebView({super.key});
static const String path = '/web_view';

@override
WebViewAppState createState() => WebViewAppState();
}

class WebViewAppState extends ConsumerState<WebViewApp> {
class WebViewAppState extends ConsumerState<WebView> {
late AuthInAppBrowser authBrowser;
late Manifest manifest;
late URLRequest _initialRequest;
Expand Down
6 changes: 3 additions & 3 deletions lib/util/intent/intent_plugin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class IntentPluginState extends ConsumerState<IntentPlugin> {
if (redirectUrl != null) {
UniversalOpenerController opener = UniversalOpenerController(url: redirectUrl);
await opener.initHumHub();
navigatorKey.currentState!.pushNamed(WebViewApp.path, arguments: opener);
navigatorKey.currentState!.pushNamed(WebView.path, arguments: opener);
return;
}
}
Expand All @@ -129,7 +129,7 @@ class IntentPluginState extends ConsumerState<IntentPlugin> {
LoadingProvider.of(ref).showLoading();
bool isNewRouteSameAsCurrent = false;
navigatorKey.currentState!.popUntil((route) {
if (route.settings.name == WebViewApp.path) {
if (route.settings.name == WebView.path) {
isNewRouteSameAsCurrent = true;
}
return true;
Expand All @@ -138,7 +138,7 @@ class IntentPluginState extends ConsumerState<IntentPlugin> {
await opener.initHumHub();
// Always pop the current instance and init the new one.
LoadingProvider.of(ref).dismissAll();
navigatorKey.currentState!.pushNamed(WebViewApp.path, arguments: opener);
navigatorKey.currentState!.pushNamed(WebView.path, arguments: opener);
return isNewRouteSameAsCurrent;
}
}
Expand Down
8 changes: 4 additions & 4 deletions lib/util/notifications/channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,24 @@ class NotificationChannel {
this.description = 'These notifications are redirect the user to specific url in a payload.'});

/// If the WebView is not opened yet or the app is not running the onTap will wake up the app or redirect to the WebView.
/// If app is already running in WebView mode then the state of [WebViewApp] will be updated with new url.
/// If app is already running in WebView mode then the state of [WebView] will be updated with new url.
///
Future<void> onTap(String? payload) async {
if (payload != null && navigatorKey.currentState != null) {
bool isNewRouteSameAsCurrent = false;
navigatorKey.currentState!.popUntil((route) {
if (route.settings.name == WebViewApp.path) {
if (route.settings.name == WebView.path) {
isNewRouteSameAsCurrent = true;
}
return true;
});
UniversalOpenerController opener = UniversalOpenerController(url: payload);
await opener.initHumHub();
if (isNewRouteSameAsCurrent) {
navigatorKey.currentState!.pushNamed(WebViewApp.path, arguments: opener);
navigatorKey.currentState!.pushNamed(WebView.path, arguments: opener);
return;
}
navigatorKey.currentState!.pushNamed(WebViewApp.path, arguments: opener);
navigatorKey.currentState!.pushNamed(WebView.path, arguments: opener);
} else {
if (payload != null) {
InitFromPush.setPayload(payload);
Expand Down
6 changes: 3 additions & 3 deletions lib/util/router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class MyRouter {

static var routes = {
Opener.path: (context) => const Opener(),
WebViewApp.path: (context) => const WebViewApp(),
WebView.path: (context) => const WebView(),
'/help': (context) => Platform.isAndroid ? const HelpAndroid() : const HelpIos(),
};

Expand All @@ -46,9 +46,9 @@ class MyRouter {
initRoute = Opener.path;
return Opener.path;
case RedirectAction.webView:
initRoute = WebViewApp.path;
initRoute = WebView.path;
initParams = humhub.manifest;
return WebViewApp.path;
return WebView.path;
}
}
}
Expand Down

0 comments on commit 9459277

Please sign in to comment.