From 0851a5e15f384ba46c6b134919aec1457148b967 Mon Sep 17 00:00:00 2001 From: pacjo Date: Tue, 22 Apr 2025 15:36:44 +0200 Subject: [PATCH] add basic smartspacer support --- app/build.gradle.kts | 1 + app/src/main/AndroidManifest.xml | 12 ++ .../parceltracker/NotificationWorker.kt | 5 + .../smartspacer/targets/ParcelStatusTarget.kt | 105 ++++++++++++++++++ gradle/libs.versions.toml | 2 + 5 files changed, 125 insertions(+) create mode 100644 app/src/main/java/dev/itsvic/parceltracker/smartspacer/targets/ParcelStatusTarget.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0c1ab86..07f4fe7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -117,6 +117,7 @@ dependencies { implementation(libs.work.runtime.ktx) implementation(libs.kotlinx.coroutines.guava) implementation(libs.androidx.browser) + implementation(libs.smartspacer) ksp(libs.room.compiler) ksp(libs.moshi.kotlin.codegen) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 22de8c1..edcf28d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,6 +5,8 @@ + + + + + + + + diff --git a/app/src/main/java/dev/itsvic/parceltracker/NotificationWorker.kt b/app/src/main/java/dev/itsvic/parceltracker/NotificationWorker.kt index 5c2354c..9c61f05 100644 --- a/app/src/main/java/dev/itsvic/parceltracker/NotificationWorker.kt +++ b/app/src/main/java/dev/itsvic/parceltracker/NotificationWorker.kt @@ -11,8 +11,10 @@ import androidx.work.PeriodicWorkRequestBuilder import androidx.work.WorkInfo import androidx.work.WorkManager import androidx.work.WorkerParameters +import com.kieronquinn.app.smartspacer.sdk.provider.SmartspacerTargetProvider import dev.itsvic.parceltracker.api.getParcel import dev.itsvic.parceltracker.db.ParcelStatus +import dev.itsvic.parceltracker.smartspacer.targets.ParcelStatusTarget import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map @@ -80,6 +82,9 @@ class NotificationWorker(context: Context, params: WorkerParameters) : } } + // TODO: this most likely has to be moved + SmartspacerTargetProvider.notifyChange(applicationContext, ParcelStatusTarget::class.java) + return Result.success() } } diff --git a/app/src/main/java/dev/itsvic/parceltracker/smartspacer/targets/ParcelStatusTarget.kt b/app/src/main/java/dev/itsvic/parceltracker/smartspacer/targets/ParcelStatusTarget.kt new file mode 100644 index 0000000..a5def5a --- /dev/null +++ b/app/src/main/java/dev/itsvic/parceltracker/smartspacer/targets/ParcelStatusTarget.kt @@ -0,0 +1,105 @@ +package dev.itsvic.parceltracker.smartspacer.targets + +import android.content.ComponentName +import android.util.Log +import android.graphics.drawable.Icon as AndroidIcon +import com.kieronquinn.app.smartspacer.sdk.model.SmartspaceTarget +import com.kieronquinn.app.smartspacer.sdk.model.uitemplatedata.Icon +import com.kieronquinn.app.smartspacer.sdk.model.uitemplatedata.Text +import com.kieronquinn.app.smartspacer.sdk.provider.SmartspacerTargetProvider +import com.kieronquinn.app.smartspacer.sdk.utils.TargetTemplate +import dev.itsvic.parceltracker.ParcelApplication +import dev.itsvic.parceltracker.R +import dev.itsvic.parceltracker.api.Status +import dev.itsvic.parceltracker.api.getParcel +import dev.itsvic.parceltracker.db.ParcelWithStatus +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlin.String + +class ParcelStatusTarget: SmartspacerTargetProvider() { + override fun getSmartspaceTargets(smartspacerId: String): List { + val targets = mutableListOf() + + val db = ParcelApplication.db + val parcels: List = runBlocking(Dispatchers.IO) { + db.parcelDao().getAllNonArchivedWithStatusAsync() + } + + // this doesn't limit the number of returned targets + // it probably should, but I don't know whether to hardcode it or make configurable + + parcels.forEach { parcelWithStatus -> + val parcel = parcelWithStatus.parcel + + val apiParcel = try { + runBlocking(Dispatchers.IO) { + provideContext().getParcel(parcel.parcelId, parcel.postalCode, parcel.service) + } + } catch (e: Exception) { + Log.d(TAG, "Failed to fetch, skipping", e) + + return@forEach + } + + // TODO: is the one from API or db preferred + val status = apiParcel.currentStatus //parcelWithStatus.status?.status + + targets.add( + TargetTemplate.Basic( + id = "parcel_status_$smartspacerId", + componentName = ComponentName( + provideContext(), + ParcelStatusTarget::class.java + ), +// featureType = SmartspaceTarget.FEATURE_PACKAGE_TRACKING, + title = Text("${parcel.humanName}: ${status.name}"), + subtitle = Text(apiParcel.history.first().description), + icon = Icon( + AndroidIcon.createWithResource( + provideContext(), + // this when is the same as the one in ParcelRow, maybe unify those two? + when (status) { + Status.Preadvice -> R.drawable.outline_other_admission_24 + Status.InTransit -> R.drawable.outline_local_shipping_24 + Status.InWarehouse -> R.drawable.outline_warehouse_24 + Status.Customs -> R.drawable.outline_search_24 + Status.OutForDelivery -> R.drawable.outline_local_shipping_24 + Status.DeliveryFailure -> R.drawable.outline_error_24 + Status.AwaitingPickup -> R.drawable.outline_pin_drop_24 + Status.Delivered, Status.PickedUp -> R.drawable.outline_check_24 + + else -> R.drawable.outline_question_mark_24 + } + ) + ), + onClick = null // TODO: change + ).create().apply { + isSensitive = true + canBeDismissed = false + }) + } + + return targets + } + + override fun getConfig(smartspacerId: String?): Config { + return Config( + label = "Parcel Status", + description = "Shows the current status of a selected parcel", + icon = AndroidIcon.createWithResource(provideContext(), R.drawable.package_2), + allowAddingMoreThanOnce = true, +// configActivity = // Optional: An Intent given as an option to the user in the settings UI after adding +// setupActivity = // Optional: An Intent of an Activity presented to the user during setup (see below) + ) + } + + override fun onDismiss(smartspacerId: String, targetId: String): Boolean { + return false + } + + companion object { + private const val TAG = "ParcelStatusTarget" + } + +} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1a187b2..a1e6be3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,6 +21,7 @@ work = "2.10.0" kotlinxCoroutinesGuava = "1.10.1" material3 = "1.4.0-alpha11" browser = "1.8.0" +smartspacer = "1.1" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -57,6 +58,7 @@ work-runtime = { group = "androidx.work", name = "work-runtime", version.ref = " work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work" } kotlinx-coroutines-guava = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-guava", version.ref = "kotlinxCoroutinesGuava" } androidx-browser = { group = "androidx.browser", name = "browser", version.ref = "browser" } +smartspacer = { group = "com.kieronquinn.smartspacer", name = "sdk-plugin", version.ref = "smartspacer" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" }