Skip to content

Commit 4cc5891

Browse files
authored
Merge pull request #82 from LanPet-dev/develop
Develop
2 parents 5f9ceef + 4a5fcc6 commit 4cc5891

51 files changed

Lines changed: 1523 additions & 558 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

core/common/src/main/java/com/lanpet/core/common/Extensions.kt

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ package com.lanpet.core.common
33
import android.annotation.SuppressLint
44
import android.content.ContentValues
55
import android.content.Context
6+
import android.graphics.Bitmap
7+
import android.graphics.BitmapFactory
68
import android.net.Uri
79
import android.provider.MediaStore
810
import android.widget.Toast
911
import androidx.compose.foundation.layout.WindowInsets
12+
import java.io.ByteArrayOutputStream
13+
import java.io.IOException
1014
import java.text.SimpleDateFormat
1115
import java.util.Date
1216
import java.util.Locale
@@ -63,16 +67,17 @@ fun createdAtPostString(
6367
}
6468

6569
fun String.toLocalDate(
66-
dateFormat: String = "yyyy-MM-dd'T'HH:mm:ssXXX",
70+
dateFormat: String = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX",
6771
timeZone: TimeZone = TimeZone.getTimeZone("UTC"),
6872
): Date {
6973
val parser = SimpleDateFormat(dateFormat, Locale.getDefault())
7074
parser.timeZone = timeZone
75+
parser.isLenient = false
7176
return parser.parse(this) ?: throw IllegalArgumentException("Invalid date format")
7277
}
7378

