Skip to content

Commit

Permalink
deeplinks
Browse files Browse the repository at this point in the history
  • Loading branch information
leo-lox committed Nov 24, 2024
1 parent 72afffd commit 49754dd
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 57 deletions.
16 changes: 14 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</intent-filter>

<!-- deep links -->
<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" />
Expand All @@ -36,12 +36,24 @@
<data android:scheme="nostr" />
<data android:scheme="camelus" />


</intent-filter>

<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />


<!-- with verification -->
<data android:scheme="https" android:host="camelus.app" />
<data android:scheme="https" android:host="www.camelus.app" android:pathPrefix="/i"/>
<data android:scheme="https" android:host="camelus.app" android:pathPrefix="/i"/>


</intent-filter>

<meta-data android:name="flutter_deeplinking_enabled" android:value="false" />

</activity>

<!-- enable impeller -->
Expand Down
148 changes: 104 additions & 44 deletions lib/deep_links.dart
Original file line number Diff line number Diff line change
@@ -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<NavigatorState> navigatorKey}) {
void listenDeeplinks({
required GlobalKey<NavigatorState> 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<void> _camelusLinks({
required String link,
required GlobalKey<NavigatorState> navigatorKey,
required ProviderContainer providerContainer,
}) async {
final myMatch = link.replaceAll("https://camelus.app", "");

Map<String, dynamic> nProfileDecode =
NprofileHelper().bech32toMap(myMatch);
if (myMatch.startsWith("/i/")) {
final List<String> myMatchSplit = myMatch.split("/");
final String invitedBy = myMatchSplit[2];
final String inviteListName = myMatchSplit[3];

final List<String> 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<NavigatorState> 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<String, dynamic> nProfileDecode = NprofileHelper().bech32toMap(myMatch);

final List<String> 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({
Expand Down
6 changes: 6 additions & 0 deletions lib/domain_layer/entities/onboarding_user_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ class OnboardingUserInfo {
String lud06 = '';
String lud16 = '';

// if invited by someone
String? invitedByPubkey = '';
String? inviteListName = '';

OnboardingUserInfo({
this.name,
this.picture,
Expand All @@ -27,5 +31,7 @@ class OnboardingUserInfo {
this.lud06 = '',
this.lud16 = '',
required this.keyPair,
this.invitedByPubkey,
this.inviteListName,
});
}
1 change: 1 addition & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Future<void> main() async {

listenDeeplinks(
navigatorKey: navigatorKey,
providerContainer: providerContainer,
);

runApp(
Expand Down
16 changes: 5 additions & 11 deletions lib/presentation_layer/routes/nostr/onboarding/onboarding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -155,7 +149,7 @@ class _NostrOnboardingState extends ConsumerState<NostrOnboarding>
controller: _tabController,
physics: pageLock ? const NeverScrollableScrollPhysics() : null,
children: [
if (widget.invitedByPubkey == null)
if (signUpInfo.invitedByPubkey == null)
OnboardingPage01(
loginCallback: _navigateToLogin,
registerCallback: () {
Expand All @@ -166,14 +160,14 @@ class _NostrOnboardingState extends ConsumerState<NostrOnboarding>
);
},
),
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,
Expand All @@ -194,7 +188,7 @@ class _NostrOnboardingState extends ConsumerState<NostrOnboarding>
signUpInfo: signUpInfo,
),
OnboardingStarterPack(
invitedByPubkey: widget.invitedByPubkey,
invitedByPubkey: signUpInfo.invitedByPubkey,
submitCallback: (followPubkeys) {
signUpInfo.followPubkeys = followPubkeys;
_nextTab();
Expand Down

0 comments on commit 49754dd

Please sign in to comment.