Skip to content

Commit 511752a

Browse files
authored
Merge branch 'android:main' into main
2 parents 2596cf7 + 452ab50 commit 511752a

File tree

45 files changed

+538
-126
lines changed

Some content is hidden

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

45 files changed

+538
-126
lines changed

.github/workflows/AndroidCIWithGmd.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
- name: Run instrumented tests with GMD
2828
run: ./gradlew cleanManagedDevices --unused-only &&
2929
./gradlew ${{ matrix.device-config }}DemoDebugAndroidTest -Dorg.gradle.workers.max=1
30-
-Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" -Pandroid.experimental.testOptions.managedDevices.emulator.showKernelLogging=true --info
30+
-Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" -Pandroid.experimental.testOptions.managedDevices.emulator.showKernelLogging=true
3131

3232
- name: Upload test reports
3333
if: success() || failure()

app-nia-catalog/build.gradle.kts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,8 @@ android {
6565
}
6666

6767
dependencies {
68-
implementation(project(":core:ui"))
6968
implementation(project(":core:designsystem"))
70-
71-
implementation(libs.androidx.activity.compose)
69+
implementation(project(":core:ui"))
7270
implementation(libs.accompanist.flowlayout)
71+
implementation(libs.androidx.activity.compose)
7372
}

benchmarks/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,13 @@ android {
6868
}
6969

7070
dependencies {
71+
implementation(libs.androidx.benchmark.macro)
7172
implementation(libs.androidx.test.core)
7273
implementation(libs.androidx.test.espresso.core)
7374
implementation(libs.androidx.test.ext)
74-
implementation(libs.androidx.test.runner)
7575
implementation(libs.androidx.test.rules)
76+
implementation(libs.androidx.test.runner)
7677
implementation(libs.androidx.test.uiautomator)
77-
implementation(libs.androidx.benchmark.macro)
7878
}
7979

