Skip to content

Commit c8718c8

Browse files
committed
Merge remote-tracking branch 'origin/develop' into HEAD
* origin/develop: fix: scope HomeViewModel to screen only; allow immediate auto airdrops after logout -> login feat(chat): advance read pointers when opening chats feat: airdrop first kin automatically; cleanup historical transaction usage feat: fetch transaction delta where applicable in app chore: reorganize utils into ui/non-ui feat: layout balance/chat unread indicator more inline w/ iOS feat: add unread indicator support to HomeBottom feat: cache chat Flow's in app scope to prevent unneccesary API calls to repopulate feeds feat: update styling for messages within a ChatMessage; add mute support feat: render on-chain messages WIP: feat: start to render chat UI feat: on-chain messaging for balance screen
2 parents 8a1189a + bd2a112 commit c8718c8

146 files changed

Lines changed: 2991 additions & 1126 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ dependencies {
6363
implementation(Libs.okhttp)
6464
implementation(Libs.mixpanel)
6565

66+
implementation(Libs.androidx_paging_runtime)
67+
6668
kapt(Libs.androidx_room_compiler)
6769
implementation(Libs.sqlcipher)
6870

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
{
2+
"formatVersion": 1,
3+
"database": {
4+
"version": 8,
5+
"identityHash": "45c39753eadbdaeddb35d2e002424dac",
6+
"entities": [
7+
{
8+
"tableName": "CurrencyRate",
9+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `rate` REAL NOT NULL, PRIMARY KEY(`id`))",
10+
"fields": [
11+
{
12+
"fieldPath": "id",
13+
"columnName": "id",
14+
"affinity": "TEXT",
15+
"notNull": true
16+
},
17+
{
18+
"fieldPath": "rate",
19+
"columnName": "rate",
20+
"affinity": "REAL",
21+
"notNull": true
22+
}
23+
],
24+
"primaryKey": {
25+
"autoGenerate": false,
26+
"columnNames": [
27+
"id"
28+
]
29+
},
30+
"indices": [],
31+
"foreignKeys": []
32+
},
33+
{
34+
"tableName": "FaqItem",
35+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT, `question` TEXT NOT NULL, `answer` TEXT NOT NULL)",
36+
"fields": [
37+
{
38+
"fieldPath": "uid",
39+
"columnName": "uid",
40+
"affinity": "INTEGER",
41+
"notNull": false
42+
},
43+
{
44+
"fieldPath": "question",
45+
"columnName": "question",
46+
"affinity": "TEXT",
47+
"notNull": true
48+
},
49+
{
50+
"fieldPath": "answer",
51+
"columnName": "answer",
52+
"affinity": "TEXT",
53+
"notNull": true
54+
}
55+
],
56+
"primaryKey": {
57+
"autoGenerate": true,
58+
"columnNames": [
59+
"uid"
60+
]
61+
},
62+
"indices": [],
63+
"foreignKeys": []
64+
},
65+
{
66+
"tableName": "PrefInt",
67+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `value` INTEGER NOT NULL, PRIMARY KEY(`key`))",
68+
"fields": [
69+
{
70+
"fieldPath": "key",
71+
"columnName": "key",
72+
"affinity": "TEXT",
73+
"notNull": true
74+
},
75+
{
76+
"fieldPath": "value",
77+
"columnName": "value",
78+
"affinity": "INTEGER",
79+
"notNull": true
80+
}
81+
],
82+
"primaryKey": {
83+
"autoGenerate": false,
84+
"columnNames": [
85+
"key"
86+
]
87+
},
88+
"indices": [],
89+
"foreignKeys": []
90+
},
91+
{
92+
"tableName": "PrefString",
93+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `value` TEXT NOT NULL, PRIMARY KEY(`key`))",
94+
"fields": [
95+
{
96+
"fieldPath": "key",
97+
"columnName": "key",
98+
"affinity": "TEXT",
99+
"notNull": true
100+
},
101+
{
102+
"fieldPath": "value",
103+
"columnName": "value",
104+
"affinity": "TEXT",
105+
"notNull": true
106+
}
107+
],
108+
"primaryKey": {
109+
"autoGenerate": false,
110+
"columnNames": [
111+
"key"
112+
]
113+
},
114+
"indices": [],
115+
"foreignKeys": []
116+
},
117+
{
118+
"tableName": "PrefBool",
119+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `value` INTEGER NOT NULL, PRIMARY KEY(`key`))",
120+
"fields": [
121+
{
122+
"fieldPath": "key",
123+
"columnName": "key",
124+
"affinity": "TEXT",
125+
"notNull": true
126+
},
127+
{
128+
"fieldPath": "value",
129+
"columnName": "value",
130+
"affinity": "INTEGER",
131+
"notNull": true
132+
}
133+
],
134+
"primaryKey": {
135+
"autoGenerate": false,
136+
"columnNames": [
137+
"key"
138+
]
139+
},
140+
"indices": [],
141+
"foreignKeys": []
142+
},
143+
{
144+
"tableName": "PrefDouble",
145+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `value` REAL NOT NULL, PRIMARY KEY(`key`))",
146+
"fields": [
147+
{
148+
"fieldPath": "key",
149+
"columnName": "key",
150+
"affinity": "TEXT",
151+
"notNull": true
152+
},
153+
{
154+
"fieldPath": "value",
155+
"columnName": "value",
156+
"affinity": "REAL",
157+
"notNull": true
158+
}
159+
],
160+
"primaryKey": {
161+
"autoGenerate": false,
162+
"columnNames": [
163+
"key"
164+
]
165+
},
166+
"indices": [],
167+
"foreignKeys": []
168+
},
169+
{
170+
"tableName": "SendLimit",
171+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `limit` REAL NOT NULL, PRIMARY KEY(`id`))",
172+
"fields": [
173+
{
174+
"fieldPath": "id",
175+
"columnName": "id",
176+
"affinity": "TEXT",
177+
"notNull": true
178+
},
179+
{
180+
"fieldPath": "limit",
181+
"columnName": "limit",
182+
"affinity": "REAL",
183+
"notNull": true
184+
}
185+
],
186+
"primaryKey": {
187+
"autoGenerate": false,
188+
"columnNames": [
189+
"id"
190+
]
191+
},
192+
"indices": [],
193+
"foreignKeys": []
194+
},
195+
{
196+
"tableName": "GiftCard",
197+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `entropy` TEXT NOT NULL, `amount` INTEGER NOT NULL, `date` INTEGER NOT NULL, PRIMARY KEY(`key`))",
198+
"fields": [
199+
{
200+
"fieldPath": "key",
201+
"columnName": "key",
202+
"affinity": "TEXT",
203+
"notNull": true
204+
},
205+
{
206+
"fieldPath": "entropy",
207+
"columnName": "entropy",
208+
"affinity": "TEXT",
209+
"notNull": true
210+
},
211+
{
212+
"fieldPath": "amount",
213+
"columnName": "amount",
214+
"affinity": "INTEGER",
215+
"notNull": true
216+
},
217+
{
218+
"fieldPath": "date",
219+
"columnName": "date",
220+
"affinity": "INTEGER",
221+
"notNull": true
222+
}
223+
],
224+
"primaryKey": {
225+
"autoGenerate": false,
226+
"columnNames": [
227+
"key"
228+
]
229+
},
230+
"indices": [],
231+
"foreignKeys": []
232+
},
233+
{
234+
"tableName": "exchangeData",
235+
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`fiat` REAL NOT NULL, `currency` TEXT NOT NULL, `synced_at` INTEGER NOT NULL, PRIMARY KEY(`currency`))",
236+
"fields": [
237+
{
238+
"fieldPath": "fx",
239+
"columnName": "fiat",
240+
"affinity": "REAL",
241+
"notNull": true
242+
},
243+
{
244+
"fieldPath": "currency",
245+
"columnName": "currency",
246+
"affinity": "TEXT",
247+
"notNull": true
248+
},
249+
{
250+
"fieldPath": "synced",
251+
"columnName": "synced_at",
252+
"affinity": "INTEGER",
253+
"notNull": true
254+
}
255+
],
256+
"primaryKey": {
257+
"autoGenerate": false,
258+
"columnNames": [
259+
"currency"
260+
]
261+
},
262+
"indices": [],
263+
"foreignKeys": []
264+
}
265+
],
266+
"views": [],
267+
"setupQueries": [
268+
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
269+
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '45c39753eadbdaeddb35d2e002424dac')"
270+
]
271+
}
272+
}

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

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
package com.getcode.db
22

33
import android.content.Context
4+
import androidx.room.AutoMigration
45
import androidx.room.Database
6+
import androidx.room.DeleteTable
57
import androidx.room.Room
68
import androidx.room.RoomDatabase
79
import androidx.room.TypeConverters
10+
import androidx.room.migration.AutoMigrationSpec
11+
import androidx.room.migration.Migration
12+
import androidx.sqlite.db.SupportSQLiteDatabase
813
import com.getcode.model.*
914
import com.getcode.network.repository.decodeBase64
1015
import com.getcode.vendor.Base58
@@ -16,7 +21,6 @@ import java.io.File
1621

1722
@Database(
1823
entities = [
19-
HistoricalTransaction::class,
2024
CurrencyRate::class,
2125
FaqItem::class,
2226
PrefInt::class,
@@ -27,7 +31,10 @@ import java.io.File
2731
GiftCard::class,
2832
ExchangeRate::class,
2933
],
30-
version = 7
34+
autoMigrations = [
35+
AutoMigration(from = 7, to = 8, spec = AppDatabase.Migration7To8::class)
36+
],
37+
version = 8
3138
)
3239
@TypeConverters(Converters::class)
3340
abstract class AppDatabase : RoomDatabase() {
@@ -37,6 +44,9 @@ abstract class AppDatabase : RoomDatabase() {
3744
abstract fun prefDoubleDao(): PrefDoubleDao
3845
abstract fun giftCardDao(): GiftCardDao
3946
abstract fun exchangeDao(): ExchangeDao
47+
48+
@DeleteTable(tableName = "HistoricalTransaction")
49+
class Migration7To8 : AutoMigrationSpec
4050
}
4151

4252
object Database {

api/src/main/java/com/getcode/manager/SessionManager.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ import javax.inject.Singleton
1414

1515

1616
@Singleton
17-
class SessionManager @Inject constructor(
18-
) {
17+
class SessionManager @Inject constructor() {
1918
data class SessionState(
2019
val entropyB64: String? = null,
2120
val keyPair: Ed25519.KeyPair? = null,
@@ -26,7 +25,9 @@ class SessionManager @Inject constructor(
2625

2726
fun set(context: Context, entropyB64: String) {
2827
val mnemonic = MnemonicPhrase.fromEntropyB64(context, entropyB64)
29-
if (getOrganizer()?.mnemonic?.words == mnemonic.words) return
28+
if (getOrganizer()?.mnemonic?.words == mnemonic.words
29+
&& getOrganizer()?.ownerKeyPair == authState.value.keyPair
30+
) return
3031
val organizer = Organizer.newInstance(
3132
context = context,
3233
mnemonic = mnemonic
@@ -37,7 +38,7 @@ class SessionManager @Inject constructor(
3738
entropyB64 = entropyB64,
3839
keyPair = organizer.ownerKeyPair,
3940
isAuthenticated = true,
40-
organizer = organizer
41+
organizer = organizer,
4142
)
4243
}
4344
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.getcode.mapper
2+
3+
4+
import com.codeinc.gen.chat.v1.ChatService
5+
import com.getcode.model.ChatMessage
6+
import com.getcode.model.MessageContent
7+
import javax.inject.Inject
8+
import com.codeinc.gen.chat.v1.ChatService.ChatMessage as ApiChatMessage
9+
import com.getcode.model.ChatMessage as DomainChatMessage
10+
11+
12+
class ChatMessageMapper @Inject constructor(
13+
): Mapper<ApiChatMessage, DomainChatMessage> {
14+
override fun map(from: ChatService.ChatMessage): ChatMessage {
15+
return ChatMessage(
16+
id = from.messageId.value.toByteArray().toList(),
17+
cursor = from.cursor.value.toList(),
18+
dateMillis = from.ts.seconds * 1_000L,
19+
contents = from.contentList.mapNotNull { MessageContent(it) },
20+
)
21+
}
22+
}

0 commit comments

Comments
 (0)