Skip to content

Commit f29b943

Browse files
committed
feat: add send tip within tip chat UI
Signed-off-by: Brandon McAnsh <[email protected]>
1 parent 4a62c11 commit f29b943

File tree

24 files changed

+301
-118
lines changed

24 files changed

+301
-118
lines changed

api/schemas/com.getcode.db.AppDatabase/10.json

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"formatVersion": 1,
33
"database": {
44
"version": 10,
5-
"identityHash": "d5660e6875cc3237f2282f65ccd11b66",
5+
"identityHash": "f2095500e8b757e790d9d45cc1820bb3",
66
"entities": [
77
{
88
"tableName": "CurrencyRate",
@@ -238,14 +238,8 @@
238238
},
239239
{
240240
"tableName": "conversations",
241-
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`idBase58` TEXT NOT NULL, `messageIdBase58` TEXT NOT NULL, `cursorBase58` TEXT NOT NULL, `tipAmount` TEXT NOT NULL, `createdByUser` INTEGER NOT NULL, `hasRevealedIdentity` INTEGER NOT NULL, `user` TEXT, `userImage` TEXT, `lastActivity` INTEGER, PRIMARY KEY(`idBase58`))",
241+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`messageIdBase58` TEXT NOT NULL, `cursorBase58` TEXT NOT NULL, `tipAmount` TEXT NOT NULL, `createdByUser` INTEGER NOT NULL, `hasRevealedIdentity` INTEGER NOT NULL, `user` TEXT, `userImage` TEXT, `lastActivity` INTEGER, PRIMARY KEY(`messageIdBase58`))",
242242
"fields": [
243-
{
244-
"fieldPath": "idBase58",
245-
"columnName": "idBase58",
246-
"affinity": "TEXT",
247-
"notNull": true
248-
},
249243
{
250244
"fieldPath": "messageIdBase58",
251245
"columnName": "messageIdBase58",
@@ -298,7 +292,7 @@
298292
"primaryKey": {
299293
"autoGenerate": false,
300294
"columnNames": [
301-
"idBase58"
295+
"messageIdBase58"
302296
]
303297
},
304298
"indices": [],
@@ -384,7 +378,7 @@
384378
"views": [],
385379
"setupQueries": [
386380
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
387-
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd5660e6875cc3237f2282f65ccd11b66')"
381+
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'f2095500e8b757e790d9d45cc1820bb3')"
388382
]
389383
}
390384
}

api/src/main/java/com/getcode/analytics/AnalyticsManager.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ class AnalyticsManager @Inject constructor(
334334
Debug("Debug Screen"),
335335
ForceUpgrade("Force Upgrade"),
336336
BuyMoreKin("Buy More Kin Screen"),
337+
SendKin("Send Kin Screen"),
337338
}
338339

339340
enum class BillPresentationStyle(val value: String) {

api/src/main/java/com/getcode/db/ConversationDao.kt

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ interface ConversationDao {
1818
suspend fun upsertConversations(vararg conversation: Conversation)
1919

2020
@Transaction
21-
@Query("SELECT * FROM conversations WHERE idBase58 = :id")
21+
@Query("SELECT * FROM conversations WHERE messageIdBase58 = :id")
2222
fun observeConversationWithMessages(id: String): Flow<ConversationWithMessages>
2323

24-
fun observeConversationWithMessages(id: ID): Flow<ConversationWithMessages> {
25-
return observeConversationWithMessages(id.base58)
24+
fun observeConversationWithMessages(messageId: ID): Flow<ConversationWithMessages> {
25+
return observeConversationWithMessages(messageId.base58)
2626
}
2727

28-
@Query("SELECT * FROM conversations WHERE idBase58 = :conversationId")
29-
fun observeConversation(conversationId: String): Flow<Conversation?>
28+
@Query("SELECT * FROM conversations WHERE messageIdBase58 = :messageId")
29+
fun observeConversation(messageId: String): Flow<Conversation?>
3030

31-
fun observeConversation(conversationId: ID): Flow<Conversation?> {
32-
return observeConversation(conversationId.base58)
31+
fun observeConversation(messageId: ID): Flow<Conversation?> {
32+
return observeConversation(messageId.base58)
3333
}
3434

3535
@Query("SELECT * FROM conversations WHERE messageIdBase58 = :messageId")
@@ -39,11 +39,11 @@ interface ConversationDao {
3939
return observeConversationForMessage(messageId.base58)
4040
}
4141

42-
@Query("SELECT * FROM conversations WHERE idBase58 = :conversationId")
43-
suspend fun findConversation(conversationId: String): Conversation?
42+
@Query("SELECT * FROM conversations WHERE messageIdBase58 = :messageId")
43+
suspend fun findConversation(messageId: String): Conversation?
4444

45-
suspend fun findConversation(conversationId: ID): Conversation? {
46-
return findConversation(conversationId.base58)
45+
suspend fun findConversation(messageId: ID): Conversation? {
46+
return findConversation(messageId.base58)
4747
}
4848

4949
@Query("SELECT * FROM conversations WHERE messageIdBase58 = :messageId")
@@ -56,25 +56,25 @@ interface ConversationDao {
5656
@Query("SELECT * FROM conversations")
5757
suspend fun queryConversations(): List<Conversation>
5858

59-
@Query("SELECT EXISTS (SELECT * FROM messages WHERE conversationIdBase58 = :conversationId AND content LIKE '%1|%')")
60-
suspend fun hasTipMessage(conversationId: String): Boolean
59+
@Query("SELECT EXISTS (SELECT * FROM messages WHERE conversationIdBase58 = :messageId AND content LIKE '%1|%')")
60+
suspend fun hasTipMessage(messageId: String): Boolean
6161

62-
suspend fun hasTipMessage(conversationId: ID): Boolean {
63-
return hasTipMessage(conversationId.base58)
62+
suspend fun hasTipMessage(messageId: ID): Boolean {
63+
return hasTipMessage(messageId.base58)
6464
}
6565

66-
@Query("SELECT EXISTS (SELECT * FROM messages WHERE conversationIdBase58 = :conversationId AND content LIKE '%2|%')")
67-
suspend fun hasThanked(conversationId: String): Boolean
66+
@Query("SELECT EXISTS (SELECT * FROM messages WHERE conversationIdBase58 = :messageId AND content LIKE '%2|%')")
67+
suspend fun hasThanked(messageId: String): Boolean
6868

69-
suspend fun hasThanked(conversationId: ID): Boolean {
70-
return hasThanked(conversationId.base58)
69+
suspend fun hasThanked(messageId: ID): Boolean {
70+
return hasThanked(messageId.base58)
7171
}
7272

73-
@Query("SELECT EXISTS (SELECT * FROM messages WHERE conversationIdBase58 = :conversationId AND content LIKE '%4|%')")
74-
suspend fun hasRevealedIdentity(conversationId: String): Boolean
73+
@Query("SELECT EXISTS (SELECT * FROM messages WHERE conversationIdBase58 = :messageId AND content LIKE '%4|%')")
74+
suspend fun hasRevealedIdentity(messageId: String): Boolean
7575

76-
suspend fun hasRevealedIdentity(conversationId: ID): Boolean {
77-
return hasRevealedIdentity(conversationId.base58)
76+
suspend fun hasRevealedIdentity(messageId: ID): Boolean {
77+
return hasRevealedIdentity(messageId.base58)
7878
}
7979

8080
@Query("DELETE FROM conversations")
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.getcode.mapper
2+
3+
import com.getcode.model.ChatMessage
4+
import com.getcode.model.Conversation
5+
import com.getcode.model.KinAmount
6+
import com.getcode.model.MessageContent
7+
import com.getcode.model.Rate
8+
import com.getcode.model.orOneToOne
9+
import com.getcode.network.exchange.Exchange
10+
import com.getcode.network.repository.base58
11+
import javax.inject.Inject
12+
13+
class ConversationMapper @Inject constructor(
14+
private val exchange: Exchange,
15+
) : Mapper<ChatMessage, Conversation> {
16+
override fun map(from: ChatMessage): Conversation {
17+
val exchangeMessage = from.contents.firstOrNull {
18+
it is MessageContent.Exchange
19+
} as? MessageContent.Exchange
20+
21+
val tipAmount = if (exchangeMessage != null) {
22+
val rate = exchange.rateFor(exchangeMessage.amount.currencyCode).orOneToOne()
23+
exchangeMessage.amount.amountUsing(rate)
24+
} else {
25+
KinAmount.newInstance(0, Rate.oneToOne)
26+
}
27+
28+
return Conversation(
29+
messageIdBase58 = from.id.base58,
30+
cursorBase58 = from.cursor.base58,
31+
tipAmount = tipAmount,
32+
createdByUser = false, // TODO: ?
33+
hasRevealedIdentity = false, // TODO: ?
34+
lastActivity = null,
35+
user = null, // TODO: ?
36+
userImage = null,
37+
)
38+
}
39+
}

api/src/main/java/com/getcode/model/Conversation.kt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import kotlinx.serialization.modules.SerializersModule
1919
@Entity(tableName = "conversations")
2020
data class Conversation(
2121
@PrimaryKey
22-
val idBase58: String,
2322
val messageIdBase58: String,
2423
val cursorBase58: String,
2524
val tipAmount: KinAmount,
@@ -29,8 +28,6 @@ data class Conversation(
2928
val userImage: String?,
3029
val lastActivity: Long?,
3130
) {
32-
@Ignore
33-
val id: ID = Base58.decode(idBase58).toList()
3431
@Ignore
3532
val messageId: ID = Base58.decode(messageIdBase58).toList()
3633
@Ignore
@@ -39,7 +36,6 @@ data class Conversation(
3936
override fun toString(): String {
4037
return """
4138
{
42-
id:${idBase58},
4339
messageId:${messageIdBase58},
4440
tipAmount:$tipAmount,
4541
createByUser:$createdByUser,
@@ -72,7 +68,7 @@ data class ConversationMessage(
7268
data class ConversationWithMessages(
7369
@Embedded val user: Conversation,
7470
@Relation(
75-
parentColumn = "idBase58",
71+
parentColumn = "messageIdBase58",
7672
entityColumn = "conversationIdBase58"
7773
)
7874
val messages: List<ConversationMessage>,

api/src/main/java/com/getcode/model/Feature.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ data class TipCardFeature(
1515
override val available: Boolean = true, // always enabled
1616
): Feature
1717

18+
data class TipChatFeature(
19+
override val enabled: Boolean = false,
20+
override val available: Boolean = true, // always enabled
21+
): Feature
22+
23+
data class TipChatCashFeature(
24+
override val enabled: Boolean = false,
25+
override val available: Boolean = true, // always enabled
26+
): Feature
27+
1828

1929
data class RequestKinFeature(
2030
override val enabled: Boolean = false,

api/src/main/java/com/getcode/model/PrefBool.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@ sealed class PrefsBool(val value: String) {
3737
data object CHAT_UNSUB_ENABLED: PrefsBool("chat_unsub_enabled"), BetaFlag
3838
data object TIPS_ENABLED : PrefsBool("tips_enabled"), BetaFlag
3939
data object TIPS_CHAT_ENABLED: PrefsBool("tips_chat_enabled"), BetaFlag
40+
data object TIPS_CHAT_CASH_ENABLED: PrefsBool("tips_chat_cash_enabled"), BetaFlag
4041
}

api/src/main/java/com/getcode/network/ConversationController.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class ConversationMockController @Inject constructor(
9595
db.conversationDao().upsertConversations(conversation)
9696

9797
val tipMessage = ConversationMockProvider.createMessage(
98-
conversation.id,
98+
conversation.messageId,
9999
ConversationMessageContent.TipMessage
100100
)
101101

@@ -105,7 +105,7 @@ class ConversationMockController @Inject constructor(
105105

106106
override suspend fun hasThanked(messageId: ID): Boolean {
107107
val conversation = db.conversationDao().findConversationForMessage(messageId) ?: return false
108-
return db.conversationDao().hasThanked(conversation.id)
108+
return db.conversationDao().hasThanked(conversation.messageId)
109109
}
110110

111111
override suspend fun thankTipper(messageId: ID) {

api/src/main/java/com/getcode/network/repository/BetaFlagsRepository.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ data class BetaOptions(
1818
val chatUnsubEnabled: Boolean,
1919
val tipsEnabled: Boolean,
2020
val tipsChatEnabled: Boolean,
21+
val tipsChatCashEnabled: Boolean,
2122
) {
2223
companion object {
2324
// Default states for various beta flags in app.
@@ -32,7 +33,8 @@ data class BetaOptions(
3233
establishCodeRelationship = false,
3334
chatUnsubEnabled = false,
3435
tipsEnabled = false,
35-
tipsChatEnabled = false
36+
tipsChatEnabled = false,
37+
tipsChatCashEnabled = false
3638
)
3739
}
3840
}
@@ -63,8 +65,9 @@ class BetaFlagsRepository @Inject constructor(
6365
observeBetaFlag(PrefsBool.CHAT_UNSUB_ENABLED, default = defaults.chatUnsubEnabled),
6466
observeBetaFlag(PrefsBool.TIPS_ENABLED, default = defaults.tipsEnabled),
6567
observeBetaFlag(PrefsBool.TIPS_CHAT_ENABLED, default = defaults.tipsChatEnabled),
68+
observeBetaFlag(PrefsBool.TIPS_CHAT_CASH_ENABLED, default = defaults.tipsChatCashEnabled),
6669
observeBetaFlag(PrefsBool.DISPLAY_ERRORS, default = defaults.displayErrors),
67-
) { network, buckets, vibez, times, giveRequests, buyKin, relationship, chatUnsub, tips, tipsChat, errors ->
70+
) { network, buckets, vibez, times, giveRequests, buyKin, relationship, chatUnsub, tips, tipsChat, tipsChatCash, errors ->
6871
BetaOptions(
6972
showNetworkDropOff = network,
7073
canViewBuckets = buckets,
@@ -76,6 +79,7 @@ class BetaFlagsRepository @Inject constructor(
7679
chatUnsubEnabled = chatUnsub,
7780
tipsEnabled = tips,
7881
tipsChatEnabled = tipsChat,
82+
tipsChatCashEnabled = tipsChatCash,
7983
displayErrors = errors
8084
)
8185
}

api/src/main/java/com/getcode/network/repository/FeatureRepository.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import com.getcode.model.BuyModuleFeature
44
import com.getcode.model.PrefsBool
55
import com.getcode.model.RequestKinFeature
66
import com.getcode.model.TipCardFeature
7+
import com.getcode.model.TipChatCashFeature
8+
import com.getcode.model.TipChatFeature
79
import kotlinx.coroutines.flow.combine
810
import kotlinx.coroutines.flow.map
911
import javax.inject.Inject
@@ -22,5 +24,8 @@ class FeatureRepository @Inject constructor(
2224

2325
val tipCards = betaFlags.observe().map { TipCardFeature(it.tipsEnabled) }
2426

27+
val tipChat = betaFlags.observe().map { TipChatFeature(it.tipsChatEnabled) }
28+
val tipChatCash = betaFlags.observe().map { TipChatCashFeature(it.tipsChatCashEnabled) }
29+
2530
val requestKin = betaFlags.observe().map { RequestKinFeature(it.giveRequestsEnabled) }
2631
}

api/src/main/java/com/getcode/network/source/ConversationPagingSource.kt

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ object ConversationMockProvider {
2222

2323
suspend fun createConversation(exchange: Exchange, message: ChatMessage): Conversation? {
2424
val ret = db.conversationDao().findConversationForMessage(message.id)
25-
val hasTipMessage = ret?.let { db.conversationDao().hasTipMessage(it.id) } ?: false
25+
val hasTipMessage = ret?.let { db.conversationDao().hasTipMessage(it.messageId) } ?: false
2626
if (hasTipMessage) return null
2727

2828
val tipAmountRaw = message.contents.filterIsInstance<MessageContent.Exchange>()
@@ -32,12 +32,9 @@ object ConversationMockProvider {
3232
val rate = exchange.rateFor(tipAmountRaw.currencyCode).orOneToOne()
3333
val tipAmount = tipAmountRaw.amountUsing(rate)
3434

35-
val id = generateId()
36-
3735
val conversation = Conversation(
38-
idBase58 = id.base58,
3936
messageIdBase58 = message.id.base58,
40-
cursorBase58 = id.base58,
37+
cursorBase58 = message.id.base58,
4138
tipAmount = tipAmount,
4239
createdByUser = true,
4340
hasRevealedIdentity = false,
@@ -46,7 +43,7 @@ object ConversationMockProvider {
4643
lastActivity = null,
4744
)
4845

49-
Timber.d("Created conversation ${id.base58} from ${tipAmount.fiat}")
46+
Timber.d("Created conversation from ${tipAmount.fiat}")
5047

5148
return conversation
5249
}
@@ -67,27 +64,24 @@ object ConversationMockProvider {
6764
}
6865

6966
suspend fun thankTipper(messageId: ID): ConversationMessage? {
70-
val conversation =
71-
db.conversationDao().findConversationForMessage(messageId) ?: return null
72-
73-
if (db.conversationDao().hasThanked(conversation.id)) {
67+
if (db.conversationDao().hasThanked(messageId)) {
7468
return null
7569
}
7670

77-
return createMessage(conversation.id, ConversationMessageContent.ThanksSent)
71+
return createMessage(messageId, ConversationMessageContent.ThanksSent)
7872
}
7973

8074
suspend fun revealIdentity(messageId: ID): ConversationMessage? {
8175
val conversation =
8276
db.conversationDao().findConversationForMessage(messageId) ?: return null
8377

84-
if (db.conversationDao().hasRevealedIdentity(conversation.id)) {
78+
if (db.conversationDao().hasRevealedIdentity(conversation.messageId)) {
8579
return null
8680
}
8781

8882
db.conversationDao().upsertConversations(conversation.copy(hasRevealedIdentity = true))
8983

90-
return createMessage(conversation.id, ConversationMessageContent.IdentityRevealed)
84+
return createMessage(conversation.messageId, ConversationMessageContent.IdentityRevealed)
9185
}
9286

9387
private fun generateId() = UUID.randomUUID().toByteArray().toList()

0 commit comments

Comments
 (0)