diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 3aa394f77..d23cce259 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -28,6 +28,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/utils/url_launcher.dart b/lib/utils/url_launcher.dart
new file mode 100644
index 000000000..81555bdc1
--- /dev/null
+++ b/lib/utils/url_launcher.dart
@@ -0,0 +1,55 @@
+import 'package:famedlysdk/famedlysdk.dart';
+import 'package:fluffychat/components/matrix.dart';
+import 'package:fluffychat/utils/app_route.dart';
+import 'package:fluffychat/views/chat.dart';
+import 'package:flutter/material.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+class UrlLauncher {
+ final String url;
+ final BuildContext context;
+ const UrlLauncher(this.context, this.url);
+
+ void launchUrl() {
+ print("Open url: $url");
+ if (url.startsWith("https://matrix.to/#/")) {
+ return openMatrixToUrl();
+ }
+ launch(url);
+ }
+
+ void openMatrixToUrl() async {
+ final matrix = Matrix.of(context);
+ final String identifier = url.replaceAll("https://matrix.to/#/", "");
+ if (identifier.substring(0, 1) == "#") {
+ print("Join room ${Uri.encodeFull(identifier)}");
+ final response = await matrix.tryRequestWithLoadingDialog(
+ matrix.client.joinRoomById(
+ Uri.encodeComponent(identifier),
+ ),
+ );
+ if (response == false) return;
+ await Navigator.pushAndRemoveUntil(
+ context,
+ AppRoute.defaultRoute(context, Chat(response["room_id"])),
+ (r) => r.isFirst,
+ );
+ } else if (identifier.substring(0, 1) == "@") {
+ print("Start chat with user $identifier");
+ final User user = User(
+ identifier,
+ room: Room(id: "", client: matrix.client),
+ );
+ final String roomID =
+ await matrix.tryRequestWithLoadingDialog(user.startDirectChat());
+ Navigator.of(context).pop();
+
+ if (roomID != null) {
+ await Navigator.push(
+ context,
+ MaterialPageRoute(builder: (context) => Chat(roomID)),
+ );
+ }
+ }
+ }
+}
diff --git a/lib/views/chat_details.dart b/lib/views/chat_details.dart
index de87889e1..5cdc38119 100644
--- a/lib/views/chat_details.dart
+++ b/lib/views/chat_details.dart
@@ -13,9 +13,9 @@ import 'package:fluffychat/utils/room_state_enums_extensions.dart';
import 'package:fluffychat/views/chat_list.dart';
import 'package:fluffychat/views/invitation_selection.dart';
import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:link_text/link_text.dart';
-import 'package:share/share.dart';
import 'package:toast/toast.dart';
class ChatDetails extends StatefulWidget {
@@ -157,8 +157,13 @@ class _ChatDetailsState extends State {
if (widget.room.canonicalAlias?.isNotEmpty ?? false)
IconButton(
icon: Icon(Icons.share),
- onPressed: () => Share.share(
- "https://matrix.to/#/${widget.room.canonicalAlias}"),
+ onPressed: () {
+ Clipboard.setData(
+ ClipboardData(text: widget.room.canonicalAlias),
+ );
+ Toast.show("Invitation link copied to clipboard", context,
+ duration: 5);
+ },
),
ChatSettingsPopupMenu(widget.room, false)
],
@@ -209,6 +214,7 @@ class _ChatDetailsState extends State {
text: widget.room.topic?.isEmpty ?? true
? "Add a group description"
: widget.room.topic,
+ linkStyle: TextStyle(color: Colors.blueAccent),
textStyle: TextStyle(
fontSize: 14,
color: Colors.black,
diff --git a/lib/views/chat_list.dart b/lib/views/chat_list.dart
index 26f85efbb..5b904645b 100644
--- a/lib/views/chat_list.dart
+++ b/lib/views/chat_list.dart
@@ -7,10 +7,12 @@ import 'package:fluffychat/components/dialogs/new_private_chat_dialog.dart';
import 'package:fluffychat/components/list_items/chat_list_item.dart';
import 'package:fluffychat/components/matrix.dart';
import 'package:fluffychat/utils/app_route.dart';
+import 'package:fluffychat/utils/url_launcher.dart';
import 'package:fluffychat/views/archive.dart';
import 'package:fluffychat/views/settings.dart';
import 'package:flutter/material.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
+import 'package:receive_sharing_intent/receive_sharing_intent.dart';
enum SelectMode { normal, multi_select, share }
@@ -57,15 +59,40 @@ class _ChatListState extends State {
searchController.addListener(
() => setState(() => null),
);
+ getSharedData();
super.initState();
}
+ StreamSubscription _intentDataStreamSubscription;
+
+ void processSharedText(String text) {
+ if (text.startsWith("https://matrix.to/#/")) {
+ UrlLauncher(context, text).openMatrixToUrl();
+ } else {
+ setState(() => Matrix.of(context).shareContent = {
+ "msgtype": "m.text",
+ "body": text,
+ });
+ }
+ }
+
+ void getSharedData() {
+ // For sharing or opening urls/text coming from outside the app while the app is in the memory
+ _intentDataStreamSubscription = ReceiveSharingIntent.getTextStream()
+ .listen(processSharedText, onError: (err) {
+ print("getLinkStream error: $err");
+ });
+ // For sharing or opening urls/text coming from outside the app while the app is closed
+ ReceiveSharingIntent.getInitialText().then(processSharedText);
+ }
+
@override
void dispose() {
sub?.cancel();
searchController.removeListener(
() => setState(() => null),
);
+ _intentDataStreamSubscription?.cancel();
super.dispose();
}
diff --git a/pubspec.lock b/pubspec.lock
index 391520650..e582c26a6 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -263,6 +263,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.5"
+ receive_sharing_intent:
+ dependency: "direct main"
+ description:
+ name: receive_sharing_intent
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.3.2"
share:
dependency: "direct main"
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 2e1d83510..d81f6cf5e 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -45,6 +45,7 @@ dependencies:
path_provider: ^1.5.1
webview_flutter: ^0.3.19+4
share: ^0.6.3+5
+ receive_sharing_intent: ^1.3.2
dev_dependencies:
flutter_test: