feat: route board cards to full card detail screen

This commit is contained in:
2026-03-16 22:51:55 -04:00
parent 344c5a4faa
commit 78b34ecef2
5 changed files with 31 additions and 33 deletions

View File

@@ -795,12 +795,13 @@ class BoardDetailFlowTest {
onView(withText("Card 1")).perform(click()) onView(withText("Card 1")).perform(click())
Intents.intended(hasComponent(CardDetailActivity::class.java.name)) Intents.intended(hasComponent(CardDetailActivity::class.java.name))
Intents.intended(not(hasComponent("space.hackenslacker.kanbn4droid.app.CardDetailPlaceholderActivity")))
Intents.intended(hasExtra(CardDetailActivity.EXTRA_CARD_ID, "card-1")) Intents.intended(hasExtra(CardDetailActivity.EXTRA_CARD_ID, "card-1"))
Intents.intended(hasExtra(CardDetailActivity.EXTRA_CARD_TITLE, "Card 1")) Intents.intended(hasExtra(CardDetailActivity.EXTRA_CARD_TITLE, "Card 1"))
} }
@Test @Test
fun cardTapBlankTitle_usesCardFallbackInPlaceholderExtra() { fun cardTapBlankTitle_usesCardFallbackInCardDetailExtra() {
defaultDataSource.currentDetail = detailWithCardTitle(" ") defaultDataSource.currentDetail = detailWithCardTitle(" ")
launchBoardDetail() launchBoardDetail()
@@ -809,6 +810,7 @@ class BoardDetailFlowTest {
.getString(R.string.card_detail_placeholder_fallback_title) .getString(R.string.card_detail_placeholder_fallback_title)
Intents.intended(hasComponent(CardDetailActivity::class.java.name)) Intents.intended(hasComponent(CardDetailActivity::class.java.name))
Intents.intended(not(hasComponent("space.hackenslacker.kanbn4droid.app.CardDetailPlaceholderActivity")))
Intents.intended(hasExtra(CardDetailActivity.EXTRA_CARD_ID, "card-1")) Intents.intended(hasExtra(CardDetailActivity.EXTRA_CARD_ID, "card-1"))
Intents.intended(hasExtra(CardDetailActivity.EXTRA_CARD_TITLE, expectedFallback)) Intents.intended(hasExtra(CardDetailActivity.EXTRA_CARD_TITLE, expectedFallback))
} }

View File

@@ -1,11 +1,14 @@
package space.hackenslacker.kanbn4droid.app package space.hackenslacker.kanbn4droid.app
import android.content.Intent import android.content.Intent
import android.content.ComponentName
import android.content.pm.PackageManager
import android.graphics.Color import android.graphics.Color
import android.view.View import android.view.View
import android.widget.TextView import android.widget.TextView
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import androidx.test.core.app.ActivityScenario import androidx.test.core.app.ActivityScenario
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.closeSoftKeyboard import androidx.test.espresso.action.ViewActions.closeSoftKeyboard
@@ -237,6 +240,22 @@ class CardDetailFlowTest {
onView(withId(R.id.cardDetailTitleSavingText)).check(matches(not(isDisplayed()))) onView(withId(R.id.cardDetailTitleSavingText)).check(matches(not(isDisplayed())))
} }
@Test
fun placeholderCardDetailRouteIsNotDeclaredInManifest() {
val context = ApplicationProvider.getApplicationContext<android.content.Context>()
val placeholderComponent = ComponentName(
context.packageName,
"space.hackenslacker.kanbn4droid.app.CardDetailPlaceholderActivity",
)
val isDeclared = runCatching {
@Suppress("DEPRECATION")
context.packageManager.getActivityInfo(placeholderComponent, PackageManager.GET_META_DATA)
}.isSuccess
assertTrue(!isDeclared)
}
private fun launchCardDetail( private fun launchCardDetail(
cardId: String? = "card-1", cardId: String? = "card-1",
waitForContent: Boolean = true, waitForContent: Boolean = true,

View File

@@ -14,9 +14,6 @@
<activity <activity
android:name=".carddetail.CardDetailActivity" android:name=".carddetail.CardDetailActivity"
android:exported="false" /> android:exported="false" />
<activity
android:name=".CardDetailPlaceholderActivity"
android:exported="false" />
<activity <activity
android:name=".boarddetail.BoardDetailActivity" android:name=".boarddetail.BoardDetailActivity"
android:exported="false" /> android:exported="false" />

View File

@@ -1,24 +0,0 @@
package space.hackenslacker.kanbn4droid.app
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
class CardDetailPlaceholderActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_card_detail_placeholder)
val cardId = intent.getStringExtra(EXTRA_CARD_ID).orEmpty()
val cardTitle = intent.getStringExtra(EXTRA_CARD_TITLE).orEmpty()
val titleView: TextView = findViewById(R.id.cardDetailPlaceholderTitle)
titleView.text = getString(R.string.card_detail_placeholder_title, cardTitle, cardId)
}
companion object {
const val EXTRA_CARD_ID = "extra_card_id"
const val EXTRA_CARD_TITLE = "extra_card_title"
}
}

View File

@@ -242,11 +242,7 @@ class BoardDetailActivity : AppCompatActivity() {
.orEmpty() .orEmpty()
.trim() .trim()
.ifBlank { getString(R.string.card_detail_placeholder_fallback_title) } .ifBlank { getString(R.string.card_detail_placeholder_fallback_title) }
startActivity( openCardDetail(cardId = event.cardId, cardTitle = cardTitle)
Intent(this@BoardDetailActivity, CardDetailActivity::class.java)
.putExtra(CardDetailActivity.EXTRA_CARD_ID, event.cardId)
.putExtra(CardDetailActivity.EXTRA_CARD_TITLE, cardTitle),
)
} }
is BoardDetailUiEvent.ShowServerError -> { is BoardDetailUiEvent.ShowServerError -> {
@@ -339,6 +335,14 @@ class BoardDetailActivity : AppCompatActivity() {
.show() .show()
} }
private fun openCardDetail(cardId: String, cardTitle: String) {
startActivity(
Intent(this, CardDetailActivity::class.java)
.putExtra(CardDetailActivity.EXTRA_CARD_ID, cardId)
.putExtra(CardDetailActivity.EXTRA_CARD_TITLE, cardTitle),
)
}
private fun renderOpenDialogs(state: BoardDetailUiState) { private fun renderOpenDialogs(state: BoardDetailUiState) {
if (state.isFabChooserOpen && fabChooserDialog == null) { if (state.isFabChooserOpen && fabChooserDialog == null) {
showFabChooserDialog(state) showFabChooserDialog(state)