7479
fun Date.toUtcDateString(
75-
dateFormat: String = "yyyy-MM-dd'T'HH:mm:ssXXX",
80+
dateFormat: String = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX",
7681
timeZone: TimeZone = TimeZone.getTimeZone("UTC"),
7782
): String {
7883
val formatter = SimpleDateFormat(dateFormat, Locale.getDefault())
@@ -104,3 +109,51 @@ fun Context.toast(
104109
) {
105110
Toast.makeText(this, message, duration).show()
106111
}
112+
113+
fun List<Uri>.toByteArrayList(context: Context): List<ByteArray> =
114+
this.mapNotNull { uri ->
115+
uri.toCompressedByteArray(context)
116+
}
117+
118+
fun Uri.toCompressedByteArray(
119+
context: Context,
120+
targetWidth: Int = 800,
121+
targetHeight: Int = 800,
122+
compressFormat: Bitmap.CompressFormat = Bitmap.CompressFormat.JPEG,
123+
quality: Int = 80,
124+
): ByteArray? =
125+
try {
126+
context.contentResolver.openInputStream(this)?.use { inputStream ->
127+
val originalBitmap = BitmapFactory.decodeStream(inputStream)
128+
129+
val originalWidth = originalBitmap.width
130+
val originalHeight = originalBitmap.height
131+
132+
val aspectRatio = originalWidth.toFloat() / originalHeight
133+
val newWidth: Int
134+
val newHeight: Int
135+
if (aspectRatio > 1) {
136+
newWidth = targetWidth
137+
newHeight = (targetWidth / aspectRatio).toInt()
138+
} else {
139+
newHeight = targetHeight
140+
newWidth = (targetHeight * aspectRatio).toInt()
141+
}
142+
143+
val resizedBitmap =
144+
Bitmap.createScaledBitmap(
145+
originalBitmap,
146+
newWidth,
147+
newHeight,
148+
true,
149+
)
150+
151+
ByteArrayOutputStream().use { outputStream ->
152+
resizedBitmap.compress(compressFormat, quality, outputStream)
153+
outputStream.toByteArray()
154+
}
155+
}
156+
} catch (e: IOException) {
157+
e.printStackTrace()
158+
null
159+
}

core/common/src/main/java/com/lanpet/core/common/widget/FreeBoardListItem.kt

Lines changed: 38 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,31 @@ import androidx.compose.material3.MaterialTheme
1313
import androidx.compose.material3.Surface
1414
import androidx.compose.material3.Text
1515
import androidx.compose.runtime.Composable
16+
import androidx.compose.runtime.CompositionLocalProvider
1617
import androidx.compose.ui.Alignment
1718
import androidx.compose.ui.Modifier
1819
import androidx.compose.ui.draw.clip
1920
import androidx.compose.ui.graphics.ColorFilter
20-
import androidx.compose.ui.layout.ContentScale
21-
import androidx.compose.ui.res.painterResource
21+
import androidx.compose.ui.platform.LocalContext
2222
import androidx.compose.ui.text.style.TextOverflow
2323
import androidx.compose.ui.tooling.preview.PreviewLightDark
2424
import androidx.compose.ui.unit.dp
2525
import coil.ImageLoader
26-
import coil.compose.AsyncImage
2726
import com.lanpet.core.common.MyIconPack
2827
import com.lanpet.core.common.createdAtPostString
2928
import com.lanpet.core.common.myiconpack.Like
3029
import com.lanpet.core.common.myiconpack.Message
31-
import com.lanpet.core.designsystem.R
3230
import com.lanpet.core.designsystem.theme.GrayColor
3331
import com.lanpet.core.designsystem.theme.LanPetAppTheme
3432
import com.lanpet.core.designsystem.theme.LanPetDimensions
3533
import com.lanpet.core.designsystem.theme.customTypography
34+
import com.lanpet.core.manager.CoilManager
3635
import com.lanpet.core.manager.LocalCoilManager
36+
import com.lanpet.domain.model.PetCategory
37+
import com.lanpet.domain.model.free.FreeBoardCategoryType
3738
import com.lanpet.domain.model.free.FreeBoardItem
39+
import com.lanpet.domain.model.free.FreeBoardStat
40+
import com.lanpet.domain.model.free.FreeBoardText
3841

3942
@Composable
4043
fun FreeBoardListItem(
@@ -84,26 +87,11 @@ fun FreeBoardListItem(
8487
)
8588
}
8689
Spacer(modifier = Modifier.padding(LanPetDimensions.Spacing.small))
87-
if (freeBoardPostItem.resources?.isNotEmpty() == true) {
88-
AsyncImage(
89-
model = freeBoardPostItem.resources!!.first().url,
90-
contentDescription = "post_image",
91-
contentScale = ContentScale.Crop,
92-
imageLoader = imageLoader,
93-
modifier =
94-
Modifier
95-
.clip(
96-
shape = RoundedCornerShape(LanPetDimensions.Corner.xxSmall),
97-
).size(66.dp),
98-
error = painterResource(id = R.drawable.img_animals),
99-
)
100-
} else {
101-
Image(
102-
painter = painterResource(id = R.drawable.img_animals),
103-
contentDescription = "ic_animals",
104-
modifier = Modifier.size(66.dp),
105-
)
106-
}
90+
NetworkImage(
91+
freeBoardPostItem.resources?.getOrNull(0)?.url,
92+
modifier = Modifier.size(66.dp).clip(RoundedCornerShape(8.dp)),
93+
imageLoader = imageLoader,
94+
)
10795
}
10896
Spacer(modifier = Modifier.padding(LanPetDimensions.Spacing.xxSmall))
10997
Row(
@@ -148,8 +136,32 @@ fun FreeBoardListItem(
148136
@PreviewLightDark
149137
@Composable
150138
private fun FreeBoardListItemPreview() {
151-
LanPetAppTheme {
152-
Column {
139+
val context = LocalContext.current
140+
141+
CompositionLocalProvider(LocalCoilManager provides CoilManager(context)) {
142+
LanPetAppTheme {
143+
Column {
144+
FreeBoardListItem(
145+
freeBoardPostItem =
146+
FreeBoardItem(
147+
id = "1",
148+
category = FreeBoardCategoryType.CURIOUS,
149+
petType = PetCategory.PARROT,
150+
text =
151+
FreeBoardText(
152+
title = "title",
153+
content = "content",
154+
),
155+
stat =
156+
FreeBoardStat(
157+
likeCount = 1,
158+
commentCount = 1,
159+
),
160+
resources = emptyList(),
161+
created = "2021-10-27T17:13:40.000+00:00",
162+
),
163+
)
164+
}
153165
}
154166
}
155167
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.lanpet.core.common.widget
2+
3+
import androidx.annotation.DrawableRes
4+
import androidx.compose.foundation.Image
5+
import androidx.compose.foundation.layout.size
6+
import androidx.compose.runtime.Composable
7+
import androidx.compose.ui.Modifier
8+
import androidx.compose.ui.layout.ContentScale
9+
import androidx.compose.ui.res.painterResource
10+
import androidx.compose.ui.unit.dp
11+
import coil.ImageLoader
12+
import coil.compose.AsyncImage
13+
import com.lanpet.core.designsystem.R
14+
import com.lanpet.core.manager.LocalCoilManager
15+
16+
/**
17+
* 주어진 URL을 통해 네트워크에서 이미지를 로드하고 표시하는 컴포저블 함수입니다.
18+
* URL이 null이거나 비어있는 경우, 기본 이미지를 대신 표시합니다.
19+
*
20+
* @param url 로드할 이미지의 URL. null이거나 비어있을 경우 기본 이미지가 표시됩니다.
21+
* @param modifier 이미지에 적용할 Modifier. 기본값은 Modifier입니다.
22+
* @param imageLoader 이미지를 로드하는 데 사용할 ImageLoader. 기본값은 LocalCoilManager의 memoryCacheImageLoader입니다.
23+
* @param drawableRes URL이 null이거나 비어있을 때 표시할 기본 이미지 리소스 ID. 기본값은 R.drawable.img_animals입니다.
24+
*/
25+
@Composable
26+
fun NetworkImage(
27+
url: String?,
28+
modifier: Modifier = Modifier,
29+
imageLoader: ImageLoader = LocalCoilManager.current.memoryCacheImageLoader,
30+
@DrawableRes drawableRes: Int = R.drawable.img_animals,
31+
) {
32+
if (url.isNullOrEmpty()) {
33+
Image(
34+
painter = painterResource(id = drawableRes),
35+
contentDescription = "default_image",
36+
modifier = modifier.size(66.dp),
37+
)
38+
} else {
39+
AsyncImage(
40+
model = url,
41+
contentDescription = "network_image",
42+
contentScale = ContentScale.Crop,
43+
imageLoader = imageLoader,
44+
modifier = modifier,
45+
error = painterResource(id = R.drawable.img_animals),
46+
)
47+
}
48+
}

core/common/src/main/java/com/lanpet/core/common/widget/ProfileImage.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ private fun PreviewProfileImage() {
8686
ProfileImage(
8787
profileType = ProfileType.BUTLER,
8888
)
89+
ProfileImage(
90+
profileType = ProfileType.PET,
91+
size = 180.dp,
92+
)
93+
ProfileImage(
94+
profileType = ProfileType.BUTLER,
95+
size = 180.dp,
96+
)
8997
}
9098
}
9199
}

core/common/src/test/java/ExtensionsTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import java.util.TimeZone
99

1010
class ExtensionsTest {
1111
private val timeZone: TimeZone = TimeZone.getDefault()
12-
private val createdAt = "2016-10-27T17:13:40+00:00"
12+
private val createdAt = "2016-10-27T17:13:40.000+00:00"
1313
private val currentTime = createdAt.toLocalDate()
1414
private val calendar = Calendar.getInstance()
1515
private val dateFormat = SimpleDateFormat(" yyyy-MM-dd HH:mm:ss")

core/config/build.gradle.kts

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,14 @@
11
plugins {
22
alias(libs.plugins.android.library)
33
alias(libs.plugins.kotlin.android)
4+
alias(libs.plugins.convention.lib.build)
45
}
56

67
android {
78
namespace = "com.lanpet.core.config"
8-
compileSdk = 34
9-
10-
defaultConfig {
11-
minSdk = 24
12-
13-
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
14-
consumerProguardFiles("consumer-rules.pro")
15-
}
16-
17-
buildTypes {
18-
release {
19-
isMinifyEnabled = false
20-
proguardFiles(
21-
getDefaultProguardFile("proguard-android-optimize.txt"),
22-
"proguard-rules.pro",
23-
)
24-
}
25-
}
26-
compileOptions {
27-
sourceCompatibility = JavaVersion.VERSION_11
28-
targetCompatibility = JavaVersion.VERSION_11
29-
}
30-
kotlinOptions {
31-
jvmTarget = "11"
32-
}
339
}
3410

3511
dependencies {
36-
3712
implementation(libs.androidx.core.ktx)
3813
implementation(libs.androidx.appcompat)
3914
implementation(libs.material)

core/config/src/androidTest/java/com/lanpet/core/config/ExampleInstrumentedTest.kt

Lines changed: 0 additions & 22 deletions
This file was deleted.

core/config/src/test/java/com/lanpet/core/config/ExampleUnitTest.kt

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)