Skip to content

Commit

Permalink
Merge pull request #37 from ddyeon/feature/storage
Browse files Browse the repository at this point in the history
보관함 탭 UI 개발
  • Loading branch information
ddyeon authored Jun 29, 2024
2 parents 4439d57 + 35a0e04 commit f5559ec
Show file tree
Hide file tree
Showing 18 changed files with 495 additions and 2 deletions.
3 changes: 2 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,13 @@ android {
}

dependencies {
implementation(project(":feature:home"))
implementation(project(":domain"))
implementation(project(":data"))
implementation(project(":core:coroutine"))
implementation(project(":core:designsystem"))
implementation(project(":core:navigation"))
implementation(project(":feature:home"))
implementation(project(":feature:storage"))

implementation(libs.core.ktx)
implementation(libs.kotlin.android)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.navigation.compose.rememberNavController
import androidx.navigation.navOptions
import com.mashup.dorabangs.core.designsystem.component.bottomnavigation.BottomNavigationDestination
import com.mashup.dorabangs.feature.navigation.navigateToHome
import com.mashup.dorabangs.feature.storage.navigation.navigateToStorage
import okhttp3.internal.toImmutableList

@Composable
Expand Down Expand Up @@ -41,7 +42,7 @@ class DoraAppState(

when (bottomNavigationDestination) {
BottomNavigationDestination.HOME -> navController.navigateToHome(bottomNavigationOption)
BottomNavigationDestination.STORAGE -> navController.navigateToHome(bottomNavigationOption)
BottomNavigationDestination.STORAGE -> navController.navigateToStorage(bottomNavigationOption)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.compose.ui.Modifier
import androidx.navigation.compose.NavHost
import com.mashup.core.navigation.NavigationRoute
import com.mashup.dorabangs.feature.navigation.homeNavigation
import com.mashup.dorabangs.feature.storage.navigation.storageNavigation

@Composable
fun MainNavHost(
Expand All @@ -18,5 +19,6 @@ fun MainNavHost(
startDestination = startDestination,
) {
homeNavigation()
storageNavigation()
}
}
1 change: 1 addition & 0 deletions feature/storage/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
76 changes: 76 additions & 0 deletions feature/storage/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
plugins {
alias(libs.plugins.com.android.library)
alias(libs.plugins.org.jetbrains.kotlin.android)
alias(libs.plugins.hilt)
alias(libs.plugins.kotlin.kapt)
}

android {
namespace = "com.mashup.dorabangs.feature.storage"
compileSdk = 34

defaultConfig {
minSdk = 24

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}

buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.4.3"
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_18
targetCompatibility = JavaVersion.VERSION_18
}
kotlinOptions {
jvmTarget = "18"
}
}

dependencies {
implementation(project(":domain"))
implementation(project(":core:coroutine"))
implementation(project(":core:designsystem"))
implementation(project(":core:navigation"))

// Compose
implementation(libs.ui)
implementation(libs.ui.graphics)
implementation(libs.ui.tooling.preview)
implementation(libs.material3)
implementation(platform(libs.compose.bom))
implementation(libs.material)

// Test
androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.espresso.core)
androidTestImplementation(platform(libs.compose.bom))
androidTestImplementation(libs.ui.test.junit4)
debugImplementation(libs.ui.tooling)
debugImplementation(libs.ui.test.manifest)
testImplementation(libs.junit)

// Hilt
implementation(libs.hilt.android)
kapt(libs.hilt.compiler)
implementation(libs.hilt.navigation.compose)

// Orbit
implementation(libs.orbit.core)
implementation(libs.orbit.viewmodel)
implementation(libs.orbit.compose)
}
Empty file.
21 changes: 21 additions & 0 deletions feature/storage/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.mashup.dorabangs.feature.storage

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith

/**
* 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.mashup.dorabangs.feature.storage.test", appContext.packageName)
}
}
4 changes: 4 additions & 0 deletions feature/storage/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.mashup.dorabangs.feature.storage.navigation

import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import com.mashup.core.navigation.NavigationRoute
import com.mashup.dorabangs.feature.storage.storage.StorageRoute

fun NavController.navigateToStorage(navOptions: NavOptions) = navigate(NavigationRoute.StorageScreen.route, navOptions)

fun NavGraphBuilder.storageNavigation() {
composable(
route = NavigationRoute.StorageScreen.route,
) {
StorageRoute()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package com.mashup.dorabangs.feature.storage.storage

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.mashup.dorabangs.core.designsystem.theme.DoraColorTokens
import com.mashup.dorabangs.core.designsystem.theme.DoraTypoTokens
import com.mashup.dorabangs.feature.storage.storage.model.StorageFolderItem
import com.mashup.dorabangs.feature.storage.storage.model.StorageListState

@Composable
fun StorageFolderList(
customList: List<StorageFolderItem> = StorageListState.customFolderList(),
navigateToStorageDetail: (StorageFolderItem) -> Unit = {},
onClickAddMoreButton: (StorageFolderItem) -> Unit = {},
) {
LazyColumn(
modifier = Modifier.padding(horizontal = 20.dp),
) {
item {
Spacer(modifier = Modifier.height(20.dp))
StorageDefaultFolder()
Spacer(modifier = Modifier.height(20.dp))
}
itemsIndexed(customList) { idx, item ->
StorageListItem(
item = item,
isFirstItem = idx == 0,
isLastItem = idx == customList.lastIndex,
navigateToStorageDetail = { navigateToStorageDetail(item) },
onClickAddMoreButton = { onClickAddMoreButton(item) },
)
if (idx != customList.lastIndex) {
HorizontalDivider(
modifier =
Modifier
.height(0.5.dp)
.background(color = DoraColorTokens.G1),
)
}
}
item {
Spacer(modifier = Modifier.height(60.dp))
}
}
}

@Composable
fun StorageDefaultFolder(
list: List<StorageFolderItem> = StorageListState.defaultFolderList(),
navigateToStorageDetail: (StorageFolderItem) -> Unit = {},
) {
Column(
modifier = Modifier
.fillMaxWidth(),
) {
list.forEachIndexed { idx, item ->
StorageListItem(
item = item,
isFirstItem = idx == 0,
isLastItem = idx == list.lastIndex,
navigateToStorageDetail = { navigateToStorageDetail(item) },
)
if (idx != list.lastIndex) {
HorizontalDivider(
modifier = Modifier
.height(0.5.dp)
.background(color = DoraColorTokens.G1),
)
}
}
}
}

@Composable
fun StorageListItem(
item: StorageFolderItem,
isDefault: Boolean = false,
isFirstItem: Boolean = false,
isLastItem: Boolean = false,
navigateToStorageDetail: () -> Unit = {},
onClickAddMoreButton: () -> Unit = {},
) {
val shape =
if (isFirstItem) {
RoundedCornerShape(topStart = 12.dp, topEnd = 12.dp)
} else if (isLastItem) {
RoundedCornerShape(bottomStart = 12.dp, bottomEnd = 12.dp)
} else {
RectangleShape
}
Box(
modifier = Modifier
.fillMaxWidth()
.background(color = DoraColorTokens.P1, shape = shape)
.padding(vertical = 14.dp, horizontal = 12.dp),
) {
Row(
modifier = Modifier
.align(Alignment.CenterStart)
.clickable { navigateToStorageDetail() },
) {
Icon(
painter = painterResource(id = androidx.core.R.drawable.ic_call_answer),
contentDescription = "folderIcon",
)
Text(
modifier = Modifier
.padding(start = 12.dp)
.align(Alignment.CenterVertically),
textAlign = TextAlign.Center,
text = item.folderTitle.title,
color = DoraColorTokens.G9,
style = DoraTypoTokens.caption3Medium,
)
}
Row(
modifier = Modifier.align(Alignment.CenterEnd),
) {
Text(
modifier = Modifier
.padding(end = 12.dp)
.align(Alignment.CenterVertically),
text = "${item.postCount}",
color = DoraColorTokens.G4,
style = DoraTypoTokens.caption3Medium,
)
val icon =
if (isDefault) {
androidx.core.R.drawable.ic_call_answer
} else {
androidx.core.R.drawable.ic_call_answer
}
Icon(
modifier = Modifier.clickable { if (isDefault) navigateToStorageDetail() else onClickAddMoreButton() },
painter = painterResource(id = icon),
contentDescription = "folderIcon",
)
}
}
}

@Preview
@Composable
fun PreviewStorageFolderList() {
StorageFolderList()
}
Loading

0 comments on commit f5559ec

Please sign in to comment.