diff --git a/apps/flipcash/core/src/main/res/values/strings.xml b/apps/flipcash/core/src/main/res/values/strings.xml
index aee06a45f6..7bd13b3c05 100644
--- a/apps/flipcash/core/src/main/res/values/strings.xml
+++ b/apps/flipcash/core/src/main/res/values/strings.xml
@@ -1242,7 +1242,7 @@
Your Name
500x500 Recommended
My Tip Card
- Tip %1$s
+ Chat with %1$s on Flipcash
Share Your Tip Card to Get Tipped
Show My Tip Card
Send a Tip
diff --git a/apps/flipcash/features/menu/src/main/kotlin/com/flipcash/app/menu/internal/MenuScreenViewModel.kt b/apps/flipcash/features/menu/src/main/kotlin/com/flipcash/app/menu/internal/MenuScreenViewModel.kt
index 854a426b99..980b11cf72 100644
--- a/apps/flipcash/features/menu/src/main/kotlin/com/flipcash/app/menu/internal/MenuScreenViewModel.kt
+++ b/apps/flipcash/features/menu/src/main/kotlin/com/flipcash/app/menu/internal/MenuScreenViewModel.kt
@@ -467,16 +467,14 @@ internal class MenuScreenViewModel @Inject constructor(
.filterIsInstance()
.mapNotNull { tippingCoordinator.currentUserId }
.map { userId ->
- // Title shown above the link, e.g. "Tip Ada" (same label as the card).
- val title = stateFlow.value.tipCard?.user?.displayName
- ?.let { resources.getString(R.string.label_tipUser, it) }
+ val user = stateFlow.value.tipCard?.user
// Attach the eagerly-rendered preview if it's ready; null shares the URL alone.
shareable.present(
- Shareable.TipCard(
+ Shareable.Profile(
userId = userId,
+ displayName = user?.displayName,
+ username = user?.username,
preview = tipCodePreviewCache.get(userId),
- title = title,
- username = stateFlow.value.tipCard?.user?.username,
)
)
}
diff --git a/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/MessengerScreen.kt b/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/MessengerScreen.kt
index 8e568f6a0d..7dbd925b2d 100644
--- a/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/MessengerScreen.kt
+++ b/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/MessengerScreen.kt
@@ -49,7 +49,6 @@ import com.flipcash.shared.chat.models.ChatAction
import com.flipcash.app.core.LocalUserManager
import com.flipcash.app.shareable.LocalShareController
import com.flipcash.app.shareable.Shareable
-import com.flipcash.features.messenger.R
import kotlinx.coroutines.launch
import androidx.compose.runtime.rememberCoroutineScope
import com.getcode.navigation.core.LocalCodeNavigator
@@ -245,9 +244,9 @@ internal fun MessengerScreen(viewModel: ChatViewModel) {
// shares it (`rememberProfileShare`): the handle form, titled with their name.
is ChatAction.ShareProfile -> scope.launch {
shareController.present(
- Shareable.TipCard(
+ Shareable.Profile(
userId = action.userId,
- title = action.displayName?.let { context.getString(R.string.label_tipUser, it) },
+ displayName = action.displayName,
username = action.username,
)
)
diff --git a/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/profile/ProfileShortcuts.kt b/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/profile/ProfileShortcuts.kt
index a99684afe4..5bd103337a 100644
--- a/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/profile/ProfileShortcuts.kt
+++ b/apps/flipcash/features/messenger/src/main/kotlin/com/flipcash/app/messenger/internal/screens/profile/ProfileShortcuts.kt
@@ -86,9 +86,9 @@ internal fun rememberProfileShare(): (ChatParticipant.TipUser) -> Unit {
{ user ->
scope.launch {
shareController.present(
- Shareable.TipCard(
+ Shareable.Profile(
userId = user.userId,
- title = user.profile.displayName,
+ displayName = user.profile.displayName,
username = user.profile.username,
)
)
diff --git a/apps/flipcash/shared/shareable/src/main/kotlin/com/flipcash/app/shareable/ShareSheetController.kt b/apps/flipcash/shared/shareable/src/main/kotlin/com/flipcash/app/shareable/ShareSheetController.kt
index 8720f53abc..46629fd14c 100644
--- a/apps/flipcash/shared/shareable/src/main/kotlin/com/flipcash/app/shareable/ShareSheetController.kt
+++ b/apps/flipcash/shared/shareable/src/main/kotlin/com/flipcash/app/shareable/ShareSheetController.kt
@@ -69,16 +69,20 @@ sealed interface Shareable {
override val pendingData: ShareablePendingData? = null
}
- data class TipCard(
+ /**
+ * A user's profile link. The Sharesheet title ("Chat with Ada on Flipcash") is built from
+ * [displayName] when sharing, so every place that shares a profile titles it the same way.
+ */
+ data class Profile(
val userId: ID,
- // Optional pre-rendered Sharesheet preview. Null degrades to sharing the URL alone.
- val preview: TipCodePreview? = null,
- // Optional Sharesheet title shown above the link (e.g. "Tip Brandon McAnsh").
- val title: String? = null,
+ // The owner's display name. Null shares the link without a title.
+ val displayName: String? = null,
// The owner's claimed handle, when they have one. Carried so the shared link is the vanity
// form the You tab shows and copies — sharing a UUID for a card that displays
// `flipcash.com/` would hand out a second, unrecognisable address for it.
val username: String? = null,
+ // Optional pre-rendered Sharesheet preview. Null degrades to sharing the URL alone.
+ val preview: TipCodePreview? = null,
): Shareable {
override val pendingData: ShareablePendingData? = null
}
@@ -86,7 +90,7 @@ sealed interface Shareable {
/**
* The tip code itself, as a file (see [TipCodeExport]) — what the "Download" action produces.
*
- * Distinct from [TipCard]: that shares the tip *link* and only uses an image as the Sharesheet's
+ * Distinct from [Profile]: that shares the profile *link* and only uses an image as the Sharesheet's
* thumbnail. Here the file IS the payload, so it goes out as an `EXTRA_STREAM` of the export's
* own MIME type and a "save to Files" target receives something real.
*/
diff --git a/apps/flipcash/shared/shareable/src/main/kotlin/com/flipcash/app/shareable/internal/InternalShareConfirmationController.kt b/apps/flipcash/shared/shareable/src/main/kotlin/com/flipcash/app/shareable/internal/InternalShareConfirmationController.kt
index 4dc5e307f8..ed10feba52 100644
--- a/apps/flipcash/shared/shareable/src/main/kotlin/com/flipcash/app/shareable/internal/InternalShareConfirmationController.kt
+++ b/apps/flipcash/shared/shareable/src/main/kotlin/com/flipcash/app/shareable/internal/InternalShareConfirmationController.kt
@@ -31,7 +31,7 @@ internal class InternalShareConfirmationController(
// Nothing to take back if the link never leaves — the chat exists either way, and
// the same link can be shared again. Only a cash link needs confirming.
is Shareable.GroupInvite -> ShareConfirmationResult.Confirmed(shareResult)
- is Shareable.TipCard -> ShareConfirmationResult.Confirmed(shareResult)
+ is Shareable.Profile -> ShareConfirmationResult.Confirmed(shareResult)
is Shareable.TipCodeImage -> ShareConfirmationResult.Confirmed(shareResult)
}
}
diff --git a/apps/flipcash/shared/shareable/src/main/kotlin/com/flipcash/app/shareable/internal/InternalShareSheetController.kt b/apps/flipcash/shared/shareable/src/main/kotlin/com/flipcash/app/shareable/internal/InternalShareSheetController.kt
index fff5bf441f..882121ba32 100644
--- a/apps/flipcash/shared/shareable/src/main/kotlin/com/flipcash/app/shareable/internal/InternalShareSheetController.kt
+++ b/apps/flipcash/shared/shareable/src/main/kotlin/com/flipcash/app/shareable/internal/InternalShareSheetController.kt
@@ -116,7 +116,7 @@ internal class InternalShareSheetController(
is Shareable.TokenInfo -> Unit
is Shareable.Invite -> Unit
is Shareable.GroupInvite -> Unit
- is Shareable.TipCard -> Unit
+ is Shareable.Profile -> Unit
is Shareable.TipCodeImage -> Unit
}
}
@@ -217,7 +217,7 @@ internal class InternalShareSheetController(
shareGroupInvite(shareable)
}
- is Shareable.TipCard -> shareTipCard(shareable)
+ is Shareable.Profile -> shareProfile(shareable)
is Shareable.TipCodeImage -> shareTipCodeImage(shareable)
}
@@ -392,7 +392,7 @@ internal class InternalShareSheetController(
if (preview != null) {
// The Sharesheet draws its thumbnail from ClipData, not from any extra — see
- // shareTipCard. The payload stays the text; this is preview only.
+ // shareProfile. The payload stays the text; this is preview only.
clipData = ClipData.newUri(context.contentResolver, "Group picture", preview)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
@@ -400,7 +400,7 @@ internal class InternalShareSheetController(
val share = Intent.createChooser(intent, null).apply {
// addFlags, not `flags =` — assigning would wipe the read grant createChooser migrates
- // onto the chooser intent, and the Sharesheet could not open the image. See shareTipCard.
+ // onto the chooser intent, and the Sharesheet could not open the image. See shareProfile.
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
if (preview != null) addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
@@ -408,7 +408,7 @@ internal class InternalShareSheetController(
context.startActivity(share)
}
- private fun shareTipCard(shareable: Shareable.TipCard) {
+ private fun shareProfile(shareable: Shareable.Profile) {
// Addressed the same way the You tab's link row addresses it, so what gets shared is what
// the card says it is.
val url = Linkify.tipcard(
@@ -421,7 +421,9 @@ internal class InternalShareSheetController(
// URL's OG tags. type stays text/plain and the bitmap is NOT an EXTRA_STREAM.
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, url)
- shareable.title?.let { putExtra(Intent.EXTRA_TITLE, it) }
+ shareable.displayName
+ ?.let { resources.getString(R.string.title_shareProfile, it) }
+ ?.let { putExtra(Intent.EXTRA_TITLE, it) }
if (preview != null) {
// Android draws the Sharesheet thumbnail from the intent's ClipData (a content:// URI),
@@ -446,7 +448,7 @@ internal class InternalShareSheetController(
}
/**
- * Shares the exported code file itself (PNG/SVG). Unlike [shareTipCard], the payload here IS the
+ * Shares the exported code file itself (PNG/SVG). Unlike [shareProfile], the payload here IS the
* file: it goes out as an `EXTRA_STREAM` of the export's own MIME type, so "save to Files" and
* image-consuming targets receive something real rather than a link.
*/
@@ -467,7 +469,7 @@ internal class InternalShareSheetController(
}
val share = Intent.createChooser(intent, null).apply {
- // addFlags, not `flags =` — see shareTipCard: assigning would wipe the migrated grant.
+ // addFlags, not `flags =` — see shareProfile: assigning would wipe the migrated grant.
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}