diff --git a/.idea/compiler.xml b/.idea/compiler.xml index fb7f4a8..b589d56 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..0c0c338 --- /dev/null +++ b/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 6e2d26a..872331c 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -4,9 +4,8 @@ diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 0000000..e1eea1d --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index b1f8730..8978d23 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,7 +1,6 @@ - - + diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 28fd290..02f9a12 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -80,7 +80,6 @@ dependencies { implementation(project(":compose-ui")) implementation(project(":feature:home")) implementation(project(":feature:favourite")) - implementation(project(":sync:work")) implementation("io.github.raamcosta.compose-destinations:animations-core:1.7.32-beta") ksp("io.github.raamcosta.compose-destinations:ksp:1.7.32-beta") diff --git a/app/src/main/java/com/swayy/wezacare/HarryPotterApp.kt b/app/src/main/java/com/swayy/wezacare/HarryPotterApp.kt index 0e323d9..62a1b77 100644 --- a/app/src/main/java/com/swayy/wezacare/HarryPotterApp.kt +++ b/app/src/main/java/com/swayy/wezacare/HarryPotterApp.kt @@ -16,7 +16,6 @@ package com.swayy.wezacare import android.app.Application -import com.swayy.work.initializers.Sync import dagger.hilt.android.HiltAndroidApp @HiltAndroidApp @@ -24,6 +23,5 @@ class HarryPotterApp : Application() { override fun onCreate() { super.onCreate() // Initialize Sync; the system responsible for keeping data in the app up to date. - Sync.initialize(context = this) } } diff --git a/app/src/main/java/com/swayy/wezacare/MainActivity.kt b/app/src/main/java/com/swayy/wezacare/MainActivity.kt index 373cd62..43e47a5 100644 --- a/app/src/main/java/com/swayy/wezacare/MainActivity.kt +++ b/app/src/main/java/com/swayy/wezacare/MainActivity.kt @@ -93,7 +93,6 @@ class MainActivity : ComponentActivity() { ) } } - } } } diff --git a/base-module.gradle b/base-module.gradle index a812296..d3b4ef7 100644 --- a/base-module.gradle +++ b/base-module.gradle @@ -125,7 +125,7 @@ dependencies { kaptAndroidTest 'com.google.dagger:hilt-android-compiler:2.38.1' testImplementation 'junit:junit:4.13.2' testImplementation "androidx.test:runner:1.4.0" - testImplementation "com.google.truth:truth:1.1.3" + testImplementation "com.google.truth:truth:1.1.5" testImplementation 'androidx.test:core-ktx:1.4.0' testImplementation "org.robolectric:robolectric:4.5.1" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.4" diff --git a/core-database/src/test/java/com/swayy/core_database/CharactersDatabaseTest.kt b/core-database/src/test/java/com/swayy/core_database/CharactersDatabaseTest.kt new file mode 100644 index 0000000..4670305 --- /dev/null +++ b/core-database/src/test/java/com/swayy/core_database/CharactersDatabaseTest.kt @@ -0,0 +1,164 @@ +package com.swayy.core_database + +import android.content.Context +import androidx.room.PrimaryKey +import androidx.room.Room +import androidx.test.core.app.ApplicationProvider +import androidx.test.runner.AndroidJUnit4 +import com.google.common.truth.Truth +import com.google.gson.Gson +import com.swayy.core_database.converters.Converters +import com.swayy.core_database.dao.CharacterDao +import com.swayy.core_database.model.CharacterEntity +import com.swayy.core_network.model.harrypotter.Wand +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class CharactersDatabaseTest { + + private lateinit var dao: CharacterDao + private lateinit var db: CharactersDatabase + + @Before + fun createDb() { + val context = ApplicationProvider.getApplicationContext() + val converters = Converters(Gson()) + + db = Room.inMemoryDatabaseBuilder( + context, CharactersDatabase::class.java + ) + .addTypeConverter(converters) + .allowMainThreadQueries() + .build() + dao = db.characterDao + } + + @Test + fun `test adding empty list followed by valid data`() = runTest { + dao.insertCharacters(emptyList()) + + Truth.assertThat(dao.getCharacters().isEmpty()) + + dao.insertCharacters( + listOf( + CharacterEntity( + actor = "Gideon", + alive = true, + alternate_actors = emptyList(), + alternate_names = emptyList(), + ancestry = "Chumo", + dateOfBirth = "2002", + eyeColour = "white", + gender = "male", + hairColour = "black", + hogwartsStaff = false, + hogwartsStudent = true, + house = "harryp", + id = "1", + image = "", + name = "gede", + patronus = "Alliance", + species = "animalia", + wand = Wand("", 0.0, ""), + wizard = true, + yearOfBirth = 2001 + ) + ) + ) + + Truth.assertThat(dao.getCharacters().size).isEqualTo(1) + } + + @Test + fun `adding fav to db returns valid data on query`() = runTest { + val entity = CharacterEntity( + actor = "Gideon", + alive = true, + alternate_actors = emptyList(), + alternate_names = emptyList(), + ancestry = "Chumo", + dateOfBirth = "2002", + eyeColour = "white", + gender = "male", + hairColour = "black", + hogwartsStaff = false, + hogwartsStudent = true, + house = "harryp", + id = "1", + image = "", + name = "gede", + patronus = "Alliance", + species = "animalia", + wand = Wand("", 0.0, ""), + wizard = true, + yearOfBirth = 2001 + ) + + dao.insertCharacters(listOf(entity) ) + + Truth.assertThat(dao.getCharacters()).containsExactly(entity) + } + + @Test + fun `deleting fav to db updates properly`() = runTest { + val entity = CharacterEntity( + actor = "Gideon", + alive = true, + alternate_actors = emptyList(), + alternate_names = emptyList(), + ancestry = "Chumo", + dateOfBirth = "2002", + eyeColour = "white", + gender = "male", + hairColour = "black", + hogwartsStaff = false, + hogwartsStudent = true, + house = "harryp", + id = "1", + image = "", + name = "gede", + patronus = "Alliance", + species = "animalia", + wand = Wand("", 0.0, ""), + wizard = true, + yearOfBirth = 2001 + ) + + val entityTwo = CharacterEntity( + actor = "Brian", + alive = true, + alternate_actors = emptyList(), + alternate_names = emptyList(), + ancestry = "Chumo", + dateOfBirth = "2002", + eyeColour = "white", + gender = "male", + hairColour = "black", + hogwartsStaff = false, + hogwartsStudent = true, + house = "harryp", + id = "2", + image = "", + name = "gede", + patronus = "Alliance", + species = "animalia", + wand = Wand("", 0.0, ""), + wizard = true, + yearOfBirth = 2001 + ) + + dao.insertCharacters(listOf(entity,entityTwo) ) + + Truth.assertThat(dao.getCharacters().size).isEqualTo(2) + + dao.deleteCharacters(listOf(entity.id) ) + Truth.assertThat(dao.getCharacters().size).isEqualTo(1) + + dao.deleteCharacters(listOf(entityTwo.id) ) + Truth.assertThat(dao.getCharacters()).isEmpty() + } + +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 79a3ac6..7b06004 100644 --- a/settings.gradle +++ b/settings.gradle @@ -28,6 +28,5 @@ include ':core-database' include ':core-network' include ':feature' include ':feature:home' -include ':sync' include ':sync:work' include ':feature:favourite' diff --git a/sync/work/.gitignore b/sync/work/.gitignore deleted file mode 100644 index 42afabf..0000000 --- a/sync/work/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/sync/work/build.gradle.kts b/sync/work/build.gradle.kts deleted file mode 100644 index 1be3b24..0000000 --- a/sync/work/build.gradle.kts +++ /dev/null @@ -1,69 +0,0 @@ -plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") - id("kotlin-kapt") - id("dagger.hilt.android.plugin") - id("kotlin-parcelize") - id ("org.jetbrains.kotlin.plugin.serialization") -} - -apply { - from("$rootDir/base-module.gradle") -} - -android { - namespace = "com.swayy.work" - compileSdk = 33 - - defaultConfig { - minSdk = 24 - targetSdk = 33 - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = "1.8" - } - buildFeatures { - compose = true - } - composeOptions { - kotlinCompilerExtensionVersion = "1.3.2" - } - packagingOptions { - resources { - excludes += "/META-INF/{AL2.0,LGPL2.1}" - } - } -} - -dependencies { - - implementation(project(":core")) - implementation(project(":core-network")) - implementation(project(":core-database")) - implementation(project(":compose-ui")) - implementation(project(":feature:home")) - - implementation("androidx.core:core-ktx:1.7.0") - implementation("androidx.appcompat:appcompat:1.4.1") - implementation("com.google.android.material:material:1.5.0") - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.5") - androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") -} \ No newline at end of file diff --git a/sync/work/consumer-rules.pro b/sync/work/consumer-rules.pro deleted file mode 100644 index e69de29..0000000 diff --git a/sync/work/proguard-rules.pro b/sync/work/proguard-rules.pro deleted file mode 100644 index 481bb43..0000000 --- a/sync/work/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/sync/work/src/androidTest/java/com/swayy/work/ExampleInstrumentedTest.kt b/sync/work/src/androidTest/java/com/swayy/work/ExampleInstrumentedTest.kt deleted file mode 100644 index 530ac28..0000000 --- a/sync/work/src/androidTest/java/com/swayy/work/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.swayy.work - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.swayy.work.test", appContext.packageName) - } -} \ No newline at end of file diff --git a/sync/work/src/main/AndroidManifest.xml b/sync/work/src/main/AndroidManifest.xml deleted file mode 100644 index a5918e6..0000000 --- a/sync/work/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/sync/work/src/main/java/com/swayy/work/di/DispatchersModule.kt b/sync/work/src/main/java/com/swayy/work/di/DispatchersModule.kt deleted file mode 100644 index 52f75b7..0000000 --- a/sync/work/src/main/java/com/swayy/work/di/DispatchersModule.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swayy.work.di - -import com.swayy.work.workers.Dispatcher -import com.swayy.work.workers.NiaDispatchers -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.Dispatchers - -@Module -@InstallIn(SingletonComponent::class) -object DispatchersModule { - @Provides - @Dispatcher(NiaDispatchers.IO) - fun providesIODispatcher(): CoroutineDispatcher = Dispatchers.IO -} diff --git a/sync/work/src/main/java/com/swayy/work/di/SyncModule.kt b/sync/work/src/main/java/com/swayy/work/di/SyncModule.kt deleted file mode 100644 index b134b38..0000000 --- a/sync/work/src/main/java/com/swayy/work/di/SyncModule.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swayy.work.di - -import com.swayy.work.status.SyncStatusMonitor -import com.swayy.work.status.WorkManagerSyncStatusMonitor -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent - -@Module -@InstallIn(SingletonComponent::class) -interface SyncModule { - @Binds - fun bindsSyncStatusMonitor( - syncStatusMonitor: WorkManagerSyncStatusMonitor, - ): SyncStatusMonitor -} diff --git a/sync/work/src/main/java/com/swayy/work/initializers/SyncInitializer.kt b/sync/work/src/main/java/com/swayy/work/initializers/SyncInitializer.kt deleted file mode 100644 index 5a44a94..0000000 --- a/sync/work/src/main/java/com/swayy/work/initializers/SyncInitializer.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swayy.work.initializers - -import android.content.Context -import androidx.startup.AppInitializer -import androidx.startup.Initializer -import androidx.work.ExistingWorkPolicy -import androidx.work.WorkManager -import androidx.work.WorkManagerInitializer -import com.google.samples.apps.nowinandroid.sync.workers.SyncWorker - -object Sync { - // This method is a workaround to manually initialize the sync process instead of relying on - // automatic initialization with Androidx Startup. It is called from the app module's - // Application.onCreate() and should be only done once. - fun initialize(context: Context) { - AppInitializer.getInstance(context) - .initializeComponent(SyncInitializer::class.java) - } -} - -// This name should not be changed otherwise the app may have concurrent sync requests running -internal const val SyncWorkName = "SyncWorkName" - -/** - * Registers work to sync the data layer periodically on app startup. - */ -class SyncInitializer : Initializer { - override fun create(context: Context): Sync { - WorkManager.getInstance(context).apply { - // Run sync on app startup and ensure only one sync worker runs at any time - enqueueUniqueWork( - SyncWorkName, - ExistingWorkPolicy.KEEP, - SyncWorker.startUpSyncWork(), - ) - } - - return Sync - } - - override fun dependencies(): List>> = - listOf(WorkManagerInitializer::class.java) -} diff --git a/sync/work/src/main/java/com/swayy/work/initializers/SyncWorkHelpers.kt b/sync/work/src/main/java/com/swayy/work/initializers/SyncWorkHelpers.kt deleted file mode 100644 index afeaff3..0000000 --- a/sync/work/src/main/java/com/swayy/work/initializers/SyncWorkHelpers.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swayy.work.initializers - -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.content.Context -import android.os.Build -import androidx.core.app.NotificationCompat -import androidx.work.Constraints -import androidx.work.ForegroundInfo -import androidx.work.NetworkType -import com.swayy.work.R - -private const val SyncNotificationId = 0 -private const val SyncNotificationChannelID = "SyncNotificationChannel" - -// All sync work needs an internet connectionS -val SyncConstraints - get() = Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build() - -/** - * Foreground information for sync on lower API levels when sync workers are being - * run with a foreground service - */ -fun Context.syncForegroundInfo() = ForegroundInfo( - SyncNotificationId, - syncWorkNotification(), -) - -/** - * Notification displayed on lower API levels when sync workers are being - * run with a foreground service - */ -private fun Context.syncWorkNotification(): Notification { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - val channel = NotificationChannel( - SyncNotificationChannelID, - getString(R.string.sync_notification_channel_name), - NotificationManager.IMPORTANCE_DEFAULT, - ).apply { - description = getString(R.string.sync_notification_channel_description) - } - // Register the channel with the system - val notificationManager: NotificationManager? = - getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager - - notificationManager?.createNotificationChannel(channel) - } - - return NotificationCompat.Builder( - this, - SyncNotificationChannelID, - ) - .setSmallIcon( - R.drawable.app, - ) - .setContentTitle(getString(R.string.sync_notification_title)) - .setPriority(NotificationCompat.PRIORITY_DEFAULT) - .build() -} diff --git a/sync/work/src/main/java/com/swayy/work/status/SyncStatusMonitor.kt b/sync/work/src/main/java/com/swayy/work/status/SyncStatusMonitor.kt deleted file mode 100644 index 7285817..0000000 --- a/sync/work/src/main/java/com/swayy/work/status/SyncStatusMonitor.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swayy.work.status - -import kotlinx.coroutines.flow.Flow - -/** - * Reports on if synchronization is in progress - */ -interface SyncStatusMonitor { - val isSyncing: Flow -} diff --git a/sync/work/src/main/java/com/swayy/work/status/WorkManagerSyncStatusMonitor.kt b/sync/work/src/main/java/com/swayy/work/status/WorkManagerSyncStatusMonitor.kt deleted file mode 100644 index 4c24645..0000000 --- a/sync/work/src/main/java/com/swayy/work/status/WorkManagerSyncStatusMonitor.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.swayy.work.status - -import android.content.Context -import androidx.lifecycle.asFlow -import androidx.lifecycle.map -import androidx.work.WorkInfo -import androidx.work.WorkManager -import com.swayy.work.initializers.SyncWorkName -import dagger.hilt.android.qualifiers.ApplicationContext -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.conflate -import javax.inject.Inject - -/** - * [SyncStatusMonitor] backed by [WorkInfo] from [WorkManager] - */ -class WorkManagerSyncStatusMonitor @Inject constructor( - @ApplicationContext context: Context, -) : SyncStatusMonitor { - override val isSyncing: Flow = - WorkManager.getInstance(context).getWorkInfosForUniqueWorkLiveData(SyncWorkName) - .map(MutableList::anyRunning) - .asFlow() - .conflate() -} - -private val List.anyRunning get() = any { it.state == WorkInfo.State.RUNNING } \ No newline at end of file diff --git a/sync/work/src/main/java/com/swayy/work/workers/DelegatingWorker.kt b/sync/work/src/main/java/com/swayy/work/workers/DelegatingWorker.kt deleted file mode 100644 index 0114ad6..0000000 --- a/sync/work/src/main/java/com/swayy/work/workers/DelegatingWorker.kt +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.samples.apps.nowinandroid.sync.workers - -import android.content.Context -import androidx.hilt.work.HiltWorkerFactory -import androidx.work.CoroutineWorker -import androidx.work.Data -import androidx.work.ForegroundInfo -import androidx.work.WorkerParameters -import dagger.hilt.EntryPoint -import dagger.hilt.InstallIn -import dagger.hilt.android.EntryPointAccessors -import dagger.hilt.components.SingletonComponent -import kotlin.reflect.KClass - -/** - * An entry point to retrieve the [HiltWorkerFactory] at runtime - */ -@EntryPoint -@InstallIn(SingletonComponent::class) -interface HiltWorkerFactoryEntryPoint { - fun hiltWorkerFactory(): HiltWorkerFactory -} - -private const val WORKER_CLASS_NAME = "RouterWorkerDelegateClassName" - -/** - * Adds metadata to a WorkRequest to identify what [CoroutineWorker] the [DelegatingWorker] should - * delegate to - */ -internal fun KClass.delegatedData() = - Data.Builder() - .putString(WORKER_CLASS_NAME, qualifiedName) - .build() - -/** - * A worker that delegates sync to another [CoroutineWorker] constructed with a [HiltWorkerFactory]. - * - * This allows for creating and using [CoroutineWorker] instances with extended arguments - * without having to provide a custom WorkManager configuration that the app module needs to utilize. - * - * In other words, it allows for custom workers in a library module without having to own - * configuration of the WorkManager singleton. - */ -class DelegatingWorker( - appContext: Context, - workerParams: WorkerParameters, -) : CoroutineWorker(appContext, workerParams) { - - private val workerClassName = - workerParams.inputData.getString(WORKER_CLASS_NAME) ?: "" - - private val delegateWorker = - EntryPointAccessors.fromApplication(appContext) - .hiltWorkerFactory() - .createWorker(appContext, workerClassName, workerParams) - as? CoroutineWorker - ?: throw IllegalArgumentException("Unable to find appropriate worker") - - override suspend fun getForegroundInfo(): ForegroundInfo = - delegateWorker.getForegroundInfo() - - override suspend fun doWork(): Result = - delegateWorker.doWork() -} diff --git a/sync/work/src/main/java/com/swayy/work/workers/NiaDispatchers.kt b/sync/work/src/main/java/com/swayy/work/workers/NiaDispatchers.kt deleted file mode 100644 index 28a4cf9..0000000 --- a/sync/work/src/main/java/com/swayy/work/workers/NiaDispatchers.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.swayy.work.workers - -import javax.inject.Qualifier -import kotlin.annotation.AnnotationRetention.RUNTIME - -@Qualifier -@Retention(RUNTIME) -annotation class Dispatcher(val niaDispatcher: NiaDispatchers) - -enum class NiaDispatchers { - IO, -} diff --git a/sync/work/src/main/java/com/swayy/work/workers/SyncWorker.kt b/sync/work/src/main/java/com/swayy/work/workers/SyncWorker.kt deleted file mode 100644 index c978cb6..0000000 --- a/sync/work/src/main/java/com/swayy/work/workers/SyncWorker.kt +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.samples.apps.nowinandroid.sync.workers - -import android.content.Context -import androidx.hilt.work.HiltWorker -import androidx.tracing.traceAsync -import androidx.work.CoroutineWorker -import androidx.work.ForegroundInfo -import androidx.work.OneTimeWorkRequestBuilder -import androidx.work.OutOfQuotaPolicy -import androidx.work.WorkerParameters -import com.swayy.home.domain.repository.CharactersRepository -import com.swayy.work.initializers.SyncConstraints -import com.swayy.work.initializers.syncForegroundInfo -import com.swayy.core.work.ChangeListVersions -import com.swayy.work.workers.Dispatcher -import com.swayy.work.workers.NiaDispatchers -import com.swayy.core.work.Synchronizer -import dagger.assisted.Assisted -import dagger.assisted.AssistedInject -import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.withContext - -/** - * Syncs the data layer by delegating to the appropriate repository instances with - * sync functionality. - */ -@HiltWorker -class SyncWorker @AssistedInject constructor( - @Assisted private val appContext: Context, - private val charactersRepository: CharactersRepository, - @Assisted workerParams: WorkerParameters, - @Dispatcher(NiaDispatchers.IO) private val ioDispatcher: CoroutineDispatcher, -) : CoroutineWorker(appContext, workerParams), Synchronizer { - - override suspend fun getForegroundInfo(): ForegroundInfo = - appContext.syncForegroundInfo() - - override suspend fun doWork(): Result = withContext(ioDispatcher) { - traceAsync("Sync", 0) { - - // First sync the repositories in parallel - val syncedSuccessfully = awaitAll( - async { charactersRepository.sync() }, - ).all { it } - - - if (syncedSuccessfully) { - Result.success() - } else { - Result.retry() - } - } - } - - override suspend fun getChangeListVersions(): ChangeListVersions = ChangeListVersions(1,1) - - override suspend fun updateChangeListVersions( - update: ChangeListVersions.() -> ChangeListVersions, - ) = Unit - - companion object { - /** - * Expedited one time work to sync data on app startup - */ - fun startUpSyncWork() = OneTimeWorkRequestBuilder() - .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) - .setConstraints(SyncConstraints) - .setInputData(SyncWorker::class.delegatedData()) - .build() - } -} diff --git a/sync/work/src/main/res/drawable/app.png b/sync/work/src/main/res/drawable/app.png deleted file mode 100644 index 85928b0..0000000 Binary files a/sync/work/src/main/res/drawable/app.png and /dev/null differ diff --git a/sync/work/src/main/res/values/strings.xml b/sync/work/src/main/res/values/strings.xml deleted file mode 100644 index e3fd73f..0000000 --- a/sync/work/src/main/res/values/strings.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - Now in Android - Sync - Background tasks for Now in Android - - diff --git a/sync/work/src/test/java/com/swayy/work/ExampleUnitTest.kt b/sync/work/src/test/java/com/swayy/work/ExampleUnitTest.kt deleted file mode 100644 index a796295..0000000 --- a/sync/work/src/test/java/com/swayy/work/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.swayy.work - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file