Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
342dc5a
feat: 매칭 필터 ui 구현 #411
edv-Shin Dec 8, 2025
c6a3d80
feat: 다중 선택 추가 #411
edv-Shin Dec 8, 2025
92a599b
feat: 필터 간격 추가 #411
edv-Shin Dec 8, 2025
44ded05
fix: 필터 ui 갱신 안되는 오류 수정 #411
edv-Shin Dec 8, 2025
8a597c7
feat: 패키지 변경, 초기화 추가 #411
edv-Shin Dec 8, 2025
39ee8a7
fix: ktlint 문법 수정 #411
edv-Shin Dec 8, 2025
732fa9f
feat: 다중 선택 전체 옵션 추가 #411
edv-Shin Dec 9, 2025
b8cb29b
fix: ktlint 문법 수정 #411
edv-Shin Dec 9, 2025
db3d13f
feat: 웹소켓 연결, 네트워크 감지 및 백오프 구현 #414
edv-Shin Dec 28, 2025
958e7b1
feat: 소켓 request와 response 분리 #414
edv-Shin Dec 28, 2025
c8b5544
refactor: 메세지 전송 로직 수정 (회의 필요) #414
edv-Shin Dec 28, 2025
3892553
Merge pull request #416 from projects200/feat/filter-ui-411
edv-Shin Dec 28, 2025
cf5c4b8
Merge remote-tracking branch 'origin/dev' into feat/websocket-414
edv-Shin Dec 28, 2025
2714c95
fix: dto 수정 #414
edv-Shin Dec 29, 2025
810330c
chore: 불필요한 주석 삭제 #414
edv-Shin Dec 29, 2025
b3e739b
fix: ktlint 문법 수정 #414
edv-Shin Dec 29, 2025
665044b
feat: 주석 추가 #414
edv-Shin Dec 29, 2025
201c8da
feat: 멤버 id 저장 및 채팅 수신 시 비교 로직 추가 #426
edv-Shin Dec 29, 2025
94e5d33
fix: magic string를 constant로 수정 #426
edv-Shin Dec 29, 2025
d47824d
fix: magic string를 constant로 수정 #426
edv-Shin Dec 29, 2025
5a9560f
feat: thread safe하지 않은 변수를 AtomicInteger로 수정 #414
edv-Shin Dec 30, 2025
4fb3d61
refactor: repositoryScope 도입, Job 단위 취소로 리소스 누수 해결 #414
edv-Shin Dec 30, 2025
1e4787d
fix: Mutex 도입을 통한 웹소켓 중복 연결 및 타이밍 이슈 해결 #414
edv-Shin Dec 30, 2025
c7e5e9c
fix: ktlint 문법 수정 #414
edv-Shin Dec 30, 2025
1296e6a
Merge pull request #427 from projects200/feat/websocket-414
edv-Shin Jan 7, 2026
7bfd1ad
feat: 조회한 운동장소 필터 적용 #429
edv-Shin Jan 12, 2026
ca00156
feat: 운동 종류 선택 개발 #437
edv-Shin Jan 14, 2026
7207461
feat: 기록 완료 시 운동 종류 적용 #436
edv-Shin Jan 14, 2026
cf9e7c6
feat: 운동 장소 선택 ui 개발 #436
edv-Shin Jan 14, 2026
10a288a
feat: 운동 장소 지도에서 선택 #436
edv-Shin Jan 14, 2026
0e1b7c6
fix: 기록 수정시 종류 초기값이 표시가 안되는 버그 수정 #436
edv-Shin Jan 15, 2026
8cf300f
Merge branch 'feat/member-id-426' into feat/websocket
edv-Shin Jan 15, 2026
f80b9de
feat: 상대방 퇴장/차단 대응 로직 구현 #441
edv-Shin Jan 16, 2026
6adff4b
fix: ktlint 문법 수정 #437
edv-Shin Jan 18, 2026
6f0b72e
Merge branch 'feat/exercise-type-437' into feat/exercise-place-436
edv-Shin Jan 18, 2026
b74f173
fix: ktlint 문법 수정
edv-Shin Jan 18, 2026
ed305a5
Merge pull request #443 from projects200/feat/exercise-type-437
edv-Shin Jan 18, 2026
ee298f0
feat: 채팅 요청 시 위치 확인 #440
edv-Shin Jan 18, 2026
c3349df
feat: 온보딩 화면구현 #439
edv-Shin Jan 19, 2026
792dc7f
feat: 필터에 맞는 회원만 표시 #429
edv-Shin Jan 19, 2026
ac90f3e
Merge branch 'feat/local-filter-429' into feat/filter
edv-Shin Jan 19, 2026
f7b89d4
fix: ktlint 문법 수정 #439
edv-Shin Jan 19, 2026
0d6bcd9
feat: 화면 이동에 따라 api 재호출할지 결정 #432
edv-Shin Jan 19, 2026
e3598af
feat: 상수 변수로 변경 #432
edv-Shin Jan 20, 2026
5645775
feat: 필터 선택 및 초기화 시 쓰로틀링 적용 #433
edv-Shin Jan 20, 2026
a0a6a82
feat: 회원 운동장소 리스트 조회 api에 운동장소 id 추가 #440
edv-Shin Jan 20, 2026
fe515fc
Merge branch 'dev' into feat/location-limit-440
edv-Shin Jan 20, 2026
baf3fd2
feat: 파라미터 오류 수정 #440
edv-Shin Jan 20, 2026
40c899c
feat: 실시간 상대방 퇴장/차단 대응 #441
edv-Shin Jan 21, 2026
17a4fd0
feat: 응답값 추가 #433
edv-Shin Jan 21, 2026
a915fdb
fix: 불필요한 변수 삭제 #433
edv-Shin Jan 22, 2026
0a51f19
fix: 변수 매핑 수정 #433
edv-Shin Jan 22, 2026
f427496
Merge pull request #445 from projects200/feat/map-caching-432
edv-Shin Jan 22, 2026
1ddc1f4
Merge remote-tracking branch 'origin/feat/filter' into feat/filter-th…
edv-Shin Jan 23, 2026
d52c519
fix: ktlint 문법 수정
edv-Shin Jan 23, 2026
67802f9
fix: ktlint 문법 수정 #440
edv-Shin Jan 23, 2026
3ce1594
Merge pull request #456 from projects200/feat/location-limit-440
edv-Shin Jan 23, 2026
d4c76d0
fix: ktlint 문법 수정
edv-Shin Jan 23, 2026
713d7aa
Merge pull request #458 from projects200/feat/websocket
edv-Shin Jan 23, 2026
fb4550b
Merge remote-tracking branch 'origin/dev' into feat/filter
edv-Shin Jan 23, 2026
81a63a1
fix: ktlint 문법 수정
edv-Shin Jan 23, 2026
d643715
feat: 줌 레벨에 따라 장소 조회 여부 결정
edv-Shin Jan 23, 2026
46334c2
fix: ktlint 문법 수정
edv-Shin Jan 23, 2026
9bfc74a
Merge pull request #457 from projects200/feat/filter
edv-Shin Jan 23, 2026
9aaad79
fix: 오류 해결
edv-Shin Jan 23, 2026
8a911b9
fix: 지도 확대 로직 수정
edv-Shin Jan 24, 2026
08506c2
fix: ktlint 문법 수정
edv-Shin Jan 26, 2026
5cd596d
feat: 버전 코드 수정
edv-Shin Jan 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ class MainActivity : AppCompatActivity(), BottomNavigationController {
com.project200.undabang.feature.matching.R.id.exercisePlaceSearchFragment,
com.project200.undabang.feature.matching.R.id.exercisePlaceRegisterFragment,
com.project200.undabang.feature.matching.R.id.matchingGuideFragment,
com.project200.undabang.feature.matching.R.id.matchingUrlFormFragment,
com.project200.undabang.feature.chatting.R.id.chattingRoomFragment,
// ... 필요한 다른 프래그먼트 ID들 추가 ... //
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class MainViewModel
fun login() {
viewModelScope.launch {
val result = loginUseCase()
checkIsRegisteredUseCase()
_loginResult.value = result
}
}
Expand Down
4 changes: 2 additions & 2 deletions common/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest>

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
55 changes: 55 additions & 0 deletions common/src/main/java/com/project200/common/utils/NetworkMonitor.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.project200.common.utils

import android.Manifest
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import androidx.annotation.RequiresPermission
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.callbackFlow
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class NetworkMonitor
@Inject
constructor(
@ApplicationContext context: Context,
) {
private val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

// 현재 인터넷 연결 여부 확인
@RequiresPermission(Manifest.permission.ACCESS_NETWORK_STATE)
fun isCurrentlyConnected(): Boolean {
val activeNetwork = connectivityManager.activeNetwork ?: return false
val capabilities = connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
}

// 네트워크 상태 변경 감지 Flow
val networkState =
callbackFlow {
val callback =
object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
trySend(true)
}

override fun onLost(network: Network) {
trySend(false)
}
}

val request =
NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build()

connectivityManager.registerNetworkCallback(request, callback)
awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
}
}
4 changes: 2 additions & 2 deletions data/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest>

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
7 changes: 6 additions & 1 deletion data/src/main/java/com/project200/data/api/ApiService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,12 @@ interface ApiService {
// 매칭지도 회원들 조회
@GET("api/v1/members")
@AccessTokenApi
suspend fun getMatchingMembers(): BaseResponse<List<GetMatchingMembersDto>>
suspend fun getMatchingMembers(
@Query("leftTopLatitude") leftTopLatitude: Double,
@Query("leftTopLongitude") leftTopLongitude: Double,
@Query("rightBottomLatitude") rightBottomLatitude: Double,
@Query("rightBottomLongitude") rightBottomLongitude: Double,
): BaseResponse<List<GetMatchingMembersDto>>

// 매칭 타 회원 프로필 조회
@GET("api/v1/members/{memberId}/profile")
Expand Down
13 changes: 13 additions & 0 deletions data/src/main/java/com/project200/data/api/ChatApiService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.project200.data.api

import com.project200.data.dto.BaseResponse
import com.project200.data.dto.TicketResponse
import retrofit2.http.POST
import retrofit2.http.Path

interface ChatApiService {
@POST("api/v1/chat-rooms/{chatroomId}/ticket")
suspend fun getChatTicket(
@Path("chatroomId") chatroomId: Long,
): BaseResponse<TicketResponse>
}
8 changes: 8 additions & 0 deletions data/src/main/java/com/project200/data/di/NetworkModule.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.project200.data.di

import com.project200.data.api.ApiService
import com.project200.data.api.ChatApiService
import com.project200.data.utils.FcmTokenProvider
import com.project200.data.utils.LocalDateAdapter
import com.project200.data.utils.LocalDateTimeAdapter
Expand Down Expand Up @@ -71,6 +72,7 @@ object NetworkModule {
.addInterceptor(tokenInterceptor)
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.pingInterval(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build()
}
Expand Down Expand Up @@ -100,4 +102,10 @@ object NetworkModule {
fun provideApiService(retrofit: Retrofit): ApiService {
return retrofit.create(ApiService::class.java)
}

@Provides
@Singleton
fun provideChatApiService(retrofit: Retrofit): ChatApiService {
return retrofit.create(ChatApiService::class.java)
}
}
6 changes: 6 additions & 0 deletions data/src/main/java/com/project200/data/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.project200.data.di
import com.project200.data.impl.AddressRepositoryImpl
import com.project200.data.impl.AppUpdateRepositoryImpl
import com.project200.data.impl.AuthRepositoryImpl
import com.project200.data.impl.ChatSocketRepositoryImpl
import com.project200.data.impl.ChattingRepositoryImpl
import com.project200.data.impl.ExerciseRecordRepositoryImpl
import com.project200.data.impl.FcmRepositoryImpl
Expand All @@ -15,6 +16,7 @@ import com.project200.data.impl.TimerRepositoryImpl
import com.project200.domain.repository.AddressRepository
import com.project200.domain.repository.AppUpdateRepository
import com.project200.domain.repository.AuthRepository
import com.project200.domain.repository.ChatSocketRepository
import com.project200.domain.repository.ChattingRepository
import com.project200.domain.repository.ExerciseRecordRepository
import com.project200.domain.repository.FcmRepository
Expand Down Expand Up @@ -77,6 +79,10 @@ abstract class RepositoryModule {
@Singleton
abstract fun bindChattingRepository(chattingRepositoryImpl: ChattingRepositoryImpl): ChattingRepository

@Binds
@Singleton
abstract fun bindChatSocketRepository(chatSocketRepositoryImpl: ChatSocketRepositoryImpl): ChatSocketRepository

@Binds
@Singleton
abstract fun bindNotificationRepository(notificationRepositoryImpl: NotificationRepositoryImpl): NotificationRepository
Expand Down
59 changes: 59 additions & 0 deletions data/src/main/java/com/project200/data/dto/ChattingDTO.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.project200.data.dto

import com.project200.domain.model.SocketType
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import com.squareup.moshi.Moshi
import java.time.LocalDateTime

@JsonClass(generateAdapter = true)
Expand All @@ -11,6 +14,9 @@ data class PostChatRoomResponse(
@JsonClass(generateAdapter = true)
data class PostChatRoomRequest(
val receiverId: String,
val exerciseLocationId: Long,
val requesterLatitude: Double,
val requesterLongitude: Double,
)

@JsonClass(generateAdapter = true)
Expand Down Expand Up @@ -62,3 +68,56 @@ data class PostMessageResponse(
data class PostChatMessageRequest(
val content: String,
)

// 티켓 발급 응답
@JsonClass(generateAdapter = true)
data class TicketResponse(
@Json(name = "chatTicket")
val chatTicket: String,
)

@JsonClass(generateAdapter = true)
data class SocketChatMessage(
val succeed: Boolean,
val type: SocketType,
val message: String? = null,
val data: Any? = null,
) {
/**
* TALK 타입일 때 안전하게 DTO로 변환하여 가져오는 도우미 함수
*/
fun getChatData(moshi: Moshi): SocketChatMessageDTO? {
if (type != SocketType.TALK || data == null) return null
return try {
val adapter = moshi.adapter(SocketChatMessageDTO::class.java)
adapter.fromJsonValue(data)
} catch (e: Exception) {
null
}
}

/**
* ERROR 타입일 때 data 필드에 담긴 에러 상세 내용을 가져오는 도우미 함수
*/
fun getErrorDetail(): String? {
return data as? String
}
}

@JsonClass(generateAdapter = true)
data class SocketChatMessageDTO(
val chatId: Long,
val senderId: String?,
val senderNickname: String?,
val senderProfileUrl: String?,
val senderThumbnailUrl: String?,
val chatContent: String,
val chatType: String,
val sentAt: LocalDateTime,
)

@JsonClass(generateAdapter = true)
data class SocketChatRequest(
val type: SocketType,
val content: String?,
)
3 changes: 3 additions & 0 deletions data/src/main/java/com/project200/data/dto/MatchingDTO.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ data class GetMatchingMembersDto(
val nickname: String,
val gender: String,
val birthDate: String,
val memberScore: Int,
val locations: List<LocationDto>,
val preferredExercises: List<GetProfilePreferredExerciseDTO>,
)

@JsonClass(generateAdapter = true)
data class LocationDto(
val exerciseLocationId: Long,
val exerciseLocationName: String,
val latitude: Double,
val longitude: Double,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class AuthRepositoryImpl
withContext(ioDispatcher) {
try {
val response = apiService.getIsRegistered()
response.data?.let { spManager.saveMemberId(it.memberId) }
response.data?.isRegistered ?: false
} catch (e: CancellationException) {
throw e
Expand Down Expand Up @@ -81,6 +82,10 @@ class AuthRepositoryImpl
)
}

override suspend fun getMemberId(): String {
return spManager.getMemberId().toString()
}

companion object {
const val TAG = "AuthRepositoryImpl"
}
Expand Down
Loading