8080
androidComponents {

build-logic/convention/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ java {
2727

2828
dependencies {
2929
compileOnly(libs.android.gradlePlugin)
30-
compileOnly(libs.kotlin.gradlePlugin)
31-
compileOnly(libs.firebase.performance.gradle)
3230
compileOnly(libs.firebase.crashlytics.gradle)
31+
compileOnly(libs.firebase.performance.gradle)
32+
compileOnly(libs.kotlin.gradlePlugin)
3333
compileOnly(libs.ksp.gradlePlugin)
3434
}
3535

core/analytics/build.gradle.kts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@ android {
2424
}
2525

2626
dependencies {
27-
implementation(libs.kotlinx.coroutines.android)
27+
implementation(platform(libs.firebase.bom))
2828
implementation(libs.androidx.compose.runtime)
2929
implementation(libs.androidx.core.ktx)
30-
31-
implementation(platform(libs.firebase.bom))
3230
implementation(libs.firebase.analytics)
31+
implementation(libs.kotlinx.coroutines.android)
3332
}

core/data/build.gradle.kts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,24 +25,24 @@ android {
2525
testOptions {
2626
unitTests {
2727
isIncludeAndroidResources = true
28+
isReturnDefaultValues = true
2829
}
2930
}
3031
}
3132

3233
dependencies {
34+
implementation(project(":core:analytics"))
3335
implementation(project(":core:common"))
34-
implementation(project(":core:model"))
3536
implementation(project(":core:database"))
3637
implementation(project(":core:datastore"))
38+
implementation(project(":core:model"))
3739
implementation(project(":core:network"))
38-
implementation(project(":core:analytics"))
39-
40-
testImplementation(project(":core:testing"))
41-
testImplementation(project(":core:datastore-test"))
42-
40+
implementation(project(":core:notifications"))
4341
implementation(libs.androidx.core.ktx)
44-
45-
implementation(libs.kotlinx.datetime)
4642
implementation(libs.kotlinx.coroutines.android)
43+
implementation(libs.kotlinx.datetime)
4744
implementation(libs.kotlinx.serialization.json)
48-
}
45+
46+
testImplementation(project(":core:datastore-test"))
47+
testImplementation(project(":core:testing"))
48+
}

core/data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstNewsRepository.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ import com.google.samples.apps.nowinandroid.core.datastore.ChangeListVersions
3030
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
3131
import com.google.samples.apps.nowinandroid.core.network.NiaNetworkDataSource
3232
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource
33+
import com.google.samples.apps.nowinandroid.core.notifications.Notifier
3334
import kotlinx.coroutines.flow.Flow
35+
import kotlinx.coroutines.flow.first
3436
import kotlinx.coroutines.flow.map
3537
import javax.inject.Inject
3638

@@ -46,6 +48,7 @@ class OfflineFirstNewsRepository @Inject constructor(
4648
private val newsResourceDao: NewsResourceDao,
4749
private val topicDao: TopicDao,
4850
private val network: NiaNetworkDataSource,
51+
private val notifier: Notifier,
4952
) : NewsRepository {
5053

5154
override fun getNewsResources(
@@ -69,6 +72,16 @@ class OfflineFirstNewsRepository @Inject constructor(
6972
},
7073
modelDeleter = newsResourceDao::deleteNewsResources,
7174
modelUpdater = { changedIds ->
75+
// TODO: Make this more efficient, there is no need to retrieve populated
76+
// news resources when all that's needed are the ids
77+
val existingNewsResourceIds = newsResourceDao.getNewsResources(
78+
useFilterNewsIds = true,
79+
filterNewsIds = changedIds.toSet(),
80+
)
81+
.first()
82+
.map { it.entity.id }
83+
.toSet()
84+
7285
changedIds.chunked(SYNC_BATCH_SIZE).forEach { chunkedIds ->
7386
val networkNewsResources = network.getNewsResources(ids = chunkedIds)
7487

@@ -92,6 +105,20 @@ class OfflineFirstNewsRepository @Inject constructor(
92105
.flatten(),
93106
)
94107
}
108+
109+
val addedNewsResources = newsResourceDao.getNewsResources(
110+
useFilterNewsIds = true,
111+
filterNewsIds = changedIds.toSet(),
112+
)
113+
.first()
114+
.filter { !existingNewsResourceIds.contains(it.entity.id) }
115+
.map(PopulatedNewsResource::asExternalModel)
116+
117+
// TODO: Define business logic for notifications on first time sync.
118+
// we probably do not want to send notifications on first install.
119+
// We can easily check if the change list version is 0 and not send notifications
120+
// if it is.
121+
if (addedNewsResources.isNotEmpty()) notifier.onNewsAdded(addedNewsResources)
95122
},
96123
)
97124
}

core/data/src/main/java/com/google/samples/apps/nowinandroid/core/data/util/SyncStatusMonitor.kt renamed to core/data/src/main/java/com/google/samples/apps/nowinandroid/core/data/util/SyncManager.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import kotlinx.coroutines.flow.Flow
2121
/**
2222
* Reports on if synchronization is in progress
2323
*/
24-
interface SyncStatusMonitor {
24+
interface SyncManager {
2525
val isSyncing: Flow<Boolean>
26+
fun requestSync()
2627
}

core/data/src/test/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstNewsRepositoryTest.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import com.google.samples.apps.nowinandroid.core.datastore.test.testUserPreferen
3636
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
3737
import com.google.samples.apps.nowinandroid.core.network.model.NetworkChangeList
3838
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource
39+
import com.google.samples.apps.nowinandroid.core.testing.notifications.TestNotifier
3940
import kotlinx.coroutines.flow.first
4041
import kotlinx.coroutines.test.TestScope
4142
import kotlinx.coroutines.test.UnconfinedTestDispatcher
@@ -58,6 +59,8 @@ class OfflineFirstNewsRepositoryTest {
5859

5960
private lateinit var network: TestNiaNetworkDataSource
6061

62+
private lateinit var notifier: TestNotifier
63+
6164
private lateinit var synchronizer: Synchronizer
6265

6366
@get:Rule
@@ -68,6 +71,7 @@ class OfflineFirstNewsRepositoryTest {
6871
newsResourceDao = TestNewsResourceDao()
6972
topicDao = TestTopicDao()
7073
network = TestNiaNetworkDataSource()
74+
notifier = TestNotifier()
7175
synchronizer = TestSynchronizer(
7276
NiaPreferencesDataSource(
7377
tmpFolder.testUserPreferencesDataStore(testScope),
@@ -78,6 +82,7 @@ class OfflineFirstNewsRepositoryTest {
7882
newsResourceDao = newsResourceDao,
7983
topicDao = topicDao,
8084
network = network,
85+
notifier = notifier,
8186
)
8287
}
8388

@@ -145,6 +150,12 @@ class OfflineFirstNewsRepositoryTest {
145150
expected = network.latestChangeListVersion(CollectionType.NewsResources),
146151
actual = synchronizer.getChangeListVersions().newsResourceVersion,
147152
)
153+
154+
// Notifier should have been called with new news resources
155+
assertEquals(
156+
expected = newsResourcesFromDb.map(NewsResource::id).sorted(),
157+
actual = notifier.addedNewsResources.first().map(NewsResource::id).sorted(),
158+
)
148159
}
149160

150161
@Test
@@ -186,6 +197,13 @@ class OfflineFirstNewsRepositoryTest {
186197
expected = network.latestChangeListVersion(CollectionType.NewsResources),
187198
actual = synchronizer.getChangeListVersions().newsResourceVersion,
188199
)
200+
201+
// Notifier should have been called with news resources from network that are not
202+
// deleted
203+
assertEquals(
204+
expected = (newsResourcesFromNetwork.map(NewsResource::id) - deletedItems).sorted(),
205+
actual = notifier.addedNewsResources.first().map(NewsResource::id).sorted(),
206+
)
189207
}
190208

191209
@Test
@@ -225,6 +243,12 @@ class OfflineFirstNewsRepositoryTest {
225243
expected = changeList.last().changeListVersion,
226244
actual = synchronizer.getChangeListVersions().newsResourceVersion,
227245
)
246+
247+
// Notifier should have been called with only added news resources from network
248+
assertEquals(
249+
expected = newsResourcesFromNetwork.map(NewsResource::id).sorted(),
250+
actual = notifier.addedNewsResources.first().map(NewsResource::id).sorted(),
251+
)
228252
}
229253

230254
@Test

core/datastore-test/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ android {
2424

2525
dependencies {
2626
api(project(":core:datastore"))
27+
api(libs.androidx.dataStore.core)
28+
2729
implementation(project(":core:common"))
2830
implementation(project(":core:testing"))
29-
30-
api(libs.androidx.dataStore.core)
3131
}

0 commit comments

Comments
 (0)