Handle matrix.to links

This commit is contained in:
Christian Pauly 2020-01-19 19:28:12 +01:00
parent b386e1b9a4
commit 4f4e3a4df5
6 changed files with 116 additions and 3 deletions

View file

@ -28,6 +28,23 @@
<action android:name="FLUTTER_NOTIFICATION_CLICK" /> <action android:name="FLUTTER_NOTIFICATION_CLICK" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="matrix.to"/>
</intent-filter>
<!--TODO: Add this filter, if you want to support sharing text into your app-->
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
</intent-filter>
</activity> </activity>
<!-- Don't delete the meta-data below. <!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->

View file

@ -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)),
);
}
}
}
}

View file

@ -13,9 +13,9 @@ import 'package:fluffychat/utils/room_state_enums_extensions.dart';
import 'package:fluffychat/views/chat_list.dart'; import 'package:fluffychat/views/chat_list.dart';
import 'package:fluffychat/views/invitation_selection.dart'; import 'package:fluffychat/views/invitation_selection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:link_text/link_text.dart'; import 'package:link_text/link_text.dart';
import 'package:share/share.dart';
import 'package:toast/toast.dart'; import 'package:toast/toast.dart';
class ChatDetails extends StatefulWidget { class ChatDetails extends StatefulWidget {
@ -157,8 +157,13 @@ class _ChatDetailsState extends State<ChatDetails> {
if (widget.room.canonicalAlias?.isNotEmpty ?? false) if (widget.room.canonicalAlias?.isNotEmpty ?? false)
IconButton( IconButton(
icon: Icon(Icons.share), icon: Icon(Icons.share),
onPressed: () => Share.share( onPressed: () {
"https://matrix.to/#/${widget.room.canonicalAlias}"), Clipboard.setData(
ClipboardData(text: widget.room.canonicalAlias),
);
Toast.show("Invitation link copied to clipboard", context,
duration: 5);
},
), ),
ChatSettingsPopupMenu(widget.room, false) ChatSettingsPopupMenu(widget.room, false)
], ],
@ -209,6 +214,7 @@ class _ChatDetailsState extends State<ChatDetails> {
text: widget.room.topic?.isEmpty ?? true text: widget.room.topic?.isEmpty ?? true
? "Add a group description" ? "Add a group description"
: widget.room.topic, : widget.room.topic,
linkStyle: TextStyle(color: Colors.blueAccent),
textStyle: TextStyle( textStyle: TextStyle(
fontSize: 14, fontSize: 14,
color: Colors.black, color: Colors.black,

View file

@ -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/list_items/chat_list_item.dart';
import 'package:fluffychat/components/matrix.dart'; import 'package:fluffychat/components/matrix.dart';
import 'package:fluffychat/utils/app_route.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/archive.dart';
import 'package:fluffychat/views/settings.dart'; import 'package:fluffychat/views/settings.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.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 } enum SelectMode { normal, multi_select, share }
@ -57,15 +59,40 @@ class _ChatListState extends State<ChatList> {
searchController.addListener( searchController.addListener(
() => setState(() => null), () => setState(() => null),
); );
getSharedData();
super.initState(); 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 @override
void dispose() { void dispose() {
sub?.cancel(); sub?.cancel();
searchController.removeListener( searchController.removeListener(
() => setState(() => null), () => setState(() => null),
); );
_intentDataStreamSubscription?.cancel();
super.dispose(); super.dispose();
} }

View file

@ -263,6 +263,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.0.5" 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: share:
dependency: "direct main" dependency: "direct main"
description: description:

View file

@ -45,6 +45,7 @@ dependencies:
path_provider: ^1.5.1 path_provider: ^1.5.1
webview_flutter: ^0.3.19+4 webview_flutter: ^0.3.19+4
share: ^0.6.3+5 share: ^0.6.3+5
receive_sharing_intent: ^1.3.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: