Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
Expand All @@ -24,50 +23,56 @@ import com.nextroom.nextroom.presentation.extension.throttleClick

@Composable
fun NRToolbar(
title: String,
onBackClick: () -> Unit,
onRightButtonClick: () -> Unit,
title: String? = null,
onBackClick: (() -> Unit)? = null,
rightButtonText: String? = null,
onRightButtonClick: (() -> Unit)? = null,
modifier: Modifier = Modifier
) {
Box(
modifier = modifier,
contentAlignment = Alignment.Center
) {
Text(
text = title,
style = NRTypo.Poppins.size20,
color = NRColor.White,
textAlign = TextAlign.Center,
)
if (title != null) {
Text(
text = title,
style = NRTypo.Poppins.size20,
color = NRColor.White,
textAlign = TextAlign.Center,
)
}

Row(
modifier = modifier
modifier = Modifier
.fillMaxWidth()
.height(64.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
Image(
painter = painterResource(R.drawable.ic_navigate_back_24),
modifier = modifier
modifier = Modifier
.size(64.dp)
.throttleClick { onBackClick() }
.throttleClick { onBackClick?.invoke() }
.padding(20.dp),
contentDescription = null,
)

Text(
text = stringResource(R.string.memo_button),
color = NRColor.Dark01,
style = NRTypo.Poppins.size14,
modifier = modifier
.padding(end = 20.dp)
.background(
color = NRColor.White,
shape = RoundedCornerShape(size = 50.dp)
)
.padding(vertical = 6.dp, horizontal = 16.dp)
.throttleClick { onRightButtonClick() }
)
if (rightButtonText != null) {
Text(
text = rightButtonText,
color = NRColor.Dark01,
style = NRTypo.Poppins.size14,
modifier = Modifier
.padding(end = 20.dp)
.background(
color = NRColor.White,
shape = RoundedCornerShape(size = 50.dp)
)
.padding(vertical = 6.dp, horizontal = 16.dp)
.throttleClick { onRightButtonClick?.invoke() }
)
}
}
}
}
Expand All @@ -78,6 +83,7 @@ private fun NRToolbarPreview() {
NRToolbar(
title = "01:23:45",
onBackClick = {},
rightButtonText = "MEMO",
onRightButtonClick = {}
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package com.nextroom.nextroom.presentation.common.compose

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
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.Path
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

enum class TooltipArrowPosition { Top, TopLeft, TopRight, Bottom, Right }

@Composable
fun NRTooltip(
text: String,
arrowPosition: TooltipArrowPosition,
modifier: Modifier = Modifier
) {
val tooltipColor = NRColor.White
val arrowWidthDp = 16.dp
val arrowHeightDp = 8.dp

if (arrowPosition == TooltipArrowPosition.Right) {
Row(
modifier = modifier.wrapContentSize(),
verticalAlignment = Alignment.CenterVertically
) {
Box(
modifier = Modifier
.background(color = tooltipColor, shape = RoundedCornerShape(8.dp))
.padding(horizontal = 12.dp, vertical = 8.dp)
) {
Text(text = text, style = NRTypo.Body.size14Medium, color = NRColor.Dark01)
}
Canvas(modifier = Modifier.size(arrowHeightDp, arrowWidthDp)) {
drawPath(
path = Path().apply {
moveTo(0f, 0f)
lineTo(0f, size.height)
lineTo(size.width, size.height / 2f)
close()
},
color = tooltipColor
)
}
}
} else {
val horizontalAlignment = when (arrowPosition) {
TooltipArrowPosition.TopLeft -> Alignment.Start
TooltipArrowPosition.TopRight -> Alignment.End
else -> Alignment.CenterHorizontally
}

Column(
modifier = modifier.wrapContentSize(),
horizontalAlignment = horizontalAlignment
) {
if (arrowPosition == TooltipArrowPosition.Top ||
arrowPosition == TooltipArrowPosition.TopLeft ||
arrowPosition == TooltipArrowPosition.TopRight
) {
val arrowModifier = when (arrowPosition) {
TooltipArrowPosition.TopLeft -> Modifier
.size(arrowWidthDp, arrowHeightDp)
.offset(x = 8.dp)
TooltipArrowPosition.TopRight -> Modifier
.size(arrowWidthDp, arrowHeightDp)
.offset(x = (-8).dp)
else -> Modifier.size(arrowWidthDp, arrowHeightDp)
}
Canvas(modifier = arrowModifier) {
drawPath(
path = Path().apply {
moveTo(size.width / 2f, 0f)
lineTo(size.width, size.height)
lineTo(0f, size.height)
close()
},
color = tooltipColor
)
}
}

Box(
modifier = Modifier
.background(color = tooltipColor, shape = RoundedCornerShape(8.dp))
.padding(horizontal = 12.dp, vertical = 8.dp),
) {
Text(
text = text,
style = NRTypo.Body.size14Medium,
color = NRColor.Dark01,
textAlign = TextAlign.Center,
lineHeight = 18.sp,
)
}

if (arrowPosition == TooltipArrowPosition.Bottom) {
Canvas(modifier = Modifier.size(arrowWidthDp, arrowHeightDp)) {
drawPath(
path = Path().apply {
moveTo(0f, 0f)
lineTo(size.width, 0f)
lineTo(size.width / 2f, size.height)
close()
},
color = tooltipColor
)
}
}
}
}
}

@Preview(showBackground = true, backgroundColor = 0xFF151516)
@Composable
private fun NRTooltipTopPreview() {
NRTooltip(text = "남은 시간과 힌트 수 표시", arrowPosition = TooltipArrowPosition.Top)
}

@Preview(showBackground = true, backgroundColor = 0xFF151516)
@Composable
private fun NRTooltipTopLeftPreview() {
NRTooltip(text = "길게 꾹 눌러 종료", arrowPosition = TooltipArrowPosition.TopLeft)
}

@Preview(showBackground = true, backgroundColor = 0xFF151516)
@Composable
private fun NRTooltipTopRightPreview() {
NRTooltip(text = "메모 하러 이동", arrowPosition = TooltipArrowPosition.TopRight)
}

@Preview(showBackground = true, backgroundColor = 0xFF151516)
@Composable
private fun NRTooltipBottomPreview() {
NRTooltip(text = "힌트 코드 입력", arrowPosition = TooltipArrowPosition.Bottom)
}

@Preview(showBackground = true, backgroundColor = 0xFF151516)
@Composable
private fun NRTooltipRightPreview() {
NRTooltip(text = "그리기", arrowPosition = TooltipArrowPosition.Right)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.nextroom.nextroom.presentation.common.compose

import androidx.compose.runtime.Composable
import androidx.compose.ui.text.PlatformTextStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
Expand All @@ -20,6 +21,10 @@ object NextRoomFontFamily {
Font(R.font.poppins_medium, FontWeight.Medium),
Font(R.font.poppins_semi_bold, FontWeight.SemiBold)
)

val NotoSansMono = FontFamily(
Font(R.font.notosansmono_semibold, FontWeight.SemiBold)
)
}

object NRTypo {
Expand Down Expand Up @@ -280,6 +285,18 @@ object NRTypo {
)
}

// ===== NotoSansMono Styles =====
object NotoSansMono {
val size54: TextStyle
@Composable get() = TextStyle(
fontFamily = NextRoomFontFamily.NotoSansMono,
fontWeight = FontWeight.SemiBold,
fontSize = 54.sp,
platformStyle = PlatformTextStyle(includeFontPadding = false),
color = NRColor.White
)
}

// ===== Poppins Styles =====
object Poppins {
val size14: TextStyle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ fun HintTimerToolbar(
NRToolbar(
title = timerText,
onBackClick = onBackClick,
rightButtonText = stringResource(R.string.memo_button),
onRightButtonClick = onMemoClick
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ class TimerFragment : BaseFragment<FragmentTimerBinding>(FragmentTimerBinding::i
}

private fun showModifyTimeBottomSheet(timeLimitInMinute: Int) {
TimerFragmentDirections
NavGraphDirections
.showModifyTimeBottomSheet(
requestKey = REQUEST_KEY_MODIFY_TIME,
timeLimitInMinute = timeLimitInMinute
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class LoginFragment : BaseViewModelFragment<FragmentLoginBinding, LoginViewModel
super.initListeners()
binding.tvStartWithEmail.setOnClickListener(this)
binding.llStartWithGoogle.setOnClickListener(this)
binding.tvTryWithoutLogin.setOnClickListener(this)
}

override fun setFragmentResultListeners() {
Expand Down Expand Up @@ -73,10 +74,15 @@ class LoginFragment : BaseViewModelFragment<FragmentLoginBinding, LoginViewModel
LoginFragmentDirections.moveToSignup(SIGNUP_REQUEST_KEY).also { findNavController().safeNavigate(it) }
}

private fun moveToTutorial() {
LoginFragmentDirections.moveToTutorial().also { findNavController().safeNavigate(it) }
}

override fun onClick(v: View) {
when (v) {
binding.tvStartWithEmail -> moveToEmailLogin()
binding.llStartWithGoogle -> viewModel.requestGoogleAuth()
binding.tvTryWithoutLogin -> moveToTutorial()
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.nextroom.nextroom.presentation.ui.tutorial

import java.io.Serializable

object TutorialData {
const val DEFAULT_TIME_LIMIT_SECONDS = 3600 // 1시간

val hints = listOf(
TutorialHint(
id = 1,
code = "1111",
progress = 33,
hint = "벽에 걸린 시계를 자세히 살펴보세요. 시계 바늘이 가리키는 숫자들의 합이 중요한 단서입니다.",
answer = "시계의 시침은 3, 분침은 9를 가리키고 있습니다. 3+9=12가 첫 번째 비밀번호입니다."
),
TutorialHint(
id = 2,
code = "2222",
progress = 66,
hint = "책장에 있는 책들 중 색상이 다른 책이 하나 있습니다. 그 책의 페이지 번호를 확인하세요.",
answer = "빨간색 책의 27페이지에 금고 비밀번호 '4821'이 적혀있습니다. 금고를 열어 열쇠를 획득하세요."
),
TutorialHint(
id = 3,
code = "3333",
progress = 100,
hint = "마지막 문을 열기 위해서는 방 안의 모든 거울에 비친 글자들을 순서대로 읽어야 합니다.",
answer = "거울에 비친 글자는 'ESCAPE'입니다. 문 앞의 키패드에 이 단어를 입력하면 탈출에 성공합니다!"
)
)

// 랜덤한 힌트를 리턴한다.
fun getRandomHint(code: String): TutorialHint? {
return if (code.length == 4 && code.all { it.isDigit() }) {
val index = code.toInt() % hints.size
hints[index]
} else {
null
}
}
}

data class TutorialHint(
val id: Int,
val code: String,
val progress: Int,
val hint: String,
val answer: String,
val hintImageUrlList: List<String> = emptyList(),
val answerImageUrlList: List<String> = emptyList()
) : Serializable
Loading
Loading