Skip to content

Commit

Permalink
Merge branch 'develop' into feat-main-map-modal
Browse files Browse the repository at this point in the history
# Conflicts:
#	app/src/main/res/values/dimens.xml
#	app/src/main/res/values/strings.xml
  • Loading branch information
jihyunniiii committed Jan 5, 2024
2 parents 0f4c75d + 812b6d9 commit 06194cb
Show file tree
Hide file tree
Showing 32 changed files with 834 additions and 28 deletions.
7 changes: 7 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
buildConfigField("String", "BASE_URL", properties["base.url"].toString())
buildConfigField("String", "ACCESS_TOKEN", properties["access.token"].toString())
buildConfigField("String", "NAVER_MAP_CLIENT_ID", properties["naver.map.client.id"].toString())
manifestPlaceholders["IO_SENTRY_DSN"] = properties["io.sentry.dsn"] as String
}

Expand Down Expand Up @@ -89,6 +90,12 @@ dependencies {
implementation(libs.bundles.okhttp)
implementation(libs.bundles.retrofit)
implementation(libs.kotlin.serialization.json)

// Naver Map
implementation(libs.naver.maps)

// Location
implementation(libs.play.services.location)
}

ktlint {
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

<application
android:name=".PingleApp"
Expand All @@ -16,6 +18,11 @@
android:theme="@style/Theme.Pingle"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".presentation.ui.joingroup.JoinGroupSuccessActivity"
android:exported="false"
android:screenOrientation="portrait"
tools:ignore="LockedOrientationActivity" />
<activity
android:name=".presentation.ui.onboarding.OnBoardingActivity"
android:exported="false"
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/java/org/sopt/pingle/PingleApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package org.sopt.pingle

import android.app.Application
import androidx.appcompat.app.AppCompatDelegate
import com.naver.maps.map.NaverMapSdk
import dagger.hilt.android.HiltAndroidApp
import org.sopt.pingle.BuildConfig.NAVER_MAP_CLIENT_ID
import org.sopt.pingle.util.PingleDebugTree
import timber.log.Timber

Expand All @@ -13,6 +15,7 @@ class PingleApp : Application() {

setTimber()
setDarkMode()
setNaverMap()
}

private fun setTimber() {
Expand All @@ -22,4 +25,9 @@ class PingleApp : Application() {
private fun setDarkMode() {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
}

private fun setNaverMap() {
NaverMapSdk.getInstance(this).client =
NaverMapSdk.NaverCloudPlatformClient(NAVER_MAP_CLIENT_ID)
}
}
9 changes: 9 additions & 0 deletions app/src/main/java/org/sopt/pingle/domain/model/PinEntity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.pingle.domain.model

data class PinEntity(
val id: Long,
val x: Double,
val y: Double,
val category: String,
val meetingCount: Int
)
21 changes: 21 additions & 0 deletions app/src/main/java/org/sopt/pingle/presentation/mapper/PinMapper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.sopt.pingle.presentation.mapper

import com.naver.maps.geometry.LatLng
import com.naver.maps.map.overlay.Marker
import com.naver.maps.map.overlay.OverlayImage
import org.sopt.pingle.R
import org.sopt.pingle.domain.model.PinEntity
import org.sopt.pingle.presentation.type.CategoryType

fun PinEntity.toMarker(): Marker = Marker().apply {
position = LatLng(y, x)
isHideCollidedMarkers = true
icon = OverlayImage.fromResource(
when (category) {
CategoryType.PLAY.toString() -> R.drawable.ic_map_marker_play_small
CategoryType.STUDY.toString() -> R.drawable.ic_map_marker_study_small
CategoryType.MULTI.toString() -> R.drawable.ic_map_marker_multi_small
else -> R.drawable.ic_map_marker_other_small
}
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.sopt.pingle.presentation.ui.joingroup

import android.os.Bundle
import android.text.Spannable
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.text.style.TextAppearanceSpan
import androidx.core.content.ContextCompat
import org.sopt.pingle.R
import org.sopt.pingle.databinding.ActivityJoinGroupSuccessBinding
import org.sopt.pingle.util.base.BindingActivity

class JoinGroupSuccessActivity :
BindingActivity<ActivityJoinGroupSuccessBinding>(R.layout.activity_join_group_success) {
private lateinit var groupName: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

initLayout()
}

private fun initLayout() {
// TODO 이전 화면에서 Intent를 통해서 groupName을 가져옴
groupName = "SOPT"

binding.tvJoinGroupSuccessDescriptionGroupName.text = SpannableString(
getString(
R.string.join_group_success_description_group_name,
groupName
)
).apply {
setSpan(
TextAppearanceSpan(
this@JoinGroupSuccessActivity,
R.style.TextAppearance_Pingle_Sub_Semi_16
),
GROUP_NAME_START,
groupName.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
setSpan(
ForegroundColorSpan(
ContextCompat.getColor(
this@JoinGroupSuccessActivity,
R.color.g_01
)
),
GROUP_NAME_START,
groupName.length,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}

companion object {
const val GROUP_NAME_START = 0
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,10 @@ class MainActivity : BindingActivity<ActivityMainBinding>(R.layout.activity_main
}

private inline fun <reified T : Fragment> navigateToFragment() {
supportFragmentManager.commit {
replace<T>(R.id.fcv_main_all_navi, T::class.java.canonicalName)
if (supportFragmentManager.findFragmentById(R.id.fcv_main_all_navi) !is T) {
supportFragmentManager.commit {
replace<T>(R.id.fcv_main_all_navi, T::class.java.canonicalName)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,179 @@
package org.sopt.pingle.presentation.ui.main.home.map

import android.Manifest
import android.content.pm.PackageManager
import android.location.Location
import android.os.Bundle
import android.view.View
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.fragment.app.add
import androidx.fragment.app.commit
import androidx.fragment.app.viewModels
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.google.android.gms.location.LocationServices
import com.naver.maps.geometry.LatLng
import com.naver.maps.map.CameraAnimation
import com.naver.maps.map.CameraUpdate
import com.naver.maps.map.LocationTrackingMode
import com.naver.maps.map.MapFragment
import com.naver.maps.map.NaverMap
import com.naver.maps.map.OnMapReadyCallback
import com.naver.maps.map.overlay.OverlayImage
import com.naver.maps.map.util.FusedLocationSource
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.sopt.pingle.R
import org.sopt.pingle.databinding.FragmentMapBinding
import org.sopt.pingle.presentation.mapper.toMarker
import org.sopt.pingle.presentation.type.CategoryType
import org.sopt.pingle.util.base.BindingFragment
import org.sopt.pingle.util.component.PingleChip
import org.sopt.pingle.util.fragment.showToast

class MapFragment : BindingFragment<FragmentMapBinding>(R.layout.fragment_map), OnMapReadyCallback {
private val mapViewModel by viewModels<MapViewModel>()
private lateinit var naverMap: NaverMap
private lateinit var locationSource: FusedLocationSource

class MapFragment : BindingFragment<FragmentMapBinding>(R.layout.fragment_map) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

initMap()
initLayout()
addListeners()
collectData()
setLocationTrackingMode()
}

override fun onMapReady(naverMap: NaverMap) {
this.naverMap = naverMap.apply {
isNightModeEnabled = true
mapType = NaverMap.MapType.Navi

with(uiSettings) {
isZoomControlEnabled = false
isScaleBarEnabled = false
}
}

makeMarkers()
}

private fun initMap() {
val mapFragment =
childFragmentManager.findFragmentById(R.id.fragment_map_naver_map) as MapFragment?
?: MapFragment.newInstance().also {
childFragmentManager.commit {
add<MapFragment>(R.id.fragment_map_naver_map)
setReorderingAllowed(true)
}
}

mapFragment.getMapAsync(this@MapFragment)
}

private fun initLayout() {
with(binding) {
chipMapCategoryPlay.setChipCategoryType(CategoryType.PLAY)
chipMapCategoryStudy.setChipCategoryType(CategoryType.STUDY)
chipMapCategoryMulti.setChipCategoryType(CategoryType.MULTI)
chipMapCategoryOthers.setChipCategoryType(CategoryType.OTHER)
}
}

private fun addListeners() {
binding.fabMapHere.setOnClickListener {
if (::locationSource.isInitialized) {
locationSource.lastLocation?.let { location -> moveMapCamera(location) }
}
}

binding.cgMapCategory.setOnCheckedStateChangeListener { group, checkedIds ->
mapViewModel.setCategory(
category = checkedIds.getOrNull(SINGLE_SELECTION)
?.let { group.findViewById<PingleChip>(it).categoryType }
)
}
}

private fun collectData() {
mapViewModel.category.flowWithLifecycle(lifecycle).onEach {
// TODO 서버 통신 구현 시 삭제 예정
showToast(it?.name ?: "null")
}.launchIn(lifecycleScope)
}

private fun setLocationTrackingMode() {
if (LOCATION_PERMISSIONS.any { permission ->
ContextCompat.checkSelfPermission(
requireContext(),
permission
) == PackageManager.PERMISSION_GRANTED
}
) {
locationSource = FusedLocationSource(this, LOCATION_PERMISSION_REQUEST_CODE)
} else {
requestLocationPermission()
}

LocationServices.getFusedLocationProviderClient(requireContext()).lastLocation.addOnSuccessListener { location ->
if (::naverMap.isInitialized) {
with(naverMap) {
locationSource = this@MapFragment.locationSource
locationTrackingMode = LocationTrackingMode.NoFollow

locationOverlay.apply {
isVisible = true
icon = OverlayImage.fromResource(R.drawable.ic_map_location_overlay)
}
}
}

moveMapCamera(location)
}
}

private fun requestLocationPermission() {
val locationPermissionRequest = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
when {
permissions[LOCATION_PERMISSIONS[0]] == true || permissions[LOCATION_PERMISSIONS[1]] == true -> {
setLocationTrackingMode()
}
}
}

locationPermissionRequest.launch(LOCATION_PERMISSIONS)
}

private fun moveMapCamera(location: Location) {
if (::naverMap.isInitialized) {
naverMap.moveCamera(
CameraUpdate.scrollTo(
LatLng(
location.latitude,
location.longitude
)
).animate(CameraAnimation.Linear)
)
}
}

private fun makeMarkers() {
mapViewModel.dummyPinList.map { pinEntity ->
pinEntity.toMarker().map = naverMap
}
}

companion object {
private const val LOCATION_PERMISSION_REQUEST_CODE = 1000
private val LOCATION_PERMISSIONS = arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
private const val SINGLE_SELECTION = 0
}
}
Loading

0 comments on commit 06194cb

Please sign in to comment.