feat: scaffold boards drawer layout and UI resources

This commit is contained in:
2026-03-18 08:16:27 -04:00
parent 96e971229a
commit 717c87122d
6 changed files with 186 additions and 45 deletions

View File

@@ -2,7 +2,11 @@ package space.hackenslacker.kanbn4droid.app
import androidx.test.core.app.ActivityScenario
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.ViewAction
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.GeneralSwipeAction
import androidx.test.espresso.action.Press
import androidx.test.espresso.action.Swipe
import androidx.test.espresso.action.ViewActions.longClick
import androidx.test.espresso.action.ViewActions.replaceText
import androidx.test.espresso.action.ViewActions.swipeDown
@@ -16,6 +20,7 @@ import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.runners.AndroidJUnit4
import kotlin.math.roundToInt
import org.junit.After
import org.junit.Before
import org.junit.Test
@@ -117,6 +122,38 @@ class BoardsFlowTest {
onView(withText("Alpha")).check(matches(isDisplayed()))
}
@Test
fun drawerOpensAndShowsWorkspaceSection() {
MainActivity.dependencies.apiClientFactory = {
FakeBoardsApiClient(
boards = mutableListOf(BoardSummary("1", "Alpha")),
templates = emptyList(),
)
}
ActivityScenario.launch(BoardsActivity::class.java)
onView(withId(android.R.id.content)).perform(swipeFromLeftEdge())
onView(withText("Workspaces")).check(matches(isDisplayed()))
onView(withText("Alpha")).check(matches(isDisplayed()))
}
private fun swipeFromLeftEdge(): ViewAction {
return GeneralSwipeAction(
Swipe.FAST,
{ view ->
val x = (view.width * 0.02f).roundToInt().toFloat()
floatArrayOf(x, view.height * 0.5f)
},
{ view ->
val x = (view.width * 0.8f).roundToInt().toFloat()
floatArrayOf(x, view.height * 0.5f)
},
Press.FINGER,
)
}
private class InMemorySessionStore(
private var baseUrl: String? = null,
) : SessionStore {

View File

@@ -1,60 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/boardsDrawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/boardsToolbar"
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.MaterialComponents.ActionBar"
app:title="@string/boards_title" />
android:layout_height="match_parent">
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/boardsSwipeRefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize">
<FrameLayout
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/boardsToolbar"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.MaterialComponents.ActionBar"
app:title="@string/boards_title" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/boardsRecyclerView"
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/boardsSwipeRefresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:padding="16dp" />
>
<TextView
android:id="@+id/boardsEmptyStateText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/boards_empty_state"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/boardsRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:padding="16dp" />
<ProgressBar
android:id="@+id/boardsInitialProgress"
style="@style/Widget.AppCompat.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<TextView
android:id="@+id/boardsEmptyStateText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:text="@string/boards_empty_state"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:visibility="gone" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/createBoardFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:contentDescription="@string/create_board"
app:srcCompat="@android:drawable/ic_input_add" />
<ProgressBar
android:id="@+id/boardsInitialProgress"
style="@style/Widget.AppCompat.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/createBoardFab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:contentDescription="@string/create_board"
app:srcCompat="@android:drawable/ic_input_add" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<include
layout="@layout/view_boards_drawer"
android:layout_width="@dimen/boards_drawer_max_width"
android:layout_height="match_parent"
android:layout_gravity="start" />
</androidx.drawerlayout.widget.DrawerLayout>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
app:cardCornerRadius="12dp"
app:strokeWidth="1dp">
<TextView
android:id="@+id/workspaceTitleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
android:paddingTop="12dp"
android:paddingEnd="16dp"
android:paddingBottom="12dp"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" />
</com.google.android.material.card.MaterialCardView>

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/colorSurface"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingTop="24dp"
android:paddingEnd="16dp"
android:paddingBottom="16dp">
<TextView
android:id="@+id/drawerUsernameText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/drawer_profile_unavailable"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
android:textStyle="bold" />
<TextView
android:id="@+id/drawerEmailText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/drawer_profile_unavailable"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2" />
<Button
android:id="@+id/drawerSettingsButton"
style="?attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/drawer_settings" />
<TextView
android:id="@+id/drawerWorkspacesTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/drawer_workspaces"
android:textAppearance="@style/TextAppearance.MaterialComponents.Overline" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/drawerWorkspacesRecyclerView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:layout_weight="1"
android:clipToPadding="false"
android:paddingBottom="8dp" />
<Button
android:id="@+id/drawerLogoutButton"
style="?attr/materialButtonOutlinedStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/drawer_logout" />
</LinearLayout>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="boards_drawer_max_width">360dp</dimen>
</resources>

View File

@@ -84,4 +84,11 @@
<string name="add">Add</string>
<string name="card_detail_comment_required">Comment is required</string>
<string name="card_detail_comment_added">Comment added</string>
<string name="drawer_settings">Settings</string>
<string name="drawer_workspaces">Workspaces</string>
<string name="drawer_logout">Log out</string>
<string name="drawer_retry">Retry</string>
<string name="drawer_profile_unavailable">Profile unavailable</string>
<string name="drawer_workspaces_unavailable">Workspaces unavailable</string>
<string name="drawer_loading">Loading...</string>
</resources>