diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml
index f3e8862f5..50a4d03d3 100644
--- a/.github/workflows/android-ci.yml
+++ b/.github/workflows/android-ci.yml
@@ -84,5 +84,8 @@ jobs:
- name: Generate google-services.json
run: echo '${{ secrets.GOOGLE_SERVICES }}' | base64 -d > ./app/google-services.json
+ - name: Compose Stability Dump
+ run: ./gradlew stabilityDump
+
- name: Compose Stability Check
run: ./gradlew stabilityCheck
diff --git a/app/stability/app.stability b/app/stability/app.stability
index dc1f99ee2..93818f146 100644
--- a/app/stability/app.stability
+++ b/app/stability/app.stability
@@ -9,7 +9,7 @@ public fun com.ninecraft.booket.di.CrossFadeNavDecorator.Decoration(targetState:
skippable: false
restartable: true
params:
- - targetState: RUNTIME (requires runtime check)
+ - targetState: UNSTABLE (has mutable properties or unstable members)
- innerContent: STABLE (composable function type)
@Composable
diff --git a/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/ComponentPreview.kt b/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/ComponentPreview.kt
index 065804537..488855406 100644
--- a/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/ComponentPreview.kt
+++ b/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/ComponentPreview.kt
@@ -1,7 +1,6 @@
package com.ninecraft.booket.core.designsystem
import android.content.res.Configuration.UI_MODE_NIGHT_NO
-import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.ui.tooling.preview.Preview
@Preview(
@@ -9,9 +8,4 @@ import androidx.compose.ui.tooling.preview.Preview
showBackground = true,
uiMode = UI_MODE_NIGHT_NO,
)
-@Preview(
- name = "Dark",
- showBackground = true,
- uiMode = UI_MODE_NIGHT_YES,
-)
annotation class ComponentPreview
diff --git a/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/DevicePreview.kt b/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/DevicePreview.kt
index 8dbd713d1..ad9b39ac4 100644
--- a/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/DevicePreview.kt
+++ b/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/DevicePreview.kt
@@ -1,7 +1,6 @@
package com.ninecraft.booket.core.designsystem
import android.content.res.Configuration.UI_MODE_NIGHT_NO
-import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.ui.tooling.preview.Preview
@Preview(
@@ -10,10 +9,4 @@ import androidx.compose.ui.tooling.preview.Preview
uiMode = UI_MODE_NIGHT_NO,
device = "spec:width=360dp,height=800dp,dpi=411",
)
-@Preview(
- name = "Dark",
- showBackground = true,
- uiMode = UI_MODE_NIGHT_YES,
- device = "spec:width=360dp,height=800dp,dpi=411",
-)
annotation class DevicePreview
diff --git a/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/Emotion.kt b/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/Emotion.kt
index 931074a10..52bb4fdb0 100644
--- a/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/Emotion.kt
+++ b/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/Emotion.kt
@@ -1,14 +1,21 @@
package com.ninecraft.booket.core.designsystem
import androidx.compose.ui.graphics.Color
+import com.ninecraft.booket.core.designsystem.theme.Blue300
+import com.ninecraft.booket.core.designsystem.theme.EtcBgColor
+import com.ninecraft.booket.core.designsystem.theme.EtcTextColor
import com.ninecraft.booket.core.designsystem.theme.InsightBgColor
import com.ninecraft.booket.core.designsystem.theme.InsightTextColor
import com.ninecraft.booket.core.designsystem.theme.JoyBgColor
import com.ninecraft.booket.core.designsystem.theme.JoyTextColor
+import com.ninecraft.booket.core.designsystem.theme.Neutral300
+import com.ninecraft.booket.core.designsystem.theme.Orange300
import com.ninecraft.booket.core.designsystem.theme.SadnessBgColor
import com.ninecraft.booket.core.designsystem.theme.SadnessTextColor
+import com.ninecraft.booket.core.designsystem.theme.Violet300
import com.ninecraft.booket.core.designsystem.theme.WarmthBgColor
import com.ninecraft.booket.core.designsystem.theme.WarmthTextColor
+import com.ninecraft.booket.core.designsystem.theme.Yellow300
import com.ninecraft.booket.core.model.Emotion
val Emotion.bgColor: Color
@@ -17,6 +24,7 @@ val Emotion.bgColor: Color
Emotion.JOY -> JoyBgColor
Emotion.SAD -> SadnessBgColor
Emotion.INSIGHT -> InsightBgColor
+ Emotion.ETC -> EtcBgColor
}
val Emotion.textColor: Color
@@ -25,6 +33,7 @@ val Emotion.textColor: Color
Emotion.JOY -> JoyTextColor
Emotion.SAD -> SadnessTextColor
Emotion.INSIGHT -> InsightTextColor
+ Emotion.ETC -> EtcTextColor
}
val Emotion.graphicRes: Int
@@ -33,14 +42,25 @@ val Emotion.graphicRes: Int
Emotion.JOY -> R.drawable.img_emotion_joy
Emotion.SAD -> R.drawable.img_emotion_sadness
Emotion.INSIGHT -> R.drawable.img_emotion_insight
+ Emotion.ETC -> R.drawable.img_emotion_warmth
}
-val Emotion.graphicResV2: Int
+val Emotion.ratioBarColor: Color
+ get() = when (this) {
+ Emotion.WARM -> Yellow300
+ Emotion.JOY -> Orange300
+ Emotion.SAD -> Blue300
+ Emotion.INSIGHT -> Violet300
+ Emotion.ETC -> Neutral300
+ }
+
+val Emotion.graphicResV2: Int?
get() = when (this) {
Emotion.WARM -> R.drawable.img_category_warm
Emotion.JOY -> R.drawable.img_category_joy
Emotion.SAD -> R.drawable.img_category_sad
Emotion.INSIGHT -> R.drawable.img_category_insight
+ Emotion.ETC -> null
}
val Emotion.descriptionRes: Int
@@ -49,4 +69,5 @@ val Emotion.descriptionRes: Int
Emotion.JOY -> R.string.emotion_joy_description
Emotion.SAD -> R.string.emotion_sad_description
Emotion.INSIGHT -> R.string.emotion_insight_description
+ Emotion.ETC -> R.string.emotion_etc_description
}
diff --git a/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt b/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt
index 61997cc91..e3b2588f0 100644
--- a/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt
+++ b/core/designsystem/src/main/kotlin/com/ninecraft/booket/core/designsystem/theme/Color.kt
@@ -63,6 +63,28 @@ val Blue700 = Color(0xFF007BFF)
val Blue800 = Color(0xFF1269EC)
val Blue900 = Color(0xFF1F47CD)
+val Orange50 = Color(0xFFFFF1EB)
+val Orange100 = Color(0xFFFFD2BE)
+val Orange200 = Color(0xFFFFB392)
+val Orange300 = Color(0xFFFF9365)
+val Orange400 = Color(0xFFEF6D35)
+val Orange500 = Color(0xFFCD5622)
+val Orange600 = Color(0xFFAB4114)
+val Orange700 = Color(0xFF892F08)
+val Orange800 = Color(0xFF672001)
+val Orange900 = Color(0xFF451500)
+
+val Violet50 = Color(0xFFF7F0FF)
+val Violet100 = Color(0xFFE6CEFF)
+val Violet200 = Color(0xFFD4ADFF)
+val Violet300 = Color(0xFFC38CFF)
+val Violet400 = Color(0xFFB26AFF)
+val Violet500 = Color(0xFF9A55E4)
+val Violet600 = Color(0xFF7F40C2)
+val Violet700 = Color(0xFF652EA0)
+val Violet800 = Color(0xFF4C1E7E)
+val Violet900 = Color(0xFF36125C)
+
val Kakao = Color(0xFFFBD300)
val Blank = Color(0xFFD6D6D6)
val HomeBg = Color(0xFFF0F9E8)
@@ -76,6 +98,8 @@ val InsightTextColor = Color(0xFF9A55E4)
val InsightBgColor = Color(0xFFF3E8FF)
val SadnessTextColor = Color(0xFF2872E9)
val SadnessBgColor = Color(0xFFE1ECFF)
+val EtcTextColor = Color(0xFF737373)
+val EtcBgColor = Color(0xFFF5F5F5)
@Immutable
data class ReedColorScheme(
diff --git a/core/designsystem/src/main/res/values/strings.xml b/core/designsystem/src/main/res/values/strings.xml
index 674c8c554..1bc404a78 100644
--- a/core/designsystem/src/main/res/values/strings.xml
+++ b/core/designsystem/src/main/res/values/strings.xml
@@ -8,4 +8,5 @@
흥미롭고 유쾌한 순간
눈물이 고인 순간
생각이 깊어지는 순간
+ 네 가지 감정으로 표현하기 어려울 때
diff --git a/core/designsystem/stability/designsystem.stability b/core/designsystem/stability/designsystem.stability
index 9261a0737..7a2aa49f4 100644
--- a/core/designsystem/stability/designsystem.stability
+++ b/core/designsystem/stability/designsystem.stability
@@ -42,43 +42,53 @@ public fun com.ninecraft.booket.core.designsystem.component.ResourceImage(imageR
- contentScale: STABLE (marked @Stable or @Immutable)
@Composable
-public fun com.ninecraft.booket.core.designsystem.component.button.(): com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle
+public fun com.ninecraft.booket.core.designsystem.component.button.ReedButton(onClick: kotlin.Function0, text: kotlin.String, sizeStyle: com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle, colorStyle: com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle, modifier: androidx.compose.ui.Modifier, enabled: kotlin.Boolean, leadingIcon: @[Composable] androidx.compose.runtime.internal.ComposableFunction0?, trailingIcon: @[Composable] androidx.compose.runtime.internal.ComposableFunction0?, multipleEventsCutterEnabled: kotlin.Boolean): kotlin.Unit
skippable: true
restartable: true
params:
+ - onClick: STABLE (function type)
+ - text: STABLE (String is immutable)
+ - sizeStyle: STABLE (class with no mutable properties)
+ - colorStyle: STABLE (class with no mutable properties)
+ - modifier: STABLE (marked @Stable or @Immutable)
+ - enabled: STABLE (primitive type)
+ - leadingIcon: STABLE (composable function type)
+ - trailingIcon: STABLE (composable function type)
+ - multipleEventsCutterEnabled: STABLE (primitive type)
@Composable
-public fun com.ninecraft.booket.core.designsystem.component.button.(): com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle
+public fun com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle.borderStroke(): androidx.compose.foundation.BorderStroke?
skippable: true
restartable: true
params:
@Composable
-public fun com.ninecraft.booket.core.designsystem.component.button.(): com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle
+public fun com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle.containerColor(isPressed: kotlin.Boolean): androidx.compose.ui.graphics.Color
skippable: true
restartable: true
params:
+ - isPressed: STABLE (primitive type)
@Composable
-public fun com.ninecraft.booket.core.designsystem.component.button.(): com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle
+public fun com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle.contentColor(): androidx.compose.ui.graphics.Color
skippable: true
restartable: true
params:
@Composable
-public fun com.ninecraft.booket.core.designsystem.component.button.(): com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle
+public fun com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle.disabledContainerColor(): androidx.compose.ui.graphics.Color
skippable: true
restartable: true
params:
@Composable
-public fun com.ninecraft.booket.core.designsystem.component.button.(): com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle
+public fun com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle.disabledContentColor(): androidx.compose.ui.graphics.Color
skippable: true
restartable: true
params:
@Composable
-public fun com.ninecraft.booket.core.designsystem.component.button.ReedButton(onClick: kotlin.Function0, text: kotlin.String, sizeStyle: com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle, colorStyle: com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle, modifier: androidx.compose.ui.Modifier, enabled: kotlin.Boolean, leadingIcon: @[Composable] androidx.compose.runtime.internal.ComposableFunction0?, trailingIcon: @[Composable] androidx.compose.runtime.internal.ComposableFunction0?, multipleEventsCutterEnabled: kotlin.Boolean): kotlin.Unit
+public fun com.ninecraft.booket.core.designsystem.component.button.ReedTextButton(onClick: kotlin.Function0, text: kotlin.String, sizeStyle: com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle, colorStyle: com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle, modifier: androidx.compose.ui.Modifier, enabled: kotlin.Boolean, multipleEventsCutterEnabled: kotlin.Boolean): kotlin.Unit
skippable: true
restartable: true
params:
@@ -88,53 +98,43 @@ public fun com.ninecraft.booket.core.designsystem.component.button.ReedButton(on
- colorStyle: STABLE (class with no mutable properties)
- modifier: STABLE (marked @Stable or @Immutable)
- enabled: STABLE (primitive type)
- - leadingIcon: STABLE (composable function type)
- - trailingIcon: STABLE (composable function type)
- multipleEventsCutterEnabled: STABLE (primitive type)
@Composable
-public fun com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle.borderStroke(): androidx.compose.foundation.BorderStroke?
+public fun com.ninecraft.booket.core.designsystem.component.button.largeButtonStyle(): com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle
skippable: true
restartable: true
params:
@Composable
-public fun com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle.containerColor(isPressed: kotlin.Boolean): androidx.compose.ui.graphics.Color
+public fun com.ninecraft.booket.core.designsystem.component.button.largeRoundedButtonStyle(): com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle
skippable: true
restartable: true
params:
- - isPressed: STABLE (primitive type)
@Composable
-public fun com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle.contentColor(): androidx.compose.ui.graphics.Color
+public fun com.ninecraft.booket.core.designsystem.component.button.mediumButtonStyle(): com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle
skippable: true
restartable: true
params:
@Composable
-public fun com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle.disabledContainerColor(): androidx.compose.ui.graphics.Color
+public fun com.ninecraft.booket.core.designsystem.component.button.mediumRoundedButtonStyle(): com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle
skippable: true
restartable: true
params:
@Composable
-public fun com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle.disabledContentColor(): androidx.compose.ui.graphics.Color
+public fun com.ninecraft.booket.core.designsystem.component.button.smallButtonStyle(): com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle
skippable: true
restartable: true
params:
@Composable
-public fun com.ninecraft.booket.core.designsystem.component.button.ReedTextButton(onClick: kotlin.Function0, text: kotlin.String, sizeStyle: com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle, colorStyle: com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorStyle, modifier: androidx.compose.ui.Modifier, enabled: kotlin.Boolean, multipleEventsCutterEnabled: kotlin.Boolean): kotlin.Unit
+public fun com.ninecraft.booket.core.designsystem.component.button.smallRoundedButtonStyle(): com.ninecraft.booket.core.designsystem.component.button.ButtonSizeStyle
skippable: true
restartable: true
params:
- - onClick: STABLE (function type)
- - text: STABLE (String is immutable)
- - sizeStyle: STABLE (class with no mutable properties)
- - colorStyle: STABLE (class with no mutable properties)
- - modifier: STABLE (marked @Stable or @Immutable)
- - enabled: STABLE (primitive type)
- - multipleEventsCutterEnabled: STABLE (primitive type)
@Composable
public fun com.ninecraft.booket.core.designsystem.component.checkbox.CircleCheckBox(checked: kotlin.Boolean, onCheckedChange: kotlin.Function1, modifier: androidx.compose.ui.Modifier): kotlin.Unit
@@ -163,18 +163,6 @@ public fun com.ninecraft.booket.core.designsystem.component.checkbox.TickOnlyChe
- onCheckedChange: STABLE (function type)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-public fun com.ninecraft.booket.core.designsystem.component.chip.(): com.ninecraft.booket.core.designsystem.component.chip.ChipSizeStyle
- skippable: true
- restartable: true
- params:
-
-@Composable
-public fun com.ninecraft.booket.core.designsystem.component.chip.(): com.ninecraft.booket.core.designsystem.component.chip.ChipSizeStyle
- skippable: true
- restartable: true
- params:
-
@Composable
public fun com.ninecraft.booket.core.designsystem.component.chip.ReedRemovableChip(label: kotlin.String, chipSizeStyle: com.ninecraft.booket.core.designsystem.component.chip.ChipSizeStyle, onRemove: kotlin.Function0, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -196,6 +184,18 @@ public fun com.ninecraft.booket.core.designsystem.component.chip.ReedSelectableC
- onClick: STABLE (function type)
- modifier: STABLE (marked @Stable or @Immutable)
+@Composable
+public fun com.ninecraft.booket.core.designsystem.component.chip.mediumChipStyle(): com.ninecraft.booket.core.designsystem.component.chip.ChipSizeStyle
+ skippable: true
+ restartable: true
+ params:
+
+@Composable
+public fun com.ninecraft.booket.core.designsystem.component.chip.smallChipStyle(): com.ninecraft.booket.core.designsystem.component.chip.ChipSizeStyle
+ skippable: true
+ restartable: true
+ params:
+
@Composable
public fun com.ninecraft.booket.core.designsystem.component.textfield.ReedRecordTextField(recordState: androidx.compose.foundation.text.input.TextFieldState, recordHintRes: kotlin.Int, modifier: androidx.compose.ui.Modifier, inputTransformation: androidx.compose.foundation.text.input.InputTransformation?, keyboardOptions: androidx.compose.foundation.text.KeyboardOptions, lineLimits: androidx.compose.foundation.text.input.TextFieldLineLimits, isError: kotlin.Boolean, errorMessage: kotlin.String, onClear: kotlin.Function0?, onNext: kotlin.Function0, backgroundColor: androidx.compose.ui.graphics.Color, textColor: androidx.compose.ui.graphics.Color, cornerShape: androidx.compose.foundation.shape.RoundedCornerShape, borderStroke: androidx.compose.foundation.BorderStroke): kotlin.Unit
skippable: true
@@ -240,31 +240,31 @@ public fun com.ninecraft.booket.core.designsystem.theme.ReedTheme(content: @[Com
- content: STABLE (composable function type)
@Composable
-public fun com.ninecraft.booket.core.designsystem.theme.ReedTheme.(): com.ninecraft.booket.core.designsystem.theme.ReedBorder
+public fun com.ninecraft.booket.core.designsystem.theme.ReedTheme.border(): com.ninecraft.booket.core.designsystem.theme.ReedBorder
skippable: true
restartable: true
params:
@Composable
-public fun com.ninecraft.booket.core.designsystem.theme.ReedTheme.(): com.ninecraft.booket.core.designsystem.theme.ReedColorScheme
+public fun com.ninecraft.booket.core.designsystem.theme.ReedTheme.colors(): com.ninecraft.booket.core.designsystem.theme.ReedColorScheme
skippable: true
restartable: true
params:
@Composable
-public fun com.ninecraft.booket.core.designsystem.theme.ReedTheme.(): com.ninecraft.booket.core.designsystem.theme.ReedRadius
+public fun com.ninecraft.booket.core.designsystem.theme.ReedTheme.radius(): com.ninecraft.booket.core.designsystem.theme.ReedRadius
skippable: true
restartable: true
params:
@Composable
-public fun com.ninecraft.booket.core.designsystem.theme.ReedTheme.(): com.ninecraft.booket.core.designsystem.theme.ReedSpacing
+public fun com.ninecraft.booket.core.designsystem.theme.ReedTheme.spacing(): com.ninecraft.booket.core.designsystem.theme.ReedSpacing
skippable: true
restartable: true
params:
@Composable
-public fun com.ninecraft.booket.core.designsystem.theme.ReedTheme.(): com.ninecraft.booket.core.designsystem.theme.ReedTypography
+public fun com.ninecraft.booket.core.designsystem.theme.ReedTheme.typography(): com.ninecraft.booket.core.designsystem.theme.ReedTypography
skippable: true
restartable: true
params:
diff --git a/core/model/src/main/kotlin/com/ninecraft/booket/core/model/ReadingRecordsModel.kt b/core/model/src/main/kotlin/com/ninecraft/booket/core/model/ReadingRecordsModel.kt
index 1c6356e16..6bf289d17 100644
--- a/core/model/src/main/kotlin/com/ninecraft/booket/core/model/ReadingRecordsModel.kt
+++ b/core/model/src/main/kotlin/com/ninecraft/booket/core/model/ReadingRecordsModel.kt
@@ -1,6 +1,6 @@
package com.ninecraft.booket.core.model
-import androidx.compose.runtime.Stable
+import androidx.compose.runtime.Immutable
data class ReadingRecordsModel(
val lastPage: Boolean = true,
@@ -10,7 +10,7 @@ data class ReadingRecordsModel(
val readingRecords: List = emptyList(),
)
-@Stable
+@Immutable
data class ReadingRecordModel(
val id: String = "",
val userBookId: String = "",
diff --git a/core/model/src/main/kotlin/com/ninecraft/booket/core/model/SeedModel.kt b/core/model/src/main/kotlin/com/ninecraft/booket/core/model/SeedModel.kt
index 670b050df..24ee2845a 100644
--- a/core/model/src/main/kotlin/com/ninecraft/booket/core/model/SeedModel.kt
+++ b/core/model/src/main/kotlin/com/ninecraft/booket/core/model/SeedModel.kt
@@ -20,6 +20,7 @@ enum class Emotion(
JOY("즐거움"),
SAD("슬픔"),
INSIGHT("깨달음"),
+ ETC("기타"),
;
companion object {
diff --git a/core/network/src/main/kotlin/com/ninecraft/booket/core/network/service/ReedService.kt b/core/network/src/main/kotlin/com/ninecraft/booket/core/network/service/ReedService.kt
index f3926e64e..0521ac594 100644
--- a/core/network/src/main/kotlin/com/ninecraft/booket/core/network/service/ReedService.kt
+++ b/core/network/src/main/kotlin/com/ninecraft/booket/core/network/service/ReedService.kt
@@ -127,7 +127,7 @@ interface ReedService {
@Path("userBookId") userBookId: String,
): SeedResponse
- @GET("api/v1/reading-records/detail/{readingRecordId}")
+ @GET("api/v2/reading-records/detail/{readingRecordId}")
suspend fun getRecordDetail(
@Path("readingRecordId") readingRecordId: String,
): RecordDetailResponse
diff --git a/core/ui/stability/ui.stability b/core/ui/stability/ui.stability
index 964ce26ce..0305109da 100644
--- a/core/ui/stability/ui.stability
+++ b/core/ui/stability/ui.stability
@@ -64,12 +64,6 @@ public fun com.ninecraft.booket.core.ui.component.ReedBottomSheet(onDismissReque
- sheetState: STABLE (marked @Stable or @Immutable)
- content: STABLE (composable function type)
-@Composable
-private fun com.ninecraft.booket.core.ui.component.ReedBottomSheetPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
public fun com.ninecraft.booket.core.ui.component.ReedCloseTopAppBar(modifier: androidx.compose.ui.Modifier, isDark: kotlin.Boolean, title: kotlin.String, onClose: kotlin.Function0): kotlin.Unit
skippable: true
@@ -119,24 +113,6 @@ public fun com.ninecraft.booket.core.ui.component.ReedLoadingIndicator(modifier:
- modifier: STABLE (marked @Stable or @Immutable)
- delayMillis: STABLE (primitive type)
-@Composable
-private fun com.ninecraft.booket.core.ui.component.ReedLoadingIndicatorPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
-@Composable
-private fun com.ninecraft.booket.core.ui.component.ReedNetworkErrorUiPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
-@Composable
-private fun com.ninecraft.booket.core.ui.component.ReedServerErrorUiPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
public fun com.ninecraft.booket.core.ui.component.ReedTopAppBar(modifier: androidx.compose.ui.Modifier, isDark: kotlin.Boolean, title: kotlin.String, startIconRes: kotlin.Int?, startIconDescription: kotlin.String, startIconOnClick: kotlin.Function0, endIconRes: kotlin.Int?, endIconDescription: kotlin.String, endIconOnClick: kotlin.Function0): kotlin.Unit
skippable: true
diff --git a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailPresenter.kt b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailPresenter.kt
index c49bd0d5e..7d9ca4422 100644
--- a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailPresenter.kt
+++ b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailPresenter.kt
@@ -79,6 +79,7 @@ class BookDetailPresenter(
var footerState by rememberRetained { mutableStateOf(FooterState.Idle) }
var bookDetail by rememberRetained { mutableStateOf(BookDetailModel()) }
var seedsStates by rememberRetained { mutableStateOf>(persistentListOf()) }
+ var isStatsExpanded by rememberRetained { mutableStateOf(false) }
var readingRecords by rememberRetained { mutableStateOf(persistentListOf()) }
var readingRecordsTotalCount by rememberRetained { mutableIntStateOf(0) }
var currentStartIndex by rememberRetained { mutableIntStateOf(START_INDEX) }
@@ -398,6 +399,10 @@ class BookDetailPresenter(
initialLoad()
}
}
+
+ is BookDetailUiEvent.OnStatsToggleClick -> {
+ isStatsExpanded = event.flag
+ }
}
}
@@ -410,6 +415,7 @@ class BookDetailPresenter(
footerState = footerState,
bookDetail = bookDetail,
seedsStats = seedsStates,
+ isStatsExpanded = isStatsExpanded,
readingRecords = readingRecords,
readingRecordsTotalCount = readingRecordsTotalCount,
isBookUpdateBottomSheetVisible = isBookUpdateBottomSheetVisible,
diff --git a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUi.kt b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUi.kt
index 2c7ce7f64..83c7e25cb 100644
--- a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUi.kt
+++ b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUi.kt
@@ -1,6 +1,5 @@
package com.ninecraft.booket.feature.detail.book
-import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
@@ -37,6 +36,9 @@ import com.ninecraft.booket.core.designsystem.component.button.ReedButtonColorSt
import com.ninecraft.booket.core.designsystem.component.button.mediumButtonStyle
import com.ninecraft.booket.core.designsystem.theme.ReedTheme
import com.ninecraft.booket.core.model.BookDetailModel
+import com.ninecraft.booket.core.model.Emotion
+import com.ninecraft.booket.core.model.EmotionModel
+import com.ninecraft.booket.core.model.ReadingRecordModel
import com.ninecraft.booket.core.ui.ReedScaffold
import com.ninecraft.booket.core.ui.component.InfinityLazyColumn
import com.ninecraft.booket.core.ui.component.LoadStateFooter
@@ -57,6 +59,7 @@ import com.ninecraft.booket.feature.screens.BookDetailScreen
import com.skydoves.compose.stability.runtime.TraceRecomposition
import com.slack.circuit.codegen.annotations.CircuitInject
import dev.zacsweers.metro.AppScope
+import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.launch
import com.ninecraft.booket.core.designsystem.R as designR
@@ -238,7 +241,7 @@ internal fun BookDetailContent(
item {
Column {
BookItem(bookDetail = state.bookDetail)
- Spacer(Modifier.height(ReedTheme.spacing.spacing7))
+ Spacer(Modifier.height(ReedTheme.spacing.spacing5))
Row(
modifier = Modifier
.fillMaxWidth()
@@ -280,7 +283,13 @@ internal fun BookDetailContent(
item {
if (state.hasEmotionData()) {
- CollectedSeeds(seedsStats = state.seedsStats)
+ CollectedSeeds(
+ seedsStats = state.seedsStats,
+ isStatsExpanded = state.isStatsExpanded,
+ onToggleClick = {
+ state.eventSink(BookDetailUiEvent.OnStatsToggleClick(!state.isStatsExpanded))
+ },
+ )
} else {
Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing10))
}
@@ -292,7 +301,7 @@ internal fun BookDetailContent(
Column(
modifier = Modifier.padding(horizontal = ReedTheme.spacing.spacing5),
) {
- Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing6))
+ Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing8))
ReadingRecordsHeader(
totalCount = state.readingRecordsTotalCount,
currentRecordSort = state.currentRecordSort,
@@ -329,6 +338,9 @@ internal fun BookDetailContent(
val record = state.readingRecords[index]
RecordItem(
recordInfo = record,
+ onRecordClick = {
+ state.eventSink(BookDetailUiEvent.OnRecordItemClick(record.id))
+ },
onRecordMenuClick = { recordInfo ->
state.eventSink(BookDetailUiEvent.OnRecordMenuClick(recordInfo))
},
@@ -337,10 +349,7 @@ internal fun BookDetailContent(
start = ReedTheme.spacing.spacing5,
end = ReedTheme.spacing.spacing5,
bottom = ReedTheme.spacing.spacing3,
- )
- .clickable {
- state.eventSink(BookDetailUiEvent.OnRecordItemClick(record.id))
- },
+ ),
)
}
@@ -365,7 +374,27 @@ internal fun BookDetailContent(
@ComponentPreview
@Composable
-private fun BookDetailPreview() {
+private fun BookDetailEmptyPreview() {
+ ReedTheme {
+ BookDetailUi(
+ state = BookDetailUiState(
+ uiState = UiState.Success,
+ bookDetail = BookDetailModel(
+ title = "데미안",
+ author = "헤르만 헤세",
+ publisher = "민음사",
+ pubDate = "2023-01-01",
+ coverImageUrl = "",
+ ),
+ eventSink = {},
+ ),
+ )
+ }
+}
+
+@ComponentPreview
+@Composable
+private fun BookDetailSeedStatsPreview() {
ReedTheme {
BookDetailUi(
state = BookDetailUiState(
@@ -377,6 +406,93 @@ private fun BookDetailPreview() {
pubDate = "2023-01-01",
coverImageUrl = "",
),
+ seedsStats = persistentListOf(
+ EmotionModel(name = Emotion.WARM, count = 5),
+ EmotionModel(name = Emotion.JOY, count = 3),
+ EmotionModel(name = Emotion.SAD, count = 2),
+ EmotionModel(name = Emotion.INSIGHT, count = 7),
+ ),
+ readingRecords = persistentListOf(
+ ReadingRecordModel(
+ id = "1",
+ pageNumber = 42,
+ quote = "새는 알에서 나오려고 투쟁한다. 알은 세계이다.",
+ review = "정말 인상 깊은 구절이었다.",
+ emotionTags = listOf("깨달음", "따뜻함"),
+ createdAt = "2024-01-15T10:30:00.000000",
+ ),
+ ReadingRecordModel(
+ id = "2",
+ pageNumber = 78,
+ quote = "나는 더 이상 꿈을 꾸지 않으려 했다.",
+ review = "성장통을 느끼는 부분",
+ emotionTags = listOf("슬픔"),
+ createdAt = "2024-01-20T14:20:00.000000",
+ ),
+ ReadingRecordModel(
+ id = "3",
+ pageNumber = 156,
+ quote = "운명과 성향은 같은 개념의 두 이름이다.",
+ review = "내 삶을 돌아보게 되었다.",
+ emotionTags = listOf("깨달음", "즐거움"),
+ createdAt = "2024-01-25T09:15:00.000000",
+ ),
+ ),
+ readingRecordsTotalCount = 3,
+ eventSink = {},
+ ),
+ )
+ }
+}
+
+@ComponentPreview
+@Composable
+private fun BookDetailSeedsStatsExpandedPreview() {
+ ReedTheme {
+ BookDetailUi(
+ state = BookDetailUiState(
+ uiState = UiState.Success,
+ bookDetail = BookDetailModel(
+ title = "데미안",
+ author = "헤르만 헤세",
+ publisher = "민음사",
+ pubDate = "2023-01-01",
+ coverImageUrl = "",
+ ),
+ seedsStats = persistentListOf(
+ EmotionModel(name = Emotion.WARM, count = 5),
+ EmotionModel(name = Emotion.JOY, count = 3),
+ EmotionModel(name = Emotion.SAD, count = 2),
+ EmotionModel(name = Emotion.INSIGHT, count = 7),
+ ),
+ isStatsExpanded = true,
+ readingRecords = persistentListOf(
+ ReadingRecordModel(
+ id = "1",
+ pageNumber = 42,
+ quote = "새는 알에서 나오려고 투쟁한다. 알은 세계이다.",
+ review = "정말 인상 깊은 구절이었다.",
+ emotionTags = listOf("깨달음", "따뜻함"),
+ createdAt = "2024-01-15T10:30:00.000000",
+ ),
+ ReadingRecordModel(
+ id = "2",
+ pageNumber = 78,
+ quote = "나는 더 이상 꿈을 꾸지 않으려 했다.",
+ review = "성장통을 느끼는 부분",
+ emotionTags = listOf("슬픔"),
+ createdAt = "2024-01-20T14:20:00.000000",
+ ),
+ ReadingRecordModel(
+ id = "3",
+ pageNumber = 156,
+ quote = "운명과 성향은 같은 개념의 두 이름이다.",
+ review = "내 삶을 돌아보게 되었다.",
+ emotionTags = listOf("깨달음", "즐거움"),
+ createdAt = "2024-01-25T09:15:00.000000",
+ ),
+ ),
+ readingRecordsTotalCount = 3,
eventSink = {},
),
)
diff --git a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUiState.kt b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUiState.kt
index 550d0ee10..2d0246ce2 100644
--- a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUiState.kt
+++ b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/BookDetailUiState.kt
@@ -27,6 +27,7 @@ data class BookDetailUiState(
val isLoading: Boolean = false,
val bookDetail: BookDetailModel = BookDetailModel(),
val seedsStats: ImmutableList = persistentListOf(),
+ val isStatsExpanded: Boolean = false,
val readingRecords: ImmutableList = persistentListOf(),
val readingRecordsTotalCount: Int = 0,
val currentStartIndex: Int = 1,
@@ -84,6 +85,7 @@ sealed interface BookDetailUiEvent : CircuitUiEvent {
data class OnRecordItemClick(val recordId: String) : BookDetailUiEvent
data object OnLoadMore : BookDetailUiEvent
data object OnRetryClick : BookDetailUiEvent
+ data class OnStatsToggleClick(val flag: Boolean) : BookDetailUiEvent
}
enum class RecordSort(val value: String) {
diff --git a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt
index db940fd56..67e6ac947 100644
--- a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt
+++ b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/CollectedSeeds.kt
@@ -1,7 +1,11 @@
package com.ninecraft.booket.feature.detail.book.component
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.expandVertically
+import androidx.compose.animation.shrinkVertically
+import androidx.compose.foundation.Image
import androidx.compose.foundation.background
-import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -10,27 +14,43 @@ 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.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.CircleShape
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.runtime.remember
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.unit.dp
+import com.ninecraft.booket.core.common.utils.analyzeEmotions
import com.ninecraft.booket.core.designsystem.ComponentPreview
+import com.ninecraft.booket.core.designsystem.ratioBarColor
import com.ninecraft.booket.core.designsystem.theme.ReedTheme
+import com.ninecraft.booket.core.designsystem.theme.Yellow700
import com.ninecraft.booket.core.model.Emotion
import com.ninecraft.booket.core.model.EmotionModel
-import com.ninecraft.booket.feature.detail.R
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
+import com.ninecraft.booket.core.designsystem.R as designR
@Composable
internal fun CollectedSeeds(
seedsStats: ImmutableList,
+ isStatsExpanded: Boolean,
+ onToggleClick: () -> Unit,
modifier: Modifier = Modifier,
) {
+ val analysisResult = remember(seedsStats) { analyzeEmotions(seedsStats) }
+ val topEmotion = analysisResult.topEmotions.firstOrNull()
+
Column(
modifier = modifier
.fillMaxWidth()
@@ -41,67 +61,222 @@ internal fun CollectedSeeds(
bottom = ReedTheme.spacing.spacing6,
)
.clip(RoundedCornerShape(ReedTheme.radius.md))
- .background(ReedTheme.colors.baseSecondary),
+ .background(ReedTheme.colors.baseSecondary)
+ .padding(ReedTheme.spacing.spacing4),
) {
- Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing4))
- Text(
- text = stringResource(R.string.collected_seed_title),
- modifier = Modifier.padding(horizontal = ReedTheme.spacing.spacing4),
- color = ReedTheme.colors.contentSecondary,
- style = ReedTheme.typography.body2Medium,
+ CollectedSeedsHeader(
+ topEmotion = topEmotion,
+ isStatsExpanded = isStatsExpanded,
+ onToggleClick = onToggleClick,
)
- Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing5))
- Row(
- modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.SpaceEvenly,
+
+ AnimatedVisibility(
+ visible = isStatsExpanded,
+ enter = expandVertically(),
+ exit = shrinkVertically(),
) {
- seedsStats.forEach { emotion ->
- SeedItem(emotion = emotion)
+ Column {
+ Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing4))
+ HorizontalDivider(
+ color = ReedTheme.colors.dividerSm,
+ thickness = 1.dp,
+ )
+ Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing5))
+
+ EmotionRatioBar(seedsStats = seedsStats)
+
+ Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing4))
+
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = Arrangement.spacedBy(ReedTheme.spacing.spacing1),
+ ) {
+ Emotion.entries.forEach { emotion ->
+ val emotionModel = seedsStats.find { it.name == emotion }
+ ?: EmotionModel(emotion, 0)
+ EmotionStatCard(
+ emotion = emotionModel,
+ modifier = Modifier.weight(1f),
+ )
+ }
+ }
}
}
- Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing5))
- Box(
- modifier = Modifier
- .fillMaxWidth()
- .padding(horizontal = ReedTheme.spacing.spacing4)
- .clip(RoundedCornerShape(ReedTheme.radius.sm))
- .background(ReedTheme.colors.basePrimary)
- .border(
- width = 1.dp,
- color = ReedTheme.colors.borderPrimary,
- shape = RoundedCornerShape(ReedTheme.radius.sm),
- )
- .padding(ReedTheme.spacing.spacing3),
+ }
+}
+
+@Composable
+private fun CollectedSeedsHeader(
+ topEmotion: EmotionModel?,
+ isStatsExpanded: Boolean,
+ onToggleClick: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ Row(
+ modifier = modifier
+ .fillMaxWidth()
+ .clickable { onToggleClick() },
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.SpaceBetween,
+ ) {
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
) {
- EmotionAnalysisResultText(
- emotions = seedsStats,
- brandColor = ReedTheme.colors.contentBrand,
- secondaryColor = ReedTheme.colors.contentSecondary,
- emotionTextStyle = ReedTheme.typography.label2SemiBold,
- regularTextStyle = ReedTheme.typography.label2Regular,
- )?.let { annotatedString ->
+ topEmotion?.let { emotion ->
+ Image(
+ painter = painterResource(id = getEmotionImageResourceByDisplayName(emotion.name.displayName)),
+ contentDescription = "Seed Image",
+ modifier = Modifier
+ .size(36.dp)
+ .clip(CircleShape)
+ .background(ReedTheme.colors.basePrimary),
+ )
+ Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing2))
+ }
+
+ Row {
Text(
- text = annotatedString,
- modifier = Modifier.fillMaxWidth(),
- textAlign = TextAlign.Center,
+ text = "'${topEmotion?.name?.displayName ?: ""}'",
+ color = Yellow700,
+ style = ReedTheme.typography.label1SemiBold,
+ )
+ Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing1))
+ Text(
+ text = "감정을 많이 느꼈어요",
+ color = ReedTheme.colors.contentSecondary,
+ style = ReedTheme.typography.label1Medium,
+ )
+ }
+ }
+
+ Icon(
+ imageVector = ImageVector.vectorResource(
+ if (isStatsExpanded) designR.drawable.ic_chevron_up else designR.drawable.ic_chevron_down,
+ ),
+ contentDescription = if (isStatsExpanded) "Collapse" else "Expand",
+ modifier = Modifier.size(24.dp),
+ tint = ReedTheme.colors.contentTertiary,
+ )
+ }
+}
+
+@Composable
+private fun EmotionRatioBar(
+ seedsStats: ImmutableList,
+ modifier: Modifier = Modifier,
+) {
+ val totalCount = seedsStats.sumOf { it.count }.coerceAtLeast(1)
+
+ Row(
+ modifier = modifier
+ .fillMaxWidth()
+ .height(12.dp)
+ .clip(RoundedCornerShape(ReedTheme.radius.full)),
+ ) {
+ Emotion.entries.forEach { emotion ->
+ val emotionModel = seedsStats.find { it.name == emotion }
+ val count = emotionModel?.count ?: 0
+ if (count > 0) {
+ val weight = count.toFloat() / totalCount
+ Box(
+ modifier = Modifier
+ .weight(weight)
+ .height(12.dp)
+ .background(emotion.ratioBarColor),
)
}
}
- Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing4))
+ }
+}
+
+@Composable
+private fun EmotionStatCard(
+ emotion: EmotionModel,
+ modifier: Modifier = Modifier,
+) {
+ Column(
+ modifier = modifier
+ .clip(RoundedCornerShape(ReedTheme.radius.md))
+ .background(ReedTheme.colors.basePrimary)
+ .padding(
+ top = ReedTheme.spacing.spacing3,
+ bottom = ReedTheme.spacing.spacing2,
+ ),
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ Box(
+ modifier = Modifier
+ .size(10.dp)
+ .clip(RoundedCornerShape(ReedTheme.radius.xs))
+ .background(emotion.name.ratioBarColor),
+ )
+
+ Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing2))
+
+ Text(
+ text = emotion.name.displayName,
+ color = ReedTheme.colors.contentSecondary,
+ style = ReedTheme.typography.label2Regular,
+ )
+
+ Text(
+ text = "${emotion.count}개",
+ color = ReedTheme.colors.contentTertiary,
+ style = ReedTheme.typography.caption1Regular,
+ )
+ }
+}
+
+@ComponentPreview
+@Composable
+private fun CollectedSeedsCollapsedPreview() {
+ ReedTheme {
+ CollectedSeeds(
+ seedsStats = persistentListOf(
+ EmotionModel(Emotion.WARM, 4),
+ EmotionModel(Emotion.JOY, 2),
+ EmotionModel(Emotion.SAD, 2),
+ EmotionModel(Emotion.INSIGHT, 2),
+ EmotionModel(Emotion.ETC, 2),
+ ),
+ isStatsExpanded = false,
+ onToggleClick = {},
+ )
}
}
@ComponentPreview
@Composable
-private fun CollectedSeedPreview() {
+private fun CollectedSeedsExpandedPreview() {
ReedTheme {
CollectedSeeds(
seedsStats = persistentListOf(
- EmotionModel(Emotion.WARM, 3),
+ EmotionModel(Emotion.WARM, 4),
EmotionModel(Emotion.JOY, 2),
- EmotionModel(Emotion.SAD, 1),
- EmotionModel(Emotion.INSIGHT, 3),
+ EmotionModel(Emotion.SAD, 2),
+ EmotionModel(Emotion.INSIGHT, 2),
+ EmotionModel(Emotion.ETC, 2),
+ ),
+ isStatsExpanded = true,
+ onToggleClick = {},
+ )
+ }
+}
+
+@ComponentPreview
+@Composable
+private fun CollectedSeedsExpandedDuplicatedPreview() {
+ ReedTheme {
+ CollectedSeeds(
+ seedsStats = persistentListOf(
+ EmotionModel(Emotion.WARM, 4),
+ EmotionModel(Emotion.JOY, 4),
+ EmotionModel(Emotion.SAD, 2),
+ EmotionModel(Emotion.INSIGHT, 2),
+ EmotionModel(Emotion.ETC, 2),
),
+ isStatsExpanded = true,
+ onToggleClick = {},
)
}
}
diff --git a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/ReadingRecordsHeader.kt b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/ReadingRecordsHeader.kt
index 7dfdefb26..d0cf80d0e 100644
--- a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/ReadingRecordsHeader.kt
+++ b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/ReadingRecordsHeader.kt
@@ -43,7 +43,7 @@ internal fun ReadingRecordsHeader(
Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing1))
Text(
text = "$totalCount",
- color = ReedTheme.colors.contentBrand,
+ color = ReedTheme.colors.contentTertiary,
style = ReedTheme.typography.headline2SemiBold,
)
}
diff --git a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt
index 4b0b8d3b7..a5f8f05eb 100644
--- a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt
+++ b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/RecordItem.kt
@@ -1,6 +1,5 @@
package com.ninecraft.booket.feature.detail.book.component
-import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
@@ -11,8 +10,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
-import androidx.compose.foundation.layout.width
-import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
@@ -21,7 +18,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.vector.ImageVector
-import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.style.TextOverflow
@@ -36,6 +32,7 @@ import com.ninecraft.booket.core.designsystem.R as designR
@Composable
internal fun RecordItem(
recordInfo: ReadingRecordModel,
+ onRecordClick: () -> Unit,
onRecordMenuClick: (ReadingRecordModel) -> Unit,
modifier: Modifier = Modifier,
) {
@@ -43,6 +40,7 @@ internal fun RecordItem(
modifier = modifier
.fillMaxSize()
.clip(RoundedCornerShape(ReedTheme.radius.md))
+ .clickable { onRecordClick() }
.background(ReedTheme.colors.baseSecondary)
.padding(
start = ReedTheme.spacing.spacing5,
@@ -55,19 +53,12 @@ internal fun RecordItem(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
- Image(
- painter = painterResource(getEmotionImageResourceByDisplayName(recordInfo.emotionTags[0])),
- contentDescription = "Emotion Graphic",
- modifier = Modifier
- .size(ReedTheme.spacing.spacing8)
- .clip(CircleShape)
- .background(ReedTheme.colors.basePrimary),
- )
- Spacer(modifier = Modifier.width(ReedTheme.spacing.spacing2))
Text(
- text = "#${recordInfo.emotionTags[0]}",
+ text = if (recordInfo.pageNumber != 0) "${recordInfo.pageNumber}p"
+ else "-p",
color = ReedTheme.colors.contentBrand,
- style = ReedTheme.typography.body1SemiBold,
+ style = ReedTheme.typography.label1Medium,
+ fontStyle = FontStyle.Italic,
)
Spacer(modifier = Modifier.weight(1f))
Icon(
@@ -81,7 +72,7 @@ internal fun RecordItem(
tint = ReedTheme.colors.contentTertiary,
)
}
- Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing3))
+ Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing4))
Text(
text = "\"${recordInfo.quote}\"",
color = ReedTheme.colors.contentSecondary,
@@ -89,22 +80,21 @@ internal fun RecordItem(
maxLines = 4,
style = ReedTheme.typography.body2Medium,
)
- Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing4))
+ Spacer(modifier = Modifier.height(ReedTheme.spacing.spacing3))
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
- text = recordInfo.createdAt.toFormattedDate(),
+ text = "#${recordInfo.emotionTags[0]}",
color = ReedTheme.colors.contentTertiary,
style = ReedTheme.typography.label1Medium,
)
Spacer(modifier = Modifier.weight(1f))
Text(
- text = "${recordInfo.pageNumber}p",
+ text = recordInfo.createdAt.toFormattedDate(),
color = ReedTheme.colors.contentTertiary,
- style = ReedTheme.typography.body2Medium,
- fontStyle = FontStyle.Italic,
+ style = ReedTheme.typography.label1Medium,
)
}
}
@@ -116,6 +106,7 @@ fun getEmotionImageResourceByDisplayName(displayName: String): Int {
"즐거움" -> R.drawable.img_joy
"슬픔" -> R.drawable.img_sad
"깨달음" -> R.drawable.img_insight
+ "기타" -> R.drawable.img_etc
else -> R.drawable.img_warm
}
}
@@ -129,8 +120,9 @@ private fun RecordItemPreview() {
quote = "소설가들은 늘 소재를 찾아 떠도는 존재 같지만, 실은 그 반대인 경우가 더 잦다.",
emotionTags = persistentListOf("따뜻함"),
pageNumber = 12,
- createdAt = "2025.06.25",
+ createdAt = "2025-06-25T10:30:00.000000",
),
+ onRecordClick = {},
onRecordMenuClick = {},
)
}
diff --git a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/SeedItem.kt b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/SeedItem.kt
index ebeaf2a46..b35e49652 100644
--- a/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/SeedItem.kt
+++ b/feature/detail/src/main/kotlin/com/ninecraft/booket/feature/detail/book/component/SeedItem.kt
@@ -70,6 +70,7 @@ private fun getEmotionImageResource(emotion: Emotion): Int {
Emotion.JOY -> R.drawable.img_joy
Emotion.SAD -> R.drawable.img_sad
Emotion.INSIGHT -> R.drawable.img_insight
+ Emotion.ETC -> R.drawable.img_etc
}
}
diff --git a/feature/detail/src/main/res/drawable/img_etc.webp b/feature/detail/src/main/res/drawable/img_etc.webp
new file mode 100644
index 000000000..0672c2431
Binary files /dev/null and b/feature/detail/src/main/res/drawable/img_etc.webp differ
diff --git a/feature/detail/src/main/res/drawable/img_insight.webp b/feature/detail/src/main/res/drawable/img_insight.webp
index 77d816fdb..b86a84417 100644
Binary files a/feature/detail/src/main/res/drawable/img_insight.webp and b/feature/detail/src/main/res/drawable/img_insight.webp differ
diff --git a/feature/detail/src/main/res/drawable/img_joy.webp b/feature/detail/src/main/res/drawable/img_joy.webp
index 00414f16c..ab3c16844 100644
Binary files a/feature/detail/src/main/res/drawable/img_joy.webp and b/feature/detail/src/main/res/drawable/img_joy.webp differ
diff --git a/feature/detail/src/main/res/drawable/img_sad.webp b/feature/detail/src/main/res/drawable/img_sad.webp
index 439e3224e..72e11cf4f 100644
Binary files a/feature/detail/src/main/res/drawable/img_sad.webp and b/feature/detail/src/main/res/drawable/img_sad.webp differ
diff --git a/feature/detail/src/main/res/drawable/img_warm.webp b/feature/detail/src/main/res/drawable/img_warm.webp
index a432f9e6f..636b5a412 100644
Binary files a/feature/detail/src/main/res/drawable/img_warm.webp and b/feature/detail/src/main/res/drawable/img_warm.webp differ
diff --git a/feature/detail/stability/detail.stability b/feature/detail/stability/detail.stability
index 4866c0780..b7345b547 100644
--- a/feature/detail/stability/detail.stability
+++ b/feature/detail/stability/detail.stability
@@ -20,12 +20,6 @@ public fun com.ninecraft.booket.feature.detail.book.BookDetailPresenter.present(
restartable: true
params:
-@Composable
-private fun com.ninecraft.booket.feature.detail.book.BookDetailPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.detail.book.BookDetailUi(state: com.ninecraft.booket.feature.detail.book.BookDetailUiState, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -50,12 +44,6 @@ internal fun com.ninecraft.booket.feature.detail.book.component.BookItem(bookDet
- bookDetail: STABLE (marked @Stable or @Immutable)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.detail.book.component.BookItemPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
public fun com.ninecraft.booket.feature.detail.book.component.BookStatusItem(item: com.ninecraft.booket.core.common.constants.BookStatus, selected: kotlin.Boolean, onClick: kotlin.Function0, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -82,29 +70,23 @@ internal fun com.ninecraft.booket.feature.detail.book.component.BookUpdateBottom
- modifier: STABLE (marked @Stable or @Immutable)
@Composable
-private fun com.ninecraft.booket.feature.detail.book.component.BookUpdateBottomSheetPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
-@Composable
-private fun com.ninecraft.booket.feature.detail.book.component.ChoiceBottomSheetPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
-@Composable
-private fun com.ninecraft.booket.feature.detail.book.component.CollectedSeedPreview(): kotlin.Unit
+internal fun com.ninecraft.booket.feature.detail.book.component.CollectedSeeds(seedsStats: kotlinx.collections.immutable.ImmutableList, isStatsExpanded: kotlin.Boolean, onToggleClick: kotlin.Function0, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
restartable: true
params:
+ - seedsStats: STABLE (known stable type)
+ - isStatsExpanded: STABLE (primitive type)
+ - onToggleClick: STABLE (function type)
+ - modifier: STABLE (marked @Stable or @Immutable)
@Composable
-internal fun com.ninecraft.booket.feature.detail.book.component.CollectedSeeds(seedsStats: kotlinx.collections.immutable.ImmutableList, modifier: androidx.compose.ui.Modifier): kotlin.Unit
+private fun com.ninecraft.booket.feature.detail.book.component.CollectedSeedsHeader(topEmotion: com.ninecraft.booket.core.model.EmotionModel?, isStatsExpanded: kotlin.Boolean, onToggleClick: kotlin.Function0, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
restartable: true
params:
- - seedsStats: STABLE (known stable type)
+ - topEmotion: STABLE (marked @Stable or @Immutable)
+ - isStatsExpanded: STABLE (primitive type)
+ - onToggleClick: STABLE (function type)
- modifier: STABLE (marked @Stable or @Immutable)
@Composable
@@ -141,42 +123,41 @@ internal fun com.ninecraft.booket.feature.detail.book.component.EmotionAnalysisR
- regularTextStyle: STABLE (marked @Stable or @Immutable)
@Composable
-private fun com.ninecraft.booket.feature.detail.book.component.EmotionTextAllCasesPreview(): kotlin.Unit
+private fun com.ninecraft.booket.feature.detail.book.component.EmotionRatioBar(seedsStats: kotlinx.collections.immutable.ImmutableList, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
restartable: true
params:
+ - seedsStats: STABLE (known stable type)
+ - modifier: STABLE (marked @Stable or @Immutable)
@Composable
-internal fun com.ninecraft.booket.feature.detail.book.component.ReadingRecordsHeader(totalCount: kotlin.Int, currentRecordSort: com.ninecraft.booket.feature.detail.book.RecordSort, onReadingRecordClick: kotlin.Function0, modifier: androidx.compose.ui.Modifier): kotlin.Unit
+private fun com.ninecraft.booket.feature.detail.book.component.EmotionStatCard(emotion: com.ninecraft.booket.core.model.EmotionModel, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
restartable: true
params:
- - totalCount: STABLE (primitive type)
- - currentRecordSort: STABLE (class with no mutable properties)
- - onReadingRecordClick: STABLE (function type)
+ - emotion: STABLE (marked @Stable or @Immutable)
- modifier: STABLE (marked @Stable or @Immutable)
@Composable
-private fun com.ninecraft.booket.feature.detail.book.component.ReadingRecordsHeaderPreview(): kotlin.Unit
+internal fun com.ninecraft.booket.feature.detail.book.component.ReadingRecordsHeader(totalCount: kotlin.Int, currentRecordSort: com.ninecraft.booket.feature.detail.book.RecordSort, onReadingRecordClick: kotlin.Function0, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
restartable: true
params:
+ - totalCount: STABLE (primitive type)
+ - currentRecordSort: STABLE (class with no mutable properties)
+ - onReadingRecordClick: STABLE (function type)
+ - modifier: STABLE (marked @Stable or @Immutable)
@Composable
-internal fun com.ninecraft.booket.feature.detail.book.component.RecordItem(recordInfo: com.ninecraft.booket.core.model.ReadingRecordModel, onRecordMenuClick: kotlin.Function1, modifier: androidx.compose.ui.Modifier): kotlin.Unit
+internal fun com.ninecraft.booket.feature.detail.book.component.RecordItem(recordInfo: com.ninecraft.booket.core.model.ReadingRecordModel, onRecordClick: kotlin.Function0, onRecordMenuClick: kotlin.Function1, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
restartable: true
params:
- recordInfo: STABLE (marked @Stable or @Immutable)
+ - onRecordClick: STABLE (function type)
- onRecordMenuClick: STABLE (function type)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.detail.book.component.RecordItemPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.detail.book.component.RecordSortBottomSheet(onDismissRequest: kotlin.Function0, sheetState: androidx.compose.material3.SheetState, onCloseButtonClick: kotlin.Function0, recordSortItems: kotlinx.collections.immutable.ImmutableList, currentRecordSort: com.ninecraft.booket.feature.detail.book.RecordSort, onItemSelected: kotlin.Function1, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -190,12 +171,6 @@ internal fun com.ninecraft.booket.feature.detail.book.component.RecordSortBottom
- onItemSelected: STABLE (function type)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.detail.book.component.RecordSortBottomSheetPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
public fun com.ninecraft.booket.feature.detail.book.component.RecordSortItem(item: com.ninecraft.booket.feature.detail.book.RecordSort, selected: kotlin.Boolean, onClick: kotlin.Function0, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -214,12 +189,6 @@ internal fun com.ninecraft.booket.feature.detail.book.component.SeedItem(emotion
- emotion: STABLE (marked @Stable or @Immutable)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.detail.book.component.SeedItemPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.detail.card.HandleRecordCardSideEffects(state: com.ninecraft.booket.feature.detail.card.RecordCardUiState, recordCardGraphicsLayer: androidx.compose.ui.graphics.layer.GraphicsLayer, eventSink: kotlin.Function1): kotlin.Unit
skippable: false
@@ -243,12 +212,6 @@ internal fun com.ninecraft.booket.feature.detail.card.RecordCardUi(state: com.ni
- state: STABLE (class with no mutable properties)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.detail.card.RecordCardUiPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.detail.card.component.RecordCard(quote: kotlin.String, bookTitle: kotlin.String, emotion: kotlin.String, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -259,12 +222,6 @@ internal fun com.ninecraft.booket.feature.detail.card.component.RecordCard(quote
- emotion: STABLE (String is immutable)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.detail.card.component.RecordCardPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.detail.record.HandleRecordDetailSideEffects(state: com.ninecraft.booket.feature.detail.record.RecordDetailUiState): kotlin.Unit
skippable: true
@@ -294,18 +251,6 @@ internal fun com.ninecraft.booket.feature.detail.record.RecordDetailUi(state: co
- state: STABLE (class with no mutable properties)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.detail.record.ReviewDetailEmptyPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
-@Composable
-private fun com.ninecraft.booket.feature.detail.record.ReviewDetailPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.detail.record.component.BookItem(imageUrl: kotlin.String, bookTitle: kotlin.String, author: kotlin.String, publisher: kotlin.String, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -317,24 +262,6 @@ internal fun com.ninecraft.booket.feature.detail.record.component.BookItem(image
- publisher: STABLE (String is immutable)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.detail.record.component.BookItemPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
-@Composable
-private fun com.ninecraft.booket.feature.detail.record.component.ChoiceBottomSheetPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
-@Composable
-private fun com.ninecraft.booket.feature.detail.record.component.QuoteBoxPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.detail.record.component.QuoteItem(quote: kotlin.String, page: kotlin.Int, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -368,18 +295,6 @@ private fun com.ninecraft.booket.feature.detail.record.component.RecordMenuItem(
- onClick: STABLE (function type)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.detail.record.component.ReviewBoxEmptyPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
-@Composable
-private fun com.ninecraft.booket.feature.detail.record.component.ReviewBoxPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.detail.record.component.ReviewItem(emotion: kotlin.String, createdAt: kotlin.String, review: kotlin.String, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
diff --git a/feature/edit/stability/edit.stability b/feature/edit/stability/edit.stability
index b44dddd06..5543c7f9e 100644
--- a/feature/edit/stability/edit.stability
+++ b/feature/edit/stability/edit.stability
@@ -26,12 +26,6 @@ internal fun com.ninecraft.booket.feature.edit.emotion.EmotionEditUi(state: com.
- state: STABLE (class with no mutable properties)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.edit.emotion.EmotionEditUiPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
private fun com.ninecraft.booket.feature.edit.emotion.EmotionItem(emotion: com.ninecraft.booket.core.model.Emotion, onClick: kotlin.Function0, isSelected: kotlin.Boolean, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -70,12 +64,6 @@ internal fun com.ninecraft.booket.feature.edit.record.RecordEditUi(state: com.ni
- state: STABLE (class with no mutable properties)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.edit.record.RecordEditUiPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.edit.record.component.BookItem(imageUrl: kotlin.String, bookTitle: kotlin.String, author: kotlin.String, publisher: kotlin.String, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -87,9 +75,3 @@ internal fun com.ninecraft.booket.feature.edit.record.component.BookItem(imageUr
- publisher: STABLE (String is immutable)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.edit.record.component.BookItemPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
diff --git a/feature/home/stability/home.stability b/feature/home/stability/home.stability
index d30e4f8bb..7c83f45e2 100644
--- a/feature/home/stability/home.stability
+++ b/feature/home/stability/home.stability
@@ -25,12 +25,6 @@ public fun com.ninecraft.booket.feature.home.HomePresenter.present(): com.ninecr
restartable: true
params:
-@Composable
-private fun com.ninecraft.booket.feature.home.HomePreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.home.HomeUi(state: com.ninecraft.booket.feature.home.HomeUiState, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -49,12 +43,6 @@ public fun com.ninecraft.booket.feature.home.component.BookCard(recentBookInfo:
- onRecordButtonClick: STABLE (function type)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.home.component.BookCardPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
public fun com.ninecraft.booket.feature.home.component.EmptyBookCard(onBookRegisterClick: kotlin.Function0, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -63,12 +51,6 @@ public fun com.ninecraft.booket.feature.home.component.EmptyBookCard(onBookRegis
- onBookRegisterClick: STABLE (function type)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.home.component.EmptyBookCardPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
public fun com.ninecraft.booket.feature.home.component.HomeBanner(onBookRegisterClick: kotlin.Function0, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -77,12 +59,6 @@ public fun com.ninecraft.booket.feature.home.component.HomeBanner(onBookRegister
- onBookRegisterClick: STABLE (function type)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.home.component.HomeBannerPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
public fun com.ninecraft.booket.feature.home.component.HomeHeader(onSettingsClick: kotlin.Function0, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -91,9 +67,3 @@ public fun com.ninecraft.booket.feature.home.component.HomeHeader(onSettingsClic
- onSettingsClick: STABLE (function type)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.home.component.HomeHeaderPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
diff --git a/feature/library/stability/library.stability b/feature/library/stability/library.stability
index 73e108888..1138df11d 100644
--- a/feature/library/stability/library.stability
+++ b/feature/library/stability/library.stability
@@ -32,12 +32,6 @@ public fun com.ninecraft.booket.feature.library.LibraryPresenter.present(): com.
restartable: true
params:
-@Composable
-private fun com.ninecraft.booket.feature.library.LibraryPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.library.LibraryUi(state: com.ninecraft.booket.feature.library.LibraryUiState, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -46,12 +40,6 @@ internal fun com.ninecraft.booket.feature.library.LibraryUi(state: com.ninecraft
- state: STABLE (class with no mutable properties)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.library.component.ChipPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
public fun com.ninecraft.booket.feature.library.component.FilterChip(option: com.ninecraft.booket.feature.library.LibraryFilterOption, count: kotlin.Int, isSelected: kotlin.Boolean, onChipClick: kotlin.Function1, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -73,12 +61,6 @@ public fun com.ninecraft.booket.feature.library.component.FilterChipGroup(filter
- onChipClick: STABLE (function type)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.library.component.FilterChipGroupPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
public fun com.ninecraft.booket.feature.library.component.LibraryBookItem(book: com.ninecraft.booket.core.model.LibraryBookSummaryModel, onBookClick: kotlin.Function1, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -88,12 +70,6 @@ public fun com.ninecraft.booket.feature.library.component.LibraryBookItem(book:
- onBookClick: STABLE (function type)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.library.component.LibraryBookItemPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
public fun com.ninecraft.booket.feature.library.component.LibraryHeader(onSearchClick: kotlin.Function0, onSettingClick: kotlin.Function0, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -103,9 +79,3 @@ public fun com.ninecraft.booket.feature.library.component.LibraryHeader(onSearch
- onSettingClick: STABLE (function type)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.library.component.LibraryHeaderPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
diff --git a/feature/login/stability/login.stability b/feature/login/stability/login.stability
index 43c486b5c..005d619f2 100644
--- a/feature/login/stability/login.stability
+++ b/feature/login/stability/login.stability
@@ -18,12 +18,6 @@ public fun com.ninecraft.booket.feature.login.LoginPresenter.present(): com.nine
restartable: true
params:
-@Composable
-private fun com.ninecraft.booket.feature.login.LoginPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.login.LoginUi(state: com.ninecraft.booket.feature.login.LoginUiState, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -45,12 +39,6 @@ public fun com.ninecraft.booket.feature.termsagreement.TermsAgreementPresenter.p
restartable: true
params:
-@Composable
-private fun com.ninecraft.booket.feature.termsagreement.TermsAgreementPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.termsagreement.TermsAgreementUi(state: com.ninecraft.booket.feature.termsagreement.TermsAgreementUiState, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -71,9 +59,3 @@ internal fun com.ninecraft.booket.feature.termsagreement.component.TermItem(titl
- hasDetailAction: STABLE (primitive type)
- onDetailClick: STABLE (function type)
-@Composable
-private fun com.ninecraft.booket.feature.termsagreement.component.TermItemPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
diff --git a/feature/onboarding/stability/onboarding.stability b/feature/onboarding/stability/onboarding.stability
index 74d90270d..cf927d4cb 100644
--- a/feature/onboarding/stability/onboarding.stability
+++ b/feature/onboarding/stability/onboarding.stability
@@ -10,12 +10,6 @@ public fun com.ninecraft.booket.feature.onboarding.OnboardingPresenter.present()
restartable: true
params:
-@Composable
-private fun com.ninecraft.booket.feature.onboarding.OnboardingScreenPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.onboarding.OnboardingUi(state: com.ninecraft.booket.feature.onboarding.OnboardingUiState, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -35,12 +29,6 @@ internal fun com.ninecraft.booket.feature.onboarding.component.OnboardingPage(im
- descriptionRes: STABLE (primitive type)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.onboarding.component.OnboardingPagePreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
@Composable
internal fun com.ninecraft.booket.feature.onboarding.component.PagerIndicator(pageCount: kotlin.Int, pagerState: androidx.compose.foundation.pager.PagerState, modifier: androidx.compose.ui.Modifier): kotlin.Unit
skippable: true
@@ -50,9 +38,3 @@ internal fun com.ninecraft.booket.feature.onboarding.component.PagerIndicator(pa
- pagerState: STABLE (marked @Stable or @Immutable)
- modifier: STABLE (marked @Stable or @Immutable)
-@Composable
-private fun com.ninecraft.booket.feature.onboarding.component.PagerIndicatorPreview(): kotlin.Unit
- skippable: true
- restartable: true
- params:
-
diff --git a/feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt b/feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt
index 8a01ac5ce..2f9e225d5 100644
--- a/feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt
+++ b/feature/record/src/main/kotlin/com/ninecraft/booket/feature/record/register/RecordRegisterPresenter.kt
@@ -32,6 +32,7 @@ import dev.zacsweers.metro.Assisted
import dev.zacsweers.metro.AssistedFactory
import dev.zacsweers.metro.AssistedInject
import kotlinx.collections.immutable.ImmutableList
+import kotlinx.collections.immutable.PersistentMap
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.toPersistentList
@@ -96,9 +97,9 @@ class RecordRegisterPresenter(
val emotions by rememberRetained { mutableStateOf(Emotion.entries.toPersistentList()) }
var emotionDetails by rememberRetained { mutableStateOf(persistentListOf()) }
var selectedEmotion by rememberRetained { mutableStateOf(null) }
- var selectedEmotionDetails by rememberRetained { mutableStateOf