From 49754dd3be8550a8ecc2e95fc08d7246720b3cea Mon Sep 17 00:00:00 2001 From: LeoLox <58687994+leo-lox@users.noreply.github.com> Date: Sun, 24 Nov 2024 19:48:48 +0100 Subject: [PATCH] deeplinks --- android/app/src/main/AndroidManifest.xml | 16 +- lib/deep_links.dart | 148 ++++++++++++------ .../entities/onboarding_user_info.dart | 6 + lib/main.dart | 1 + .../routes/nostr/onboarding/onboarding.dart | 16 +- 5 files changed, 130 insertions(+), 57 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 0ffee50..e913d31 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -26,7 +26,7 @@ - + @@ -36,12 +36,24 @@ + + + + + + + + + - + + + + diff --git a/lib/deep_links.dart b/lib/deep_links.dart index 7145c72..3883b0a 100644 --- a/lib/deep_links.dart +++ b/lib/deep_links.dart @@ -1,69 +1,129 @@ +import 'dart:async'; + import 'package:app_links/app_links.dart'; import 'package:flutter/material.dart'; +import 'package:riverpod/riverpod.dart'; +import 'domain_layer/usecases/app_auth.dart'; import 'helpers/helpers.dart'; import 'helpers/nevent_helper.dart'; import 'helpers/nprofile_helper.dart'; +import 'presentation_layer/providers/onboarding_provider.dart'; /// sets up links listener //todo: fetch the notes with inbox/outbox first then navigate to the note -void listenDeeplinks({required GlobalKey navigatorKey}) { +void listenDeeplinks({ + required GlobalKey navigatorKey, + required ProviderContainer providerContainer, +}) { final appLinks = AppLinks(); // AppLinks is singleton // Subscribe to all events (initial link and further) - final sub = appLinks.uriLinkStream.listen((uri) { - final myMatch = uri.toString().replaceAll("nostr:", ""); - String myPubkeyHex = ""; + final sub = appLinks.uriLinkStream.listen((uri) async { + final uriString = uri.toString(); + print("uriString ${uriString}"); + if (uriString.startsWith("nostr:")) { + _nostrLinks( + link: uriString, + navigatorKey: navigatorKey, + ); + } else if (uriString.startsWith("https://camelus.app")) { + await _camelusLinks( + link: uriString, + navigatorKey: navigatorKey, + providerContainer: providerContainer, + ); + } + }); +} - if (myMatch.contains("nprofile")) { - // remove the "nostr:" part +Future _camelusLinks({ + required String link, + required GlobalKey navigatorKey, + required ProviderContainer providerContainer, +}) async { + final myMatch = link.replaceAll("https://camelus.app", ""); - Map nProfileDecode = - NprofileHelper().bech32toMap(myMatch); + if (myMatch.startsWith("/i/")) { + final List myMatchSplit = myMatch.split("/"); + final String invitedBy = myMatchSplit[2]; + final String inviteListName = myMatchSplit[3]; - final List myRelays = nProfileDecode['relays']; - myPubkeyHex = nProfileDecode['pubkey']; + /// check if account already setup + final mySigner = await AppAuth.getEventSigner(); - _pushProfile( - pubkey: myPubkeyHex, - navigatorKey: navigatorKey, - ); - } else if (myMatch.contains("npub")) { - final List decode = Helpers().decodeBech32(myMatch); + if (mySigner != null) { + print("account already setup"); + return; + } - myPubkeyHex = decode[0]; + final provider = providerContainer.read(onboardingProvider); + provider.signUpInfo.invitedByPubkey = invitedBy; + provider.signUpInfo.inviteListName = inviteListName; - _pushProfile( - pubkey: myPubkeyHex, - navigatorKey: navigatorKey, - ); - } else if (myMatch.contains("note1")) { - final decode = Helpers().decodeBech32(myMatch); - final String hr = decode[0]; - final String noteId = decode[1]; - if (noteId.isEmpty) { - return; - } - _pushNote( - noteId: noteId, - navigatorKey: navigatorKey, - ); - } else if (myMatch.contains("nevent")) { - final map = NeventHelper().bech32ToMap(myMatch); - final String eventId = map['eventId']; - final String authorPubkey = map['authorPubkey']; + // to update state + navigatorKey.currentState?.pushReplacementNamed( + "/onboarding", + ); + } else { + print("camelus link not supported ${link}"); + } +} + +_nostrLinks({ + required String link, + required GlobalKey navigatorKey, +}) { + final myMatch = link.replaceAll("nostr:", ""); + String myPubkeyHex = ""; - if (eventId.isEmpty) { - return; - } + if (myMatch.contains("nprofile")) { + // remove the "nostr:" part - _pushNote( - noteId: eventId, - navigatorKey: navigatorKey, - ); + Map nProfileDecode = NprofileHelper().bech32toMap(myMatch); + + final List myRelays = nProfileDecode['relays']; + myPubkeyHex = nProfileDecode['pubkey']; + + _pushProfile( + pubkey: myPubkeyHex, + navigatorKey: navigatorKey, + ); + } else if (myMatch.contains("npub")) { + final List decode = Helpers().decodeBech32(myMatch); + + myPubkeyHex = decode[0]; + + _pushProfile( + pubkey: myPubkeyHex, + navigatorKey: navigatorKey, + ); + } else if (myMatch.contains("note1")) { + final decode = Helpers().decodeBech32(myMatch); + final String hr = decode[0]; + final String noteId = decode[1]; + if (noteId.isEmpty) { + return; } - }); + _pushNote( + noteId: noteId, + navigatorKey: navigatorKey, + ); + } else if (myMatch.contains("nevent")) { + final map = NeventHelper().bech32ToMap(myMatch); + final String eventId = map['eventId']; + final String authorPubkey = map['authorPubkey']; + + if (eventId.isEmpty) { + return; + } + + _pushNote( + noteId: eventId, + navigatorKey: navigatorKey, + ); + } } _pushProfile({ diff --git a/lib/domain_layer/entities/onboarding_user_info.dart b/lib/domain_layer/entities/onboarding_user_info.dart index 64b672a..7a0d053 100644 --- a/lib/domain_layer/entities/onboarding_user_info.dart +++ b/lib/domain_layer/entities/onboarding_user_info.dart @@ -15,6 +15,10 @@ class OnboardingUserInfo { String lud06 = ''; String lud16 = ''; + // if invited by someone + String? invitedByPubkey = ''; + String? inviteListName = ''; + OnboardingUserInfo({ this.name, this.picture, @@ -27,5 +31,7 @@ class OnboardingUserInfo { this.lud06 = '', this.lud16 = '', required this.keyPair, + this.invitedByPubkey, + this.inviteListName, }); } diff --git a/lib/main.dart b/lib/main.dart index e03acf3..1d66909 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -74,6 +74,7 @@ Future main() async { listenDeeplinks( navigatorKey: navigatorKey, + providerContainer: providerContainer, ); runApp( diff --git a/lib/presentation_layer/routes/nostr/onboarding/onboarding.dart b/lib/presentation_layer/routes/nostr/onboarding/onboarding.dart index 8d50db5..5aeb60b 100644 --- a/lib/presentation_layer/routes/nostr/onboarding/onboarding.dart +++ b/lib/presentation_layer/routes/nostr/onboarding/onboarding.dart @@ -14,14 +14,8 @@ import 'onboarding_profile.dart'; import 'onboarding_starter_pack.dart'; class NostrOnboarding extends ConsumerStatefulWidget { - final String? invitedByPubkey; - final String? inviteListName; - const NostrOnboarding({ super.key, - this.invitedByPubkey = - "717ff238f888273f5d5ee477097f2b398921503769303a0c518d06a952f2a75e", // test - this.inviteListName = "news organizations", }); @override @@ -155,7 +149,7 @@ class _NostrOnboardingState extends ConsumerState controller: _tabController, physics: pageLock ? const NeverScrollableScrollPhysics() : null, children: [ - if (widget.invitedByPubkey == null) + if (signUpInfo.invitedByPubkey == null) OnboardingPage01( loginCallback: _navigateToLogin, registerCallback: () { @@ -166,14 +160,14 @@ class _NostrOnboardingState extends ConsumerState ); }, ), - if (widget.invitedByPubkey != null) + if (signUpInfo.invitedByPubkey != null) OnboardingInvitedBy( nextCallback: () { _nextTab(); }, userInfo: signUpInfo, - invitedByPubkey: widget.invitedByPubkey!, - inviteListName: widget.inviteListName!, + invitedByPubkey: signUpInfo.invitedByPubkey!, + inviteListName: signUpInfo.inviteListName!, ), OnboardingName( userInfo: signUpInfo, @@ -194,7 +188,7 @@ class _NostrOnboardingState extends ConsumerState signUpInfo: signUpInfo, ), OnboardingStarterPack( - invitedByPubkey: widget.invitedByPubkey, + invitedByPubkey: signUpInfo.invitedByPubkey, submitCallback: (followPubkeys) { signUpInfo.followPubkeys = followPubkeys; _nextTab();