Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 13 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,25 @@
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.Tiggle"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize">

<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

<intent-filter>
<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data
android:host="dutchpay"
android:scheme="tiggle" />
</intent-filter>
</activity>
</application>

Expand Down
33 changes: 26 additions & 7 deletions app/src/main/java/com/ssafy/tiggle/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,39 +14,58 @@ import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.LocalContext
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import com.google.firebase.messaging.FirebaseMessaging

import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.ssafy.tiggle.presentation.navigation.NavigationGraph
import com.ssafy.tiggle.presentation.ui.theme.TiggleTheme
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.MutableStateFlow

/**
* 메인 액티비티
* Hilt를 사용하여 의존성 주입을 받습니다
*/
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
// 1. 딥링크 Intent를 담을 StateFlow 생성
private val deepLinkIntent = MutableStateFlow<Intent?>(null)


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()

// ✅ 디버그용: 현재 기기의 FCM 토큰 로그로 확인
FirebaseMessaging.getInstance().token.addOnSuccessListener {
Log.d("TiggleFCM", "FCM token = $it")
// 2. 앱 시작 시 초기 Intent가 딥링크를 포함하는지 확인
if (intent?.data != null) {
deepLinkIntent.value = intent
}

setContent {
TiggleTheme {
// ✅ Android 13+ 알림 권한 1회 요청
RequestPostNotificationsPermissionOnce()
// ⬇️ 기존 네비게이션
NavigationGraph()
val intentState by deepLinkIntent.collectAsStateWithLifecycle()
NavigationGraph(
intent = intentState,
// 6. 딥링크 처리가 완료되면 StateFlow를 null로 비워주는 콜백 전달
onDeepLinkHandled = { deepLinkIntent.value = null }
)
}
}
}

// 4. 앱이 백그라운드에 있을 때 새 Intent를 받는 부분
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
// 5. 새로 받은 Intent로 StateFlow를 업데이트 -> Compose에 변경 사항 알림
if (intent.data != null) {
deepLinkIntent.value = intent
}
}
}

/** Android 13+에서 POST_NOTIFICATIONS 권한 1회 요청 */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ class TiggleMessagingService : FirebaseMessagingService() {

val intent = Intent(this, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
// 딥링크 정보를 Intent에 추가
if (deepLink != null) {
// URI 형태로 설정하여 NavigationGraph에서 처리할 수 있도록 함
data = android.net.Uri.parse(deepLink)
}
}
val pending = PendingIntent.getActivity(
this, 0, intent,
Expand Down
63 changes: 63 additions & 0 deletions app/src/main/java/com/ssafy/tiggle/core/utils/Formatter.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,73 @@
package com.ssafy.tiggle.core.utils

import android.annotation.SuppressLint
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeParseException
import java.util.Locale

object Formatter {
// 정수 금액 포맷팅: 50,000원
fun formatCurrency(amount: Long, locale: Locale = Locale.KOREA): String =
String.format(locale, "%,d원", amount)

// ISO 8601 날짜/시간 포맷팅: "2025-08-26T01:25:21" -> "2025.08.26 01:25"
@SuppressLint("NewApi")
fun formatDateTime(isoDateTime: String): String {
return try {
val dateTime = LocalDateTime.parse(isoDateTime)
val formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm")
dateTime.format(formatter)
} catch (e: DateTimeParseException) {
// 파싱 실패 시 원본 문자열 반환
isoDateTime
}
}

// 간단한 날짜 포맷팅: "2025-08-26T01:25:21" -> "8월 26일"
@SuppressLint("NewApi")
fun formatDateOnly(isoDateTime: String): String {
return try {
val dateTime = LocalDateTime.parse(isoDateTime)
val formatter = DateTimeFormatter.ofPattern("M월 d일", Locale.KOREA)
dateTime.format(formatter)
} catch (e: DateTimeParseException) {
// 파싱 실패 시 원본 문자열 반환
isoDateTime
}
}

// 시간만 포맷팅: "2025-08-26T01:25:21" -> "오전 1:25"
@SuppressLint("NewApi")
fun formatTimeOnly(isoDateTime: String): String {
return try {
val dateTime = LocalDateTime.parse(isoDateTime)
val formatter = DateTimeFormatter.ofPattern("a h:mm", Locale.KOREA)
dateTime.format(formatter)
} catch (e: DateTimeParseException) {
// 파싱 실패 시 원본 문자열 반환
isoDateTime
}
}

// 상대적 시간 표시: "방금", "5분 전", "3시간 전", "2일 전" 등
@SuppressLint("NewApi")
fun formatRelativeTime(isoDateTime: String): String {
return try {
val dateTime = LocalDateTime.parse(isoDateTime)
val now = LocalDateTime.now()
val duration = java.time.Duration.between(dateTime, now)

when {
duration.toMinutes() < 1 -> "방금"
duration.toMinutes() < 60 -> "${duration.toMinutes()}분 전"
duration.toHours() < 24 -> "${duration.toHours()}시간 전"
duration.toDays() < 7 -> "${duration.toDays()}일 전"
else -> formatDateOnly(isoDateTime)
}
} catch (e: DateTimeParseException) {
// 파싱 실패 시 원본 문자열 반환
isoDateTime
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.ssafy.tiggle.data.datasource.remote

import com.ssafy.tiggle.data.model.BaseResponse
import com.ssafy.tiggle.data.model.LoginRequestDto
import com.ssafy.tiggle.data.model.SignUpRequestDto
import com.ssafy.tiggle.data.model.auth.request.LoginRequestDto
import com.ssafy.tiggle.data.model.auth.request.SignUpRequestDto
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,21 @@ package com.ssafy.tiggle.data.datasource.remote
import com.ssafy.tiggle.data.model.BaseResponse
import com.ssafy.tiggle.data.model.EmptyResponse
import com.ssafy.tiggle.data.model.dutchpay.request.DutchPayRequestDto
import com.ssafy.tiggle.data.model.dutchpay.response.DutchPayRequestDetailResponseDto
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path

interface DutchPayApiService {
@POST("/api/dutchpay/requests")
suspend fun createDutchPayRequest(
@Body request: DutchPayRequestDto
): Response<BaseResponse<EmptyResponse>>

@GET("/api/dutchpay/requests/{id}")
suspend fun getDutchPayRequestDetail(
@Path("id") dutchPayId: Long
): Response<BaseResponse<DutchPayRequestDetailResponseDto>>
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.ssafy.tiggle.data.datasource.remote

import com.ssafy.tiggle.data.model.BaseResponse
import com.ssafy.tiggle.data.model.DepartmentDto
import com.ssafy.tiggle.data.model.UniversityDto
import com.ssafy.tiggle.data.model.auth.response.DepartmentDto
import com.ssafy.tiggle.data.model.auth.response.UniversityDto
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Path
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.ssafy.tiggle.data.datasource.remote

import com.ssafy.tiggle.data.model.BaseResponse
import com.ssafy.tiggle.data.model.UserSummaryDto
import com.ssafy.tiggle.data.model.dutchpay.response.UserSummaryDto
import retrofit2.Response
import retrofit2.http.GET

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.ssafy.tiggle.data.model
package com.ssafy.tiggle.data.model.auth.request

data class LoginRequestDto(
val email: String,
val password: String
)
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.ssafy.tiggle.data.model
package com.ssafy.tiggle.data.model.auth.request

/**
* 회원가입 요청 DTO
Expand All @@ -11,4 +11,4 @@ data class SignUpRequestDto(
val studentId: String,
val password: String,
val phone: String
)
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.ssafy.tiggle.data.model
package com.ssafy.tiggle.data.model.auth.response

import com.ssafy.tiggle.domain.entity.auth.Department

Expand All @@ -20,4 +20,4 @@ data class DepartmentDto(
name = name
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.ssafy.tiggle.data.model
package com.ssafy.tiggle.data.model.auth.response

import com.ssafy.tiggle.domain.entity.auth.University

Expand All @@ -20,4 +20,4 @@ data class UniversityDto(
name = name
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.ssafy.tiggle.data.model
package com.ssafy.tiggle.data.model.auth.response

import com.ssafy.tiggle.domain.entity.auth.User

Expand Down Expand Up @@ -32,6 +32,4 @@ data class UserDto(
updatedAt = updatedAt
)
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ data class DutchPayRequestDto(
val title: String,
val message: String,
val payMore: Boolean
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.ssafy.tiggle.data.model.dutchpay.response

data class DutchPayRequestDetailResponseDto(
val dutchpayId: Long,
val title: String,
val message: String,
val requesterName: String,
val participantCount: Int,
val totalAmount: Long,
val requestedAt: String,
val myAmount: Long,
val originalAmount: Long,
val tiggleAmount: Long,
val payMoreDefault: Boolean,
val creator: Boolean
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.ssafy.tiggle.data.model
package com.ssafy.tiggle.data.model.dutchpay.response

import com.ssafy.tiggle.domain.entity.dutchpay.UserSummary

Expand All @@ -13,6 +13,4 @@ data class UserSummaryDto(
id = id,
name = name
)
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import com.google.gson.Gson
import com.ssafy.tiggle.data.datasource.local.AuthDataSource
import com.ssafy.tiggle.data.datasource.remote.AuthApiService
import com.ssafy.tiggle.data.model.BaseResponse
import com.ssafy.tiggle.data.model.LoginRequestDto
import com.ssafy.tiggle.data.model.SignUpRequestDto
import com.ssafy.tiggle.data.model.auth.request.LoginRequestDto
import com.ssafy.tiggle.data.model.auth.request.SignUpRequestDto
import com.ssafy.tiggle.domain.entity.auth.UserSignUp
import com.ssafy.tiggle.domain.repository.AuthRepository
import javax.inject.Inject
Expand Down
Loading