Skip to content

Commit

Permalink
Merge branch 'develop-an' into feature/#51_travel_ui
Browse files Browse the repository at this point in the history
# Conflicts:
#	android/Staccato_AN/app/src/main/java/com/woowacourse/staccato/DeleteDialogFragment.kt
#	android/Staccato_AN/app/src/main/java/com/woowacourse/staccato/presentation/BindingAdapters.kt
#	android/Staccato_AN/app/src/main/java/com/woowacourse/staccato/presentation/visit/VisitFragment.kt
#	android/Staccato_AN/app/src/main/res/drawable/shape_place_holder_oval.xml
#	android/Staccato_AN/app/src/main/res/layout/toolbar_detail.xml
  • Loading branch information
hxeyexn committed Jul 25, 2024
2 parents a2c4410 + cde30c6 commit 3203aea
Show file tree
Hide file tree
Showing 61 changed files with 2,245 additions and 118 deletions.
3 changes: 3 additions & 0 deletions android/.idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions android/.idea/android.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions android/.idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions android/.idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions android/.idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,7 @@ import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
import com.woowacourse.staccato.databinding.FragmentDeleteDialogBinding

class DeleteDialogFragment : DialogFragment() {
private lateinit var dialogHandler: DialogHandler

fun setDialogHandler(newDialogHandler: DialogHandler) {
dialogHandler = newDialogHandler
}

class DeleteDialogFragment(private val dialogHandler: DialogHandler) : DialogFragment() {
private var _binding: FragmentDeleteDialogBinding? = null
private val binding get() = _binding!!

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.woowacourse.staccato.domain.repository

import com.woowacourse.staccato.presentation.timeline.TimelineTravelUiModel

interface TimelineRepository {
fun loadTravels(): List<TimelineTravelUiModel>
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ package com.woowacourse.staccato.presentation
import android.graphics.drawable.Drawable
import android.widget.Button
import android.widget.ImageView
import android.widget.NumberPicker
import android.widget.TextView
import androidx.core.app.NotificationCompat.getColor
import androidx.core.view.isGone
import androidx.databinding.BindingAdapter
import coil.load
import coil.transform.RoundedCornersTransformation
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import com.woowacourse.staccato.R
import com.woowacourse.staccato.presentation.visitcreation.model.TravelUiModel
import java.time.LocalDate

@BindingAdapter(
Expand Down Expand Up @@ -41,6 +43,21 @@ fun ImageView.setCircleImageWithCoil(
}
}

@BindingAdapter(
value = ["coilRoundedCornerImageUrl", "coilPlaceHolder", "coilRoundingRadius"],
)
fun ImageView.setRoundedCornerImageWithCoil(
url: String?,
placeHolder: Drawable? = null,
roundingRadius: Float,
) {
load(url) {
placeholder(placeHolder)
transformations(RoundedCornersTransformation(roundingRadius))
error(placeHolder)
}
}

@BindingAdapter(
value = ["glideImageUrl", "glidePlaceHolder"],
)
Expand All @@ -51,6 +68,7 @@ fun ImageView.loadImageWithGlide(
Glide.with(context)
.load(url)
.placeholder(placeHolder)
.centerCrop()
.error(placeHolder)
.into(this)
}
Expand Down Expand Up @@ -81,6 +99,7 @@ fun ImageView.setRoundedCornerImageWithGlide(
Glide.with(context)
.load(url)
.placeholder(placeHolder)
.centerCrop()
.apply(RequestOptions.bitmapTransform(RoundedCorners(roundingRadius)))
.error(placeHolder)
.into(this)
Expand All @@ -104,6 +123,45 @@ fun Button.setTravelSaveButtonActive(
}
}

@BindingAdapter("bindSetSelectedTravel")
fun TextView.setSelectedTravel(selectedTravel: TravelUiModel?) {
if (selectedTravel == null) {
text = resources.getString(R.string.visit_creation_travel_selection_hint)
setTextColor(resources.getColor(R.color.gray3, null))
} else {
text = selectedTravel.travelTitle
setTextColor(resources.getColor(R.color.staccato_black, null))
}
}

@BindingAdapter("bindSetSelectedVisitedAt")
fun TextView.setSelectedVisitedAt(selectedVisitedAt: String?) {
if (selectedVisitedAt == null) {
text = resources.getString(R.string.visit_creation_visited_at_hint)
setTextColor(resources.getColor(R.color.gray3, null))
} else {
text = selectedVisitedAt
setTextColor(resources.getColor(R.color.staccato_black, null))
}
}

@BindingAdapter(
value = ["selectedTravel", "visitedAt"],
)
fun Button.setVisitUpdateButtonActive(
travel: TravelUiModel?,
visitedAt: String?,
) {
isEnabled =
if (travel == null || visitedAt == null) {
setTextColor(resources.getColor(R.color.gray4, null))
false
} else {
setTextColor(resources.getColor(R.color.white, null))
true
}
}

@BindingAdapter(
value = ["startDate", "endDate"],
)
Expand All @@ -118,3 +176,29 @@ fun TextView.setTravelPeriod(
setTextColor(resources.getColor(R.color.staccato_black, null))
}
}

@BindingAdapter("bindSetVisitedAtConfirmButtonActive")
fun Button.setVisitedAtConfirmButtonActive(items: List<String>?) {
isEnabled =
if (items.isNullOrEmpty()) {
setTextColor(resources.getColor(R.color.gray4, null))
false
} else {
setTextColor(resources.getColor(R.color.white, null))
true
}
}

@BindingAdapter("bindSetVisitedAtNumberPickerItems")
fun NumberPicker.setVisitedAtNumberPickerItems(items: List<String>?) {
if (items.isNullOrEmpty()) {
isGone = true
} else {
displayedValues = items.toTypedArray()
}
}

@BindingAdapter("bindSetVisitedAtIsEmptyVisibility")
fun TextView.setVisitedAtIsEmptyVisibility(items: List<String>?) {
isGone = !items.isNullOrEmpty()
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.woowacourse.staccato.presentation.main

import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.activity.addCallback
import androidx.activity.result.contract.ActivityResultContracts
Expand Down Expand Up @@ -69,6 +70,8 @@ class MainActivity : BindingActivity<ActivityMainBinding>() {
setupBottomSheetController()
setupBottomSheetNavigation()
setupBackPressedHandler()
setUpBottomSheetBehaviorAction()
setUpToolbar()
}

private fun setupBackPressedHandler() {
Expand Down Expand Up @@ -134,4 +137,51 @@ class MainActivity : BindingActivity<ActivityMainBinding>() {
.setLaunchSingleTop(true)
.setPopUpTo(popUpToId, false)
.build()

private fun setUpToolbar() {
binding.toolbarMain.setNavigationOnClickListener {
if (navController.currentDestination?.id == R.id.timelineFragment) {
behavior.state = STATE_COLLAPSED
} else {
navController.popBackStack()
}
}
}

private fun setUpBottomSheetBehaviorAction() {
behavior.apply {
addBottomSheetCallback(
object : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(
bottomSheet: View,
newState: Int,
) {
when (newState) {
STATE_COLLAPSED -> {
binding.toolbarMain.visibility = View.INVISIBLE
}

STATE_EXPANDED -> {
binding.btnTimeline.visibility = View.INVISIBLE
}

else -> {
binding.toolbarMain.visibility = View.VISIBLE
binding.btnTimeline.visibility = View.VISIBLE
}
}
}

override fun onSlide(
bottomSheet: View,
slideOffset: Float,
) {
binding.tvBottomSheetRemindYourMemories.alpha = 1 - slideOffset
binding.btnTimeline.alpha = 1 - slideOffset
binding.toolbarMain.alpha = slideOffset
}
},
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.woowacourse.staccato.presentation.timeline

import com.woowacourse.staccato.domain.repository.TimelineRepository

class TempTimelineRepository : TimelineRepository {
private val travels =
listOf(
TimelineTravelUiModel(
travelId = 0L,
travelThumbnail = null,
travelPeriod = "2024.07.23",
travelTitle = "우테코 선릉캠 탐방",
),
TimelineTravelUiModel(
travelId = 1L,
travelThumbnail = "https://cdn.tourtoctoc.com/news/photo/202305/520_2742_5617.jpg",
travelPeriod = "2024.06.30 - 07.04",
travelTitle = "제주도 여행",
),
TimelineTravelUiModel(
travelId = 2L,
travelThumbnail = null,
travelPeriod = "2024.06.28",
travelTitle = "파리 여행",
),
TimelineTravelUiModel(
travelId = 3L,
travelThumbnail =
"https://pds.joongang.co.kr/news/component/htmlphoto_mmdata/" +
"202203/11/97c3e727-0d4c-4fba-83c7-7558d9455651.jpg",
travelPeriod = "2024.06.26",
travelTitle = "포항 영일대 당일치기",
),
TimelineTravelUiModel(
travelId = 4L,
travelThumbnail =
"https://triptogo.world/web/product/big/" +
"202104/e827b41e2d22aeddc8015b018df9aa5b.png",
travelPeriod = "2024.05.28 - 29",
travelTitle = "서울 나들이",
),
TimelineTravelUiModel(
travelId = 5L,
travelThumbnail =
"https://triptogo.world/web/product/big/" +
"202104/e827b41e2d22aeddc8015b018df9aa5b.png",
travelPeriod = "2024.05.28 - 29",
travelTitle = "서울 나들이",
),
TimelineTravelUiModel(
travelId = 6L,
travelThumbnail =
"https://triptogo.world/web/product/big/" +
"202104/e827b41e2d22aeddc8015b018df9aa5b.png",
travelPeriod = "2024.05.28 - 29",
travelTitle = "서울 나들이",
),
TimelineTravelUiModel(
travelId = 7L,
travelThumbnail =
"https://triptogo.world/web/product/big/" +
"202104/e827b41e2d22aeddc8015b018df9aa5b.png",
travelPeriod = "2024.05.28 - 29",
travelTitle = "서울 나들이",
),
)

override fun loadTravels(): List<TimelineTravelUiModel> {
return travels
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,51 @@ package com.woowacourse.staccato.presentation.timeline

import android.os.Bundle
import android.view.View
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import com.woowacourse.staccato.R
import com.woowacourse.staccato.databinding.FragmentTimelineBinding
import com.woowacourse.staccato.presentation.base.BindingFragment
import com.woowacourse.staccato.presentation.timeline.adapter.TimelineAdapter

class TimelineFragment :
BindingFragment<FragmentTimelineBinding>(R.layout.fragment_timeline),
TimelineHandler {
private lateinit var viewModel: TimelineViewModel
private lateinit var adapter: TimelineAdapter

class TimelineFragment : BindingFragment<FragmentTimelineBinding>(R.layout.fragment_timeline) {
override fun onViewCreated(
view: View,
savedInstanceState: Bundle?,
) {
binding.btnTimeline.setOnClickListener {
findNavController().navigate(R.id.action_timelineFragment_to_travelFragment)
setUpViewModel()
setUpAdapter()
setUpObserving()
viewModel.loadTimeline()
}

private fun setUpViewModel() {
val viewModelFactory = TimelineViewModelFactory(TempTimelineRepository())
viewModel = ViewModelProvider(this, viewModelFactory)[TimelineViewModel::class.java]
}

private fun setUpAdapter() {
adapter = TimelineAdapter(this)
binding.rvTimeline.adapter = adapter
}

private fun setUpObserving() {
viewModel.travels.observe(viewLifecycleOwner) { timeline ->
adapter.setTravels(timeline)
}
}

private fun navigateToTravel() {
findNavController().navigate(R.id.action_timelineFragment_to_travelFragment)
}

override fun onTravelClicked(travelId: Long) {
// Log.d("ㅌㅅㅌ", "clicked item: $travelId")
navigateToTravel()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.woowacourse.staccato.presentation.timeline

interface TimelineHandler {
fun onTravelClicked(travelId: Long)
}
Loading

0 comments on commit 3203aea

Please sign in to comment.