From 3f6a12740c51e34997e7db9a0b2cb84a3dac9158 Mon Sep 17 00:00:00 2001
From: Lucas Kivi <125697099+lucas-livefront@users.noreply.github.com>
Date: Tue, 16 Jan 2024 11:43:13 -0600
Subject: [PATCH] BIT-1458: update overlay autofill (#634)
---
.../util/FilledPartitionExtensions.kt | 4 +-
.../ui/autofill/BitwardenRemoteViews.kt | 57 +++-
.../main/res/layout/autofill_remote_view.xml | 44 ++-
.../util/FilledPartitionExtensionsTest.kt | 25 +-
.../ui/autofill/BitwardenRemoteViewsTest.kt | 252 ++++++++++++++++--
5 files changed, 341 insertions(+), 41 deletions(-)
diff --git a/app/src/main/java/com/x8bit/bitwarden/data/autofill/util/FilledPartitionExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/data/autofill/util/FilledPartitionExtensions.kt
index e12f00ce74..72aecde640 100644
--- a/app/src/main/java/com/x8bit/bitwarden/data/autofill/util/FilledPartitionExtensions.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/data/autofill/util/FilledPartitionExtensions.kt
@@ -20,8 +20,8 @@ fun FilledPartition.buildDataset(
autofillAppInfo: AutofillAppInfo,
): Dataset {
val remoteViewsPlaceholder = buildAutofillRemoteViews(
- packageName = autofillAppInfo.packageName,
- title = autofillCipher.name,
+ autofillAppInfo = autofillAppInfo,
+ autofillCipher = autofillCipher,
)
val datasetBuilder = Dataset.Builder()
diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/autofill/BitwardenRemoteViews.kt b/app/src/main/java/com/x8bit/bitwarden/ui/autofill/BitwardenRemoteViews.kt
index 8ccea2cb49..cecdde36d3 100644
--- a/app/src/main/java/com/x8bit/bitwarden/ui/autofill/BitwardenRemoteViews.kt
+++ b/app/src/main/java/com/x8bit/bitwarden/ui/autofill/BitwardenRemoteViews.kt
@@ -1,22 +1,69 @@
package com.x8bit.bitwarden.ui.autofill
+import android.content.Context
import android.widget.RemoteViews
import com.x8bit.bitwarden.R
+import com.x8bit.bitwarden.data.autofill.model.AutofillAppInfo
+import com.x8bit.bitwarden.data.autofill.model.AutofillCipher
+import com.x8bit.bitwarden.ui.autofill.util.isSystemDarkMode
/**
* Build [RemoteViews] for representing an autofill suggestion.
*/
fun buildAutofillRemoteViews(
- packageName: String,
- title: String,
+ autofillAppInfo: AutofillAppInfo,
+ autofillCipher: AutofillCipher,
): RemoteViews =
RemoteViews(
- packageName,
+ autofillAppInfo.packageName,
R.layout.autofill_remote_view,
)
.apply {
setTextViewText(
- R.id.text,
- title,
+ R.id.title,
+ autofillCipher.name,
+ )
+ setTextViewText(
+ R.id.subtitle,
+ autofillCipher.subtitle,
+ )
+ setImageViewResource(
+ R.id.icon,
+ autofillCipher.iconRes,
+ )
+
+ setInt(
+ R.id.container,
+ "setBackgroundColor",
+ autofillAppInfo.context.surface,
+ )
+ setInt(
+ R.id.icon,
+ "setColorFilter",
+ autofillAppInfo.context.onSurface,
+ )
+ setInt(
+ R.id.title,
+ "setTextColor",
+ autofillAppInfo.context.onSurface,
+ )
+ setInt(
+ R.id.subtitle,
+ "setTextColor",
+ autofillAppInfo.context.onSurfaceVariant,
)
}
+
+private val Context.onSurface: Int
+ get() = getColor(
+ if (isSystemDarkMode) R.color.dark_on_surface else R.color.on_surface,
+ )
+private val Context.onSurfaceVariant: Int
+ get() = getColor(
+ if (isSystemDarkMode) R.color.dark_on_surface_variant else R.color.on_surface_variant,
+ )
+
+private val Context.surface: Int
+ get() = getColor(
+ if (isSystemDarkMode) R.color.dark_surface else R.color.surface,
+ )
diff --git a/app/src/main/res/layout/autofill_remote_view.xml b/app/src/main/res/layout/autofill_remote_view.xml
index b433796732..36eee78dcb 100644
--- a/app/src/main/res/layout/autofill_remote_view.xml
+++ b/app/src/main/res/layout/autofill_remote_view.xml
@@ -1,6 +1,40 @@
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/test/java/com/x8bit/bitwarden/data/autofill/util/FilledPartitionExtensionsTest.kt b/app/src/test/java/com/x8bit/bitwarden/data/autofill/util/FilledPartitionExtensionsTest.kt
index c693f9dac9..07620ead6a 100644
--- a/app/src/test/java/com/x8bit/bitwarden/data/autofill/util/FilledPartitionExtensionsTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/data/autofill/util/FilledPartitionExtensionsTest.kt
@@ -81,8 +81,8 @@ class FilledPartitionExtensionsTest {
val inlinePresentation: InlinePresentation = mockk()
every {
buildAutofillRemoteViews(
- packageName = PACKAGE_NAME,
- title = CIPHER_NAME,
+ autofillAppInfo = autofillAppInfo,
+ autofillCipher = autofillCipher,
)
} returns remoteViews
every {
@@ -110,8 +110,8 @@ class FilledPartitionExtensionsTest {
assertEquals(dataset, actual)
verify(exactly = 1) {
buildAutofillRemoteViews(
- packageName = PACKAGE_NAME,
- title = CIPHER_NAME,
+ autofillAppInfo = autofillAppInfo,
+ autofillCipher = autofillCipher,
)
inlinePresentationSpec.createCipherInlinePresentationOrNull(
autofillAppInfo = autofillAppInfo,
@@ -137,11 +137,10 @@ class FilledPartitionExtensionsTest {
packageName = PACKAGE_NAME,
sdkInt = 18,
)
- val inlinePresentation: InlinePresentation = mockk()
every {
buildAutofillRemoteViews(
- packageName = PACKAGE_NAME,
- title = CIPHER_NAME,
+ autofillAppInfo = autofillAppInfo,
+ autofillCipher = autofillCipher,
)
} returns remoteViews
every {
@@ -160,8 +159,8 @@ class FilledPartitionExtensionsTest {
assertEquals(dataset, actual)
verify(exactly = 1) {
buildAutofillRemoteViews(
- packageName = PACKAGE_NAME,
- title = CIPHER_NAME,
+ autofillAppInfo = autofillAppInfo,
+ autofillCipher = autofillCipher,
)
filledItem.applyToDatasetPreTiramisu(
datasetBuilder = any(),
@@ -183,8 +182,8 @@ class FilledPartitionExtensionsTest {
val inlinePresentation: InlinePresentation = mockk()
every {
buildAutofillRemoteViews(
- packageName = PACKAGE_NAME,
- title = CIPHER_NAME,
+ autofillAppInfo = autofillAppInfo,
+ autofillCipher = autofillCipher,
)
} returns remoteViews
every {
@@ -210,8 +209,8 @@ class FilledPartitionExtensionsTest {
assertEquals(dataset, actual)
verify(exactly = 1) {
buildAutofillRemoteViews(
- packageName = PACKAGE_NAME,
- title = CIPHER_NAME,
+ autofillAppInfo = autofillAppInfo,
+ autofillCipher = autofillCipher,
)
inlinePresentationSpec.createCipherInlinePresentationOrNull(
autofillAppInfo = autofillAppInfo,
diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/autofill/BitwardenRemoteViewsTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/autofill/BitwardenRemoteViewsTest.kt
index 6f92e44732..068b90186f 100644
--- a/app/src/test/java/com/x8bit/bitwarden/ui/autofill/BitwardenRemoteViewsTest.kt
+++ b/app/src/test/java/com/x8bit/bitwarden/ui/autofill/BitwardenRemoteViewsTest.kt
@@ -1,52 +1,119 @@
package com.x8bit.bitwarden.ui.autofill
-import android.content.res.Resources
+import android.content.Context
import android.widget.RemoteViews
import com.x8bit.bitwarden.R
-import io.mockk.confirmVerified
+import com.x8bit.bitwarden.data.autofill.model.AutofillAppInfo
+import com.x8bit.bitwarden.data.autofill.model.AutofillCipher
+import com.x8bit.bitwarden.ui.autofill.util.isSystemDarkMode
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.mockkConstructor
+import io.mockk.mockkStatic
import io.mockk.runs
import io.mockk.unmockkConstructor
+import io.mockk.unmockkStatic
import io.mockk.verify
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
class BitwardenRemoteViewsTest {
- private val testResources: Resources = mockk()
+ private val testContext: Context = mockk {
+ every { this@mockk.getColor(R.color.dark_on_surface) } returns DARK_ON_SURFACE_COLOR
+ every {
+ this@mockk.getColor(R.color.dark_on_surface_variant)
+ } returns DARK_ON_SURFACE_VARIANT_COLOR
+ every { this@mockk.getColor(R.color.dark_surface) } returns DARK_SURFACE_COLOR
+ every { this@mockk.getColor(R.color.on_surface) } returns ON_SURFACE_COLOR
+ every { this@mockk.getColor(R.color.on_surface_variant) } returns ON_SURFACE_VARIANT_COLOR
+ every { this@mockk.getColor(R.color.surface) } returns SURFACE_COLOR
+ }
+ private val autofillAppInfo: AutofillAppInfo = mockk {
+ every { this@mockk.context } returns testContext
+ every { this@mockk.packageName } returns PACKAGE_NAME
+ }
+ private val autofillCipher: AutofillCipher = mockk {
+ every { this@mockk.iconRes } returns ICON_RES
+ every { this@mockk.name } returns NAME
+ every { this@mockk.subtitle } returns SUBTITLE
+ }
@BeforeEach
fun setup() {
+ mockkStatic(Context::isSystemDarkMode)
mockkConstructor(RemoteViews::class)
}
@AfterEach
fun teardown() {
+ unmockkStatic(Context::isSystemDarkMode)
unmockkConstructor(RemoteViews::class)
- confirmVerified(
- testResources,
- )
}
@Test
- fun `buildAutofillRemoteViews should set text`() {
+ fun `buildAutofillRemoteViews should set values and light mode colors when not night mode`() {
// Setup
- val title = "Bitwarden"
+ every { testContext.isSystemDarkMode } returns false
every {
anyConstructed()
.setTextViewText(
- R.id.text,
- title,
+ R.id.title,
+ NAME,
+ )
+ } just runs
+ every {
+ anyConstructed()
+ .setTextViewText(
+ R.id.subtitle,
+ SUBTITLE,
+ )
+ } just runs
+ every {
+ anyConstructed()
+ .setImageViewResource(
+ R.id.icon,
+ ICON_RES,
+ )
+ } just runs
+ every {
+ anyConstructed()
+ .setInt(
+ R.id.container,
+ "setBackgroundColor",
+ SURFACE_COLOR,
+ )
+ } just runs
+ every {
+ anyConstructed()
+ .setInt(
+ R.id.icon,
+ "setColorFilter",
+ ON_SURFACE_COLOR,
+ )
+ } just runs
+ every {
+ anyConstructed()
+ .setInt(
+ R.id.title,
+ "setTextColor",
+ ON_SURFACE_COLOR,
+ )
+ } just runs
+ every {
+ anyConstructed()
+ .setInt(
+ R.id.subtitle,
+ "setTextColor",
+ ON_SURFACE_VARIANT_COLOR,
)
} just runs
// Test
buildAutofillRemoteViews(
- title = title,
- packageName = PACKAGE_NAME,
+ autofillAppInfo = autofillAppInfo,
+ autofillCipher = autofillCipher,
)
// Note: impossible to do a useful test of the returned RemoteViews due to mockking
@@ -57,13 +124,166 @@ class BitwardenRemoteViewsTest {
verify(exactly = 1) {
anyConstructed()
.setTextViewText(
- R.id.text,
- title,
+ R.id.title,
+ NAME,
+ )
+ anyConstructed()
+ .setTextViewText(
+ R.id.subtitle,
+ SUBTITLE,
+ )
+ anyConstructed()
+ .setImageViewResource(
+ R.id.icon,
+ ICON_RES,
+ )
+ anyConstructed()
+ .setInt(
+ R.id.container,
+ "setBackgroundColor",
+ SURFACE_COLOR,
+ )
+ anyConstructed()
+ .setInt(
+ R.id.icon,
+ "setColorFilter",
+ ON_SURFACE_COLOR,
+ )
+ anyConstructed()
+ .setInt(
+ R.id.title,
+ "setTextColor",
+ ON_SURFACE_COLOR,
+ )
+ anyConstructed()
+ .setInt(
+ R.id.subtitle,
+ "setTextColor",
+ ON_SURFACE_VARIANT_COLOR,
)
}
}
- companion object {
- private const val PACKAGE_NAME: String = "com.x8bit.bitwarden"
+ @Test
+ fun `buildAutofillRemoteViews should set values and dark mode colors when night mode`() {
+ // Setup
+ every { testContext.isSystemDarkMode } returns true
+ every {
+ anyConstructed()
+ .setTextViewText(
+ R.id.title,
+ NAME,
+ )
+ } just runs
+ every {
+ anyConstructed()
+ .setTextViewText(
+ R.id.subtitle,
+ SUBTITLE,
+ )
+ } just runs
+ every {
+ anyConstructed()
+ .setImageViewResource(
+ R.id.icon,
+ ICON_RES,
+ )
+ } just runs
+ every {
+ anyConstructed()
+ .setInt(
+ R.id.container,
+ "setBackgroundColor",
+ DARK_SURFACE_COLOR,
+ )
+ } just runs
+ every {
+ anyConstructed()
+ .setInt(
+ R.id.icon,
+ "setColorFilter",
+ DARK_ON_SURFACE_COLOR,
+ )
+ } just runs
+ every {
+ anyConstructed()
+ .setInt(
+ R.id.title,
+ "setTextColor",
+ DARK_ON_SURFACE_COLOR,
+ )
+ } just runs
+ every {
+ anyConstructed()
+ .setInt(
+ R.id.subtitle,
+ "setTextColor",
+ DARK_ON_SURFACE_VARIANT_COLOR,
+ )
+ } just runs
+
+ // Test
+ buildAutofillRemoteViews(
+ autofillAppInfo = autofillAppInfo,
+ autofillCipher = autofillCipher,
+ )
+
+ // Note: impossible to do a useful test of the returned RemoteViews due to mockking
+ // constraints of the [RemoteViews] constructor. Our best bet is to make sure the correct
+ // operations are performed on the constructed [RemoteViews].
+
+ // Verify
+ verify(exactly = 1) {
+ anyConstructed()
+ .setTextViewText(
+ R.id.title,
+ NAME,
+ )
+ anyConstructed()
+ .setTextViewText(
+ R.id.subtitle,
+ SUBTITLE,
+ )
+ anyConstructed()
+ .setImageViewResource(
+ R.id.icon,
+ ICON_RES,
+ )
+ anyConstructed()
+ .setInt(
+ R.id.container,
+ "setBackgroundColor",
+ DARK_SURFACE_COLOR,
+ )
+ anyConstructed()
+ .setInt(
+ R.id.icon,
+ "setColorFilter",
+ DARK_ON_SURFACE_COLOR,
+ )
+ anyConstructed()
+ .setInt(
+ R.id.title,
+ "setTextColor",
+ DARK_ON_SURFACE_COLOR,
+ )
+ anyConstructed()
+ .setInt(
+ R.id.subtitle,
+ "setTextColor",
+ DARK_ON_SURFACE_VARIANT_COLOR,
+ )
+ }
}
}
+
+private const val DARK_ON_SURFACE_COLOR: Int = 321
+private const val DARK_ON_SURFACE_VARIANT_COLOR: Int = 654
+private const val DARK_SURFACE_COLOR: Int = 987
+private const val ICON_RES: Int = 41421421
+private const val NAME: String = "NAME"
+private const val ON_SURFACE_COLOR: Int = 123
+private const val ON_SURFACE_VARIANT_COLOR: Int = 456
+private const val PACKAGE_NAME: String = "com.x8bit.bitwarden"
+private const val SUBTITLE: String = "SUBTITLE"
+private const val SURFACE_COLOR: Int = 789