From be80d2a8491a8b335c7d80509ded480d03d9f1ce Mon Sep 17 00:00:00 2001 From: Richard Kareko Date: Tue, 1 Nov 2022 15:37:22 +0300 Subject: [PATCH 01/72] Add compose dependencies Add initial P2P event, screen and UI state classes --- build.gradle | 1 + p2p-lib/build.gradle | 14 ++++ .../p2p/search/ui/p2p/P2PEvent.kt | 8 +++ .../p2p/search/ui/p2p/P2PScreen.kt | 67 +++++++++++++++++++ .../p2p/search/ui/p2p/P2PUiState.kt | 5 ++ .../p2p/search/ui/p2p/P2PViewModel.kt | 8 +++ .../p2p/search/ui/theme/Colors.kt | 20 ++++++ 7 files changed, 123 insertions(+) create mode 100644 p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PEvent.kt create mode 100644 p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PScreen.kt create mode 100644 p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PUiState.kt create mode 100644 p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PViewModel.kt create mode 100644 p2p-lib/src/main/java/org/smartregister/p2p/search/ui/theme/Colors.kt diff --git a/build.gradle b/build.gradle index c27b0e61..b79b2b9c 100644 --- a/build.gradle +++ b/build.gradle @@ -5,6 +5,7 @@ buildscript { versions.kotlin_coveralls = '2.12.0' versions.jacoco_tool = '0.8.7' + ext.composeVersion = "1.2.1" deps.kotlin_coveralls_plugin = "gradle.plugin.org.kt3k.gradle.plugin:coveralls-gradle-plugin:$versions.kotlin_coveralls" diff --git a/p2p-lib/build.gradle b/p2p-lib/build.gradle index e038e6a4..d0f4024f 100644 --- a/p2p-lib/build.gradle +++ b/p2p-lib/build.gradle @@ -82,6 +82,20 @@ dependencies { configuration -> implementation 'com.google.code.gson:gson:2.8.7' implementation 'androidx.activity:activity:1.3.1' + //Configure Jetpack Compose and navigation + api("androidx.compose.ui:ui:$composeVersion") + api("androidx.compose.ui:ui-tooling:$composeVersion") + api("androidx.compose.foundation:foundation:$composeVersion") + api("androidx.compose.material:material:$composeVersion") + api("androidx.compose.material:material-icons-core:$composeVersion") + api("androidx.compose.material:material-icons-extended:$composeVersion") + api("androidx.compose.runtime:runtime-livedata:$composeVersion") + api("androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1") + api("androidx.paging:paging-compose:1.0.0-alpha15") + api("androidx.activity:activity-compose:1.5.1") + api ("com.google.accompanist:accompanist-flowlayout:0.23.1") + api("androidx.work:work-runtime-ktx:2.7.1") + roomDependencies(configuration) locationDependencies(configuration) diff --git a/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PEvent.kt b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PEvent.kt new file mode 100644 index 00000000..6efbab5a --- /dev/null +++ b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PEvent.kt @@ -0,0 +1,8 @@ +package org.smartregister.p2p.search.ui.p2p + +sealed class P2PEvent { + + object ReceiveData : P2PEvent() + + object SendData : P2PEvent() +} \ No newline at end of file diff --git a/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PScreen.kt b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PScreen.kt new file mode 100644 index 00000000..0c90a050 --- /dev/null +++ b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PScreen.kt @@ -0,0 +1,67 @@ +package org.smartregister.p2p.search.ui.p2p + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Divider +import androidx.compose.material.DropdownMenu +import androidx.compose.material.DropdownMenuItem +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.material.TextField +import androidx.compose.material.TopAppBar +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material.icons.outlined.MoreVert +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import org.smartregister.p2p.search.ui.theme.ProfileBackgroundColor + +const val P2P_SCREEN_TOP_BAR_TEST_TAG = "p2pScreenTopBarTestTag" +const val P2P_SCREEN_TOP_BAR_ICON_TEST_TAG = "p2pScreenTopBarIconTestTag" + +@Composable +fun P2PScreen( + modifier: Modifier = Modifier +) { + Scaffold ( + topBar = { + TopAppBar( + modifier = modifier.testTag(P2P_SCREEN_TOP_BAR_TEST_TAG), + title = {"Transfer Data"}, + navigationIcon = { + IconButton(onClick = { }) { + Icon( + Icons.Filled.ArrowBack, + null, + modifier = modifier.testTag(P2P_SCREEN_TOP_BAR_ICON_TEST_TAG) + ) + } + }, + elevation = 0.dp + ) + } + ) { innerPadding -> + Box( + modifier = modifier.background(ProfileBackgroundColor).fillMaxHeight().padding(innerPadding) + ) + { + Text("we are here") + } + } +} + +@Preview(showBackground = true) +@Composable +private fun PreviewP2PScreen() { + P2PScreen() +} \ No newline at end of file diff --git a/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PUiState.kt b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PUiState.kt new file mode 100644 index 00000000..faa2618f --- /dev/null +++ b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PUiState.kt @@ -0,0 +1,5 @@ +package org.smartregister.p2p.search.ui.p2p + +data class P2PUiState ( + val state: String = "" +) \ No newline at end of file diff --git a/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PViewModel.kt b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PViewModel.kt new file mode 100644 index 00000000..6f11bf99 --- /dev/null +++ b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PViewModel.kt @@ -0,0 +1,8 @@ +package org.smartregister.p2p.search.ui.p2p + +import androidx.lifecycle.ViewModel +import androidx.compose.runtime.mutableStateOf + +class P2PViewModel () : ViewModel() { + val p2PUiState = mutableStateOf(P2PUiState()) +} \ No newline at end of file diff --git a/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/theme/Colors.kt b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/theme/Colors.kt new file mode 100644 index 00000000..eff8ac06 --- /dev/null +++ b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/theme/Colors.kt @@ -0,0 +1,20 @@ +package org.smartregister.p2p.search.ui.theme + +import androidx.compose.material.darkColors +import androidx.compose.material.lightColors +import androidx.compose.ui.graphics.Color + +val DangerColor = Color(0xFFFF333F) +val InfoColor = Color(0xFF006EB8) +val DefaultColor = Color(0xFF6F7274) +val ProfileBackgroundColor = Color(0xFFF2F4F7) + +private val PrimaryColor = Color(0xFF005084) +private val PrimaryVariantColor = Color(0xFF003D66) +private val ErrorColor = Color(0xFFDD0000) + +val LightColors = + lightColors(primary = PrimaryColor, primaryVariant = PrimaryVariantColor, error = ErrorColor) + +val DarkColors = + darkColors(primary = PrimaryColor, primaryVariant = PrimaryVariantColor, error = ErrorColor) From 7078e8483b92dd4b1c9c9671a73bf1e6a201657b Mon Sep 17 00:00:00 2001 From: Richard Kareko Date: Wed, 2 Nov 2022 08:59:35 +0300 Subject: [PATCH 02/72] Upgrade kotlin and gradle depencies --- build.gradle | 6 +++--- gradle/wrapper/gradle-wrapper.properties | 4 ++-- p2p-lib/build.gradle | 4 ++++ .../org/smartregister/p2p/search/ui/P2PReceiverViewModel.kt | 2 +- .../org/smartregister/p2p/search/ui/P2PSenderViewModel.kt | 2 +- sample/build.gradle | 2 +- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index b79b2b9c..0aa25ee8 100644 --- a/build.gradle +++ b/build.gradle @@ -16,9 +16,9 @@ buildscript { maven { url "https://plugins.gradle.org/m2/" } } dependencies { - classpath "com.android.tools.build:gradle:7.0.2" - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0" - classpath "org.jetbrains.kotlin:kotlin-serialization:1.6.10" + classpath "com.android.tools.build:gradle:7.1.3" + classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10' + classpath "org.jetbrains.kotlin:kotlin-serialization:1.7.10" classpath deps.kotlin_coveralls_plugin classpath deps.spotless diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d2ee2b46..307bdf2d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Nov 16 16:10:20 SAST 2021 +#Wed Nov 02 07:33:43 EAT 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/p2p-lib/build.gradle b/p2p-lib/build.gradle index d0f4024f..2cad85a8 100644 --- a/p2p-lib/build.gradle +++ b/p2p-lib/build.gradle @@ -49,8 +49,12 @@ android { jvmTarget = '1.8' } buildFeatures { + compose true viewBinding true } + composeOptions { + kotlinCompilerExtensionVersion '1.3.0' + } testOptions { execution 'ANDROIDX_TEST_ORCHESTRATOR' animationsDisabled true diff --git a/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/P2PReceiverViewModel.kt b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/P2PReceiverViewModel.kt index dd3f6ebc..7bd4ee0c 100644 --- a/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/P2PReceiverViewModel.kt +++ b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/P2PReceiverViewModel.kt @@ -248,7 +248,7 @@ class P2PReceiverViewModel( private val dataSharingStrategy: DataSharingStrategy, private val dispatcherProvider: DispatcherProvider ) : ViewModelProvider.Factory { - override fun create(modelClass: Class): T { + override fun create(modelClass: Class): T { return P2PReceiverViewModel(context, dataSharingStrategy, dispatcherProvider).apply { dataSharingStrategy.setCoroutineScope(viewModelScope) } as diff --git a/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/P2PSenderViewModel.kt b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/P2PSenderViewModel.kt index 747ec76b..35b134e0 100644 --- a/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/P2PSenderViewModel.kt +++ b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/P2PSenderViewModel.kt @@ -243,7 +243,7 @@ class P2PSenderViewModel( private val dataSharingStrategy: DataSharingStrategy, private val dispatcherProvider: DispatcherProvider ) : ViewModelProvider.Factory { - override fun create(modelClass: Class): T { + override fun create(modelClass: Class): T { return P2PSenderViewModel(context, dataSharingStrategy, dispatcherProvider).apply { dataSharingStrategy.setCoroutineScope(viewModelScope) } as diff --git a/sample/build.gradle b/sample/build.gradle index 4a854346..30c41a4c 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -4,7 +4,7 @@ plugins { } android { - compileSdk 31 + compileSdk 32 defaultConfig { applicationId "org.smartregister.p2p.sample" From 88192f6b2861ed182d2438b36c8c146c23e6792e Mon Sep 17 00:00:00 2001 From: Richard Kareko Date: Wed, 2 Nov 2022 10:36:17 +0300 Subject: [PATCH 03/72] Update main P2P screen --- p2p-lib/build.gradle | 2 +- .../p2p/search/ui/p2p/P2PScreen.kt | 64 +++++++++++++------ p2p-lib/src/main/res/drawable/ic_p2p.xml | 9 +++ p2p-lib/src/main/res/values/strings.xml | 2 + 4 files changed, 58 insertions(+), 19 deletions(-) create mode 100644 p2p-lib/src/main/res/drawable/ic_p2p.xml diff --git a/p2p-lib/build.gradle b/p2p-lib/build.gradle index 2cad85a8..c04cd0a0 100644 --- a/p2p-lib/build.gradle +++ b/p2p-lib/build.gradle @@ -14,7 +14,7 @@ jacoco { } android { - compileSdk 30 + compileSdk 32 defaultConfig { minSdk 21 diff --git a/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PScreen.kt b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PScreen.kt index 0c90a050..f61d2bbb 100644 --- a/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PScreen.kt +++ b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/p2p/P2PScreen.kt @@ -1,34 +1,38 @@ package org.smartregister.p2p.search.ui.p2p -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxWidth +import android.annotation.SuppressLint +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.material.Divider -import androidx.compose.material.DropdownMenu -import androidx.compose.material.DropdownMenuItem +import androidx.compose.foundation.layout.requiredHeight +import androidx.compose.foundation.layout.requiredWidth import androidx.compose.material.Icon import androidx.compose.material.IconButton import androidx.compose.material.Scaffold import androidx.compose.material.Text -import androidx.compose.material.TextField import androidx.compose.material.TopAppBar import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack -import androidx.compose.material.icons.outlined.MoreVert import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import org.smartregister.p2p.search.ui.theme.ProfileBackgroundColor +import org.smartregister.p2p.R const val P2P_SCREEN_TOP_BAR_TEST_TAG = "p2pScreenTopBarTestTag" const val P2P_SCREEN_TOP_BAR_ICON_TEST_TAG = "p2pScreenTopBarIconTestTag" +const val P2P_SYNC_IMAGE_TEST_TAG = "p2pSyncImageTestTag" +@SuppressLint("UnusedMaterialScaffoldPaddingParameter") @Composable fun P2PScreen( modifier: Modifier = Modifier @@ -50,13 +54,37 @@ fun P2PScreen( elevation = 0.dp ) } - ) { innerPadding -> - Box( - modifier = modifier.background(ProfileBackgroundColor).fillMaxHeight().padding(innerPadding) - ) - { - Text("we are here") + ) { + Column( modifier = modifier + .fillMaxSize() + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center) { + + Column(modifier = modifier.padding(4.dp), verticalArrangement = Arrangement.Center) { + Image( + painter = painterResource(R.drawable.ic_p2p), + contentDescription = stringResource(id = R.string.device_to_device_sync_logo), + modifier = + modifier + .align(Alignment.CenterHorizontally) + .requiredHeight(120.dp) + .requiredWidth(140.dp) + .testTag(P2P_SYNC_IMAGE_TEST_TAG), + ) + + Spacer(modifier = modifier.height(40.dp)) + + Row(modifier = modifier + .fillMaxSize()) { + Column() { + Text(text = stringResource(id = R.string.send_data)) + Text(text = stringResource(id = R.string.tap_to_send_data_msg)) + } + } + } } + } } diff --git a/p2p-lib/src/main/res/drawable/ic_p2p.xml b/p2p-lib/src/main/res/drawable/ic_p2p.xml new file mode 100644 index 00000000..ba01e855 --- /dev/null +++ b/p2p-lib/src/main/res/drawable/ic_p2p.xml @@ -0,0 +1,9 @@ + + + diff --git a/p2p-lib/src/main/res/values/strings.xml b/p2p-lib/src/main/res/values/strings.xml index 17f6137c..d64cd481 100644 --- a/p2p-lib/src/main/res/values/strings.xml +++ b/p2p-lib/src/main/res/values/strings.xml @@ -31,6 +31,7 @@ Connected to: Failed: %s Device to device sync + Device to device sync logo Scan for devices Make sure both devices are unlocked, close together and have wifi turned on Nearby devices @@ -58,4 +59,5 @@ Transferring %1$d%% of %2$d records Device searching failed! Please try again Connecting to device failed! Please try again + Tap to start sending data to nearby device \ No newline at end of file From e56f871865976da295b0cb81a880d1b36cbf66ed Mon Sep 17 00:00:00 2001 From: Richard Kareko Date: Thu, 3 Nov 2022 05:08:32 +0300 Subject: [PATCH 04/72] Wire up main P2P screen --- .../p2p/search/ui/P2PDeviceSearchActivity.kt | 13 ++++--- .../p2p/search/ui/p2p/P2PScreen.kt | 36 ++++++++++++++----- .../p2p/search/ui/theme/Themes.kt | 31 ++++++++++++++++ p2p-lib/src/main/res/values/colors.xml | 1 + p2p-lib/src/main/res/values/strings.xml | 3 ++ 5 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 p2p-lib/src/main/java/org/smartregister/p2p/search/ui/theme/Themes.kt diff --git a/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/P2PDeviceSearchActivity.kt b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/P2PDeviceSearchActivity.kt index bb313399..62014f93 100644 --- a/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/P2PDeviceSearchActivity.kt +++ b/p2p-lib/src/main/java/org/smartregister/p2p/search/ui/P2PDeviceSearchActivity.kt @@ -30,6 +30,7 @@ import android.widget.ImageButton import android.widget.ImageView import android.widget.TextView import android.widget.Toast +import androidx.activity.compose.setContent import androidx.activity.viewModels import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity @@ -54,6 +55,8 @@ import org.smartregister.p2p.data_sharing.DeviceInfo import org.smartregister.p2p.data_sharing.OnDeviceFound import org.smartregister.p2p.search.adapter.DeviceListAdapter import org.smartregister.p2p.search.contract.P2pModeSelectContract +import org.smartregister.p2p.search.ui.p2p.P2PScreen +import org.smartregister.p2p.search.ui.theme.AppTheme import org.smartregister.p2p.utils.DefaultDispatcherProvider import org.smartregister.p2p.utils.getDeviceName import org.smartregister.p2p.utils.isAppDebuggable @@ -98,23 +101,25 @@ class P2PDeviceSearchActivity : AppCompatActivity(), P2pModeSelectContract.View override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(R.layout.activity_p2_pdevice_search) + //setContentView(R.layout.activity_p2_pdevice_search) + // use compose + setContent { AppTheme { P2PScreen() } } if (Timber.treeCount == 0 && isAppDebuggable(this)) { Timber.plant(Timber.DebugTree()) } title = getString(R.string.device_to_device_sync) - supportActionBar?.setHomeAsUpIndicator(android.R.drawable.ic_menu_close_clear_cancel) + // supportActionBar?.setHomeAsUpIndicator(android.R.drawable.ic_menu_close_clear_cancel) // Remaining setup for the DataSharingStrategy class dataSharingStrategy = P2PLibrary.getInstance().dataSharingStrategy dataSharingStrategy.setActivity(this) - findViewById