Skip to content

Commit 65bf0ec

Browse files
committed
[Next] feat: Implement initial backup contact list page
Change-Id: I96bba7ac4ff4f78f140729cec9478dc443381a26
1 parent bee531b commit 65bf0ec

19 files changed

Lines changed: 519 additions & 16 deletions

File tree

source-next/app/build.gradle.kts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ dependencies {
9999
implementation(libs.androidx.room.runtime)
100100
implementation(libs.androidx.room.ktx)
101101
ksp(libs.androidx.room.compiler)
102+
103+
// Moshi
104+
implementation(libs.moshi)
102105
}
103106

104107
kotlin {
@@ -107,6 +110,7 @@ kotlin {
107110
"-opt-in=androidx.compose.material3.ExperimentalMaterial3Api",
108111
"-opt-in=androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi",
109112
"-opt-in=androidx.compose.ui.ExperimentalComposeUiApi",
113+
"-opt-in=kotlin.ExperimentalStdlibApi",
110114
)
111115
}
112116
}

source-next/app/src/main/AndroidManifest.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
android:name="android.permission.QUERY_ALL_PACKAGES"
1010
tools:ignore="QueryAllPackagesPermission" />
1111

12+
<!-- Contacts permissions -->
13+
<uses-permission android:name="android.permission.READ_CONTACTS" />
14+
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
15+
1216
<application
1317
android:name=".App"
1418
android:allowBackup="true"

source-next/app/src/main/java/com/xayah/databackup/database/AppDataBase.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,22 @@ package com.xayah.databackup.database
33
import androidx.room.Database
44
import androidx.room.RoomDatabase
55
import com.xayah.databackup.database.dao.AppDao
6+
import com.xayah.databackup.database.dao.ContactDao
67
import com.xayah.databackup.database.dao.NetworkDao
78
import com.xayah.databackup.database.entity.App
9+
import com.xayah.databackup.database.entity.Contact
810
import com.xayah.databackup.database.entity.Network
911

1012
@Database(
1113
entities = [
1214
App::class,
13-
Network::class
15+
Network::class,
16+
Contact::class,
1417
],
1518
version = 1
1619
)
1720
abstract class AppDatabase : RoomDatabase() {
1821
abstract fun appDao(): AppDao
1922
abstract fun networkDao(): NetworkDao
23+
abstract fun contactDao(): ContactDao
2024
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.xayah.databackup.database.dao
2+
3+
import androidx.room.Dao
4+
import androidx.room.Query
5+
import androidx.room.Upsert
6+
import com.xayah.databackup.database.entity.Contact
7+
import kotlinx.coroutines.flow.Flow
8+
9+
@Dao
10+
interface ContactDao {
11+
@Upsert(entity = Contact::class)
12+
suspend fun upsert(contacts: List<Contact>)
13+
14+
@Query("SELECT * from contacts")
15+
fun loadFlowContacts(): Flow<List<Contact>>
16+
17+
@Query("UPDATE contacts SET selected = :selected WHERE id = :id")
18+
suspend fun selectContact(id: Long, selected: Boolean)
19+
20+
@Query("UPDATE contacts SET selected = :selected WHERE (id) in (:ids)")
21+
suspend fun selectAllContacts(ids: List<Long>, selected: Boolean)
22+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.xayah.databackup.database.entity
2+
3+
import android.provider.ContactsContract
4+
import androidx.room.Entity
5+
import com.squareup.moshi.Moshi
6+
import com.squareup.moshi.adapter
7+
import com.xayah.databackup.App
8+
import com.xayah.databackup.R
9+
import kotlinx.coroutines.flow.Flow
10+
import kotlinx.coroutines.flow.map
11+
12+
typealias FiledMap = Map<String, Any>
13+
typealias FiledMutableMap = MutableMap<String, Any>
14+
15+
@Entity(tableName = "contacts", primaryKeys = ["id"])
16+
data class Contact(
17+
var id: Long,
18+
var rawContact: String?, // JSON
19+
var data: String?, // JSON
20+
var selected: Boolean,
21+
)
22+
23+
data class ContactDeserialized(
24+
var id: Long,
25+
var rawContact: FiledMap,
26+
var data: List<FiledMap>,
27+
var selected: Boolean,
28+
) {
29+
val displayName: String =
30+
rawContact.getOrDefault(ContactsContract.RawContacts.DISPLAY_NAME_PRIMARY, App.application.getString(R.string.unknown)).toString()
31+
}
32+
33+
fun Flow<List<Contact>>.deserialize(): Flow<List<ContactDeserialized>> = map { flow ->
34+
val moshi: Moshi = Moshi.Builder().build()
35+
flow.map {
36+
val rawContact = it.rawContact?.let { json -> moshi.adapter<FiledMap>().fromJson(json) }
37+
val data = it.data?.let { json -> moshi.adapter<List<FiledMap>>().fromJson(json) }
38+
ContactDeserialized(
39+
id = it.id,
40+
rawContact = rawContact ?: mapOf(),
41+
data = data ?: listOf(),
42+
selected = it.selected
43+
)
44+
}
45+
}

source-next/app/src/main/java/com/xayah/databackup/feature/MainActivity.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import com.xayah.databackup.App
3232
import com.xayah.databackup.R
3333
import com.xayah.databackup.feature.backup.BackupPreviewScreen
3434
import com.xayah.databackup.feature.backup.apps.BackupAppsScreen
35+
import com.xayah.databackup.feature.backup.contacts.BackupContactsScreen
3536
import com.xayah.databackup.feature.backup.networks.BackupNetworksScreen
3637
import com.xayah.databackup.feature.dashboard.DashboardScreen
3738
import com.xayah.databackup.feature.setup.NoPermKey
@@ -64,6 +65,9 @@ data object BackupApps
6465
@Serializable
6566
data object BackupNetworks
6667

68+
@Serializable
69+
data object BackupContacts
70+
6771
@Composable
6872
fun ErrorServiceDialog(onConfirm: () -> Unit, onRetry: () -> Unit) {
6973
AlertDialog(
@@ -168,6 +172,10 @@ class MainActivity : ComponentActivity() {
168172
composable<BackupNetworks> {
169173
BackupNetworksScreen(navController)
170174
}
175+
176+
composable<BackupContacts> {
177+
BackupContactsScreen(navController)
178+
}
171179
}
172180
}
173181
}

source-next/app/src/main/java/com/xayah/databackup/feature/backup/BackupPreviewScreen.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import androidx.compose.ui.unit.dp
3232
import androidx.navigation.NavHostController
3333
import com.xayah.databackup.R
3434
import com.xayah.databackup.feature.BackupApps
35+
import com.xayah.databackup.feature.BackupContacts
3536
import com.xayah.databackup.feature.BackupNetworks
3637
import com.xayah.databackup.ui.component.SelectableActionButton
3738
import com.xayah.databackup.ui.component.verticalFadingEdges
@@ -118,7 +119,9 @@ fun BackupPreviewScreen(navController: NavHostController) {
118119
icon = ImageVector.vectorResource(R.drawable.ic_user_round),
119120
title = "Contacts",
120121
subtitle = "No items selected"
121-
) {}
122+
) {
123+
navController.navigateSafely(BackupContacts)
124+
}
122125

123126
SelectableActionButton(
124127
modifier = Modifier

source-next/app/src/main/java/com/xayah/databackup/feature/backup/apps/AppsViewModel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import com.xayah.databackup.util.SortsSequenceBackup
1717
import com.xayah.databackup.util.SortsType
1818
import com.xayah.databackup.util.SortsTypeBackup
1919
import com.xayah.databackup.util.combine
20-
import com.xayah.databackup.util.filter
20+
import com.xayah.databackup.util.filterApp
2121
import com.xayah.databackup.util.formatToStorageSize
2222
import com.xayah.databackup.util.readBoolean
2323
import com.xayah.databackup.util.readEnum
@@ -58,7 +58,7 @@ open class AppsViewModel : BaseViewModel() {
5858
SortsType.DATA_SIZE -> apps.sortByDataSize(sortSequence)
5959
SortsType.INSTALL_TIME -> apps.sortByInstallTime(sortSequence)
6060
SortsType.UPDATE_TIME -> apps.sortByUpdateTime(sortSequence)
61-
}.filter(searchText, userId, filterUserApps, filterSystemApps)
61+
}.filterApp(searchText, userId, filterUserApps, filterSystemApps)
6262
}.stateIn(
6363
scope = viewModelScope,
6464
initialValue = listOf(),

0 commit comments

Comments
 (0)