Skip to content

Commit 7712f07

Browse files
authored
feat(invite): add custom invite sheet with targeted messaging intents (#788)
Replace system share sheet for contact invites with a WrapContentSheet showing SMS, WhatsApp (if installed), and More options. SMS and WhatsApp get targeted intents with pre-filled recipient and message. Extract invite logic into shared/invite module with InviteController and feature/invite module for the UI. Centralize messaging package names in MessagingPackages. Signed-off-by: Brandon McAnsh <git@bmcreations.dev>
1 parent e790195 commit 7712f07

20 files changed

Lines changed: 432 additions & 5 deletions

File tree

apps/flipcash/app/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ dependencies {
161161
implementation(project(":apps:flipcash:shared:permissions"))
162162
implementation(project(":apps:flipcash:shared:phone"))
163163
implementation(project(":apps:flipcash:shared:shareable"))
164+
implementation(project(":apps:flipcash:shared:invite"))
164165
implementation(project(":apps:flipcash:shared:tokens"))
165166
implementation(project(":apps:flipcash:shared:web"))
166167
implementation(project(":apps:flipcash:shared:workers"))
@@ -186,6 +187,7 @@ dependencies {
186187
implementation(project(":apps:flipcash:features:bill-customization"))
187188
implementation(project(":apps:flipcash:features:currency-creator"))
188189
implementation(project(":apps:flipcash:features:direct-send"))
190+
implementation(project(":apps:flipcash:features:invite"))
189191
implementation(project(":apps:flipcash:features:discovery"))
190192
implementation(project(":apps:flipcash:features:userflags"))
191193

apps/flipcash/app/src/main/AndroidManifest.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,23 @@
2626
<action android:name="android.intent.action.VIEW" />
2727
<data android:host="phantom.app" />
2828
</intent>
29+
30+
<intent>
31+
<action android:name="android.intent.action.MAIN" />
32+
<category android:name="android.intent.category.APP_MESSAGING" />
33+
</intent>
34+
35+
<intent>
36+
<action android:name="android.intent.action.SENDTO" />
37+
<data android:scheme="smsto" />
38+
</intent>
39+
40+
<!-- Messaging apps for invite share sheet filtering -->
41+
<package android:name="com.whatsapp" />
42+
<package android:name="com.whatsapp.w4b" />
43+
<package android:name="org.thoughtcrime.securesms" />
44+
<package android:name="org.telegram.messenger" />
45+
<package android:name="com.facebook.orca" />
2946
</queries>
3047

3148
<application

apps/flipcash/app/src/main/kotlin/com/flipcash/app/MainActivity.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import com.flipcash.app.router.LocalRouter
3232
import com.flipcash.app.router.Router
3333
import com.flipcash.app.session.LocalSessionController
3434
import com.flipcash.app.session.SessionController
35+
import com.flipcash.app.invite.InviteController
36+
import com.flipcash.app.invite.LocalInviteController
3537
import com.flipcash.app.shareable.LocalShareController
3638
import com.flipcash.app.shareable.ShareSheetController
3739
import com.flipcash.app.updates.AppUpdateController
@@ -96,6 +98,9 @@ class MainActivity : FragmentActivity() {
9698
@Inject
9799
lateinit var shareController: ShareSheetController
98100

101+
@Inject
102+
lateinit var inviteController: InviteController
103+
99104
@Inject
100105
lateinit var appSettingsCoordinator: AppSettingsCoordinator
101106

@@ -140,6 +145,7 @@ class MainActivity : FragmentActivity() {
140145
LocalUserManager provides userManager,
141146
LocalSessionController provides sessionController,
142147
LocalShareController provides shareController,
148+
LocalInviteController provides inviteController,
143149
LocalAppSettings provides appSettingsCoordinator,
144150
LocalFeatureFlags provides featureFlagController,
145151
LocalPhoneUtils provides phoneUtils,

apps/flipcash/app/src/main/kotlin/com/flipcash/app/internal/ui/navigation/AppScreenContent.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import com.flipcash.app.currencycreator.CurrencyCreatorFlowScreen
2929
import com.flipcash.app.core.AppRoute
3030
import com.flipcash.app.currency.RegionSelectionScreen
3131
import com.flipcash.app.deposit.DepositFlowScreen
32+
import com.flipcash.app.invite.InviteContactScreen
3233
import com.flipcash.app.discovery.TokenDiscoveryScreen
3334
import com.flipcash.app.internal.ui.navigation.decorators.rememberNavMessagingEntryDecorator
3435
import com.flipcash.app.lab.LabsScreen
@@ -79,16 +80,16 @@ fun appEntryProvider(
7980
annotatedEntry<AppRoute.Main.AppRestricted> { key -> AppRestrictedScreen(key.restrictionType) }
8081
annotatedEntry<AppRoute.Main.Scanner> { ScannerScreen() }
8182
annotatedEntry<AppRoute.Main.RegionSelection> { RegionSelectionScreen() }
83+
annotatedEntry<AppRoute.Main.InviteContact> { key -> InviteContactScreen(key.phoneNumber) }
8284

8385
// Sheets (inner content — wrapped in Main.Sheet by navigateTo())
8486
annotatedEntry<AppRoute.Sheets.Give> { key -> CashScreen(key.mint, key.fromTokenInfo) }
85-
annotatedEntry<AppRoute.Sheets.Send> { }
87+
annotatedEntry<AppRoute.Sheets.Send> { }
8688
annotatedEntry<AppRoute.Sheets.TokenSelection> { key -> TokenSelectScreen(key.purpose) }
8789
annotatedEntry<AppRoute.Sheets.Wallet> { BalanceScreen() }
8890
annotatedEntry<AppRoute.Sheets.ShareApp> { ShareAppScreen() }
8991
annotatedEntry<AppRoute.Sheets.Menu> { MenuScreen() }
9092

91-
9293
// Tokens
9394
annotatedEntry<AppRoute.Token.Info> { key ->
9495
TokenInfoScreen(key.mint, key.shortfall, key.fromDeeplink)
@@ -97,6 +98,7 @@ fun appEntryProvider(
9798
annotatedEntry<AppRoute.Token.Swap> { key ->
9899
SwapFlowScreen(route = key, resultStateRegistry = resultStateRegistry)
99100
}
101+
// TODO: fold this into above entry
100102
annotatedEntry<AppRoute.Token.TxProcessing> { key ->
101103
TokenTxProcessingScreen(key.swapId, key.swapPurpose, key.amount, key.isFundingShortfall)
102104
}
@@ -120,6 +122,7 @@ fun appEntryProvider(
120122
annotatedEntry<AppRoute.Menu.DeviceLogs> { DeviceLogsScreen() }
121123

122124
annotatedEntry<AppRoute.UserFlags> { UserFlagsScreen() }
125+
123126
// Transfers
124127
annotatedEntry<AppRoute.Transfers.Deposit> { key ->
125128
DepositFlowScreen(route = key, resultStateRegistry = resultStateRegistry)

apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/AppRoute.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ sealed interface AppRoute : NavKey, Parcelable {
101101
@Serializable
102102
data object RegionSelection : Main
103103

104+
@Serializable
105+
data class InviteContact(val phoneNumber: String) : com.getcode.navigation.Sheet, com.getcode.navigation.WrapContentSheet
106+
104107
@Serializable
105108
@Parcelize
106109
data class Sheet(

apps/flipcash/core/src/main/kotlin/com/flipcash/app/core/util/Linkify.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import com.getcode.utils.urlEncode
88
object Linkify {
99
fun cashLink(entropy: String): String = "https://send.flipcash.com/c/#/e=${entropy}"
1010
fun download(shareRef: String): String = "https://flipcash.com/download?r=${shareRef}"
11+
fun whatsApp(phoneNumber: String, message: String): String =
12+
"https://wa.me/${phoneNumber.removePrefix("+")}?text=${message.urlEncode()}"
1113
fun tweet(message: String): String = "https://www.twitter.com/intent/tweet?text=${message.urlEncode()}"
1214
fun tokenInfo(token: Token): String = tokenInfo(token.address)
1315
fun tokenInfo(mint: Mint): String = "https://app.flipcash.com/token/${mint.base58()}"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.flipcash.app.core.util
2+
3+
object MessagingPackages {
4+
val whatsApp = listOf(
5+
"com.whatsapp",
6+
"com.whatsapp.w4b",
7+
)
8+
9+
val all = setOf(
10+
"org.thoughtcrime.securesms", // Signal
11+
"org.telegram.messenger", // Telegram
12+
"com.facebook.orca", // Messenger
13+
) + whatsApp
14+
}

apps/flipcash/core/src/main/res/values/strings.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@
152152

153153
<string name="title_shareDownloadLink">Get the Flipcash App</string>
154154
<string name="title_shareCashLink">Send %1$s</string>
155+
<string name="title_inviteContact">Invite to Flipcash</string>
156+
<string name="message_invite_contact">Download Flipcash so I can send you money\n\n%1$s</string>
155157

156158
<string name="title_enterAddress">Enter Solana address</string>
157159
<string name="subtitle_whereWithdrawTo">Where would you like to withdraw your %1$s to?</string>
@@ -693,4 +695,7 @@
693695
<string name="content_description_leaderboard">Learn more</string>
694696
<string name="prompt_title_learnAboutLeaderboard">Leaderboard Ranking</string>
695697
<string name="prompt_description_learnAboutLeaderboard">People must have a minimum balance of %1$s to be counted</string>
698+
699+
<string name="action_invite">Invite</string>
700+
<string name="action_inviteMoreOptions">More</string>
696701
</resources>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
build/
2+
.gradle/
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
plugins {
2+
alias(libs.plugins.flipcash.android.feature)
3+
}
4+
5+
android {
6+
namespace = "${Gradle.flipcashNamespace}.features.invite"
7+
}
8+
9+
dependencies {
10+
implementation(project(":apps:flipcash:shared:invite"))
11+
}

0 commit comments

Comments
 (0)