Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into feature/#25-mypage-ui
Browse files Browse the repository at this point in the history
# Conflicts:
#	presentation/src/main/res/values/strings.xml
  • Loading branch information
Eonji-sw committed Jan 22, 2025
2 parents 0c76e46 + 83a4679 commit c579be3
Show file tree
Hide file tree
Showing 50 changed files with 1,579 additions and 474 deletions.
8 changes: 7 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

import java.util.Properties

plugins {
Expand Down Expand Up @@ -30,6 +29,9 @@ android {
useSupportLibrary = true
}
buildConfigField("String", "BASE_URL", properties["base.url"].toString())
buildConfigField("String", "KAKAO_API_KEY", properties["KAKAO_API_KEY"].toString())
buildConfigField("String", "GOOGLE_CLIENT_ID", properties["GOOGLE_CLIENT_ID"].toString())
manifestPlaceholders["KAKAO_NATIVE_APP_KEY"] = properties["KAKAO_NATIVE_APP_KEY"].toString()
}

buildTypes {
Expand Down Expand Up @@ -130,4 +132,8 @@ dependencies {
// Kakao
implementation(libs.kakao.all)
implementation(libs.kakao.user)

// Google
implementation(libs.play.services.auth)
implementation(libs.google.id)
}
22 changes: 19 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

<application
android:name="com.sopt.noostak.MyApp"
Expand All @@ -29,6 +30,21 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity
android:name="com.kakao.sdk.auth.AuthCodeHandlerActivity"
android:exported="true">
<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="oauth"
android:scheme="${KAKAO_NATIVE_APP_KEY}" />
</intent-filter>
</activity>
</application>

</manifest>
6 changes: 6 additions & 0 deletions app/src/main/java/com/sopt/noostak/MyApp.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.sopt.noostak

import android.app.Application
import com.kakao.sdk.common.KakaoSdk
import dagger.hilt.android.HiltAndroidApp
import timber.log.Timber

Expand All @@ -9,9 +10,14 @@ class MyApp : Application() {
override fun onCreate() {
super.onCreate()
setTimber()
initKakao()
}

private fun setTimber() {
Timber.plant(Timber.DebugTree())
}

private fun initKakao() {
KakaoSdk.init(this, BuildConfig.KAKAO_API_KEY)
}
}
20 changes: 20 additions & 0 deletions app/src/main/java/com/sopt/noostak/di/GoogleIdModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.sopt.noostak.di

import com.sopt.noostak.BuildConfig
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Named
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object GoogleIdModule {
@Provides
@Singleton
@Named("GoogleClientId")
fun provideGoogleClientId(): String {
return BuildConfig.GOOGLE_CLIENT_ID
}
}
25 changes: 25 additions & 0 deletions app/src/main/java/com/sopt/noostak/di/PreferencesDataStore.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.sopt.noostak.di

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStore
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object PreferencesDataStore {
private val Context.dataStore by preferencesDataStore(name = "noostak_data_store")

@Singleton
@Provides
fun provideDataStore(
@ApplicationContext context: Context
): DataStore<Preferences> =
context.dataStore
}
27 changes: 27 additions & 0 deletions app/src/main/java/com/sopt/noostak/di/UserInfoModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.sopt.noostak.di

import com.sopt.data.datasource.UserDataSource
import com.sopt.data.datasourceimpl.UserDataSourceImpl
import com.sopt.data.repositoryimpl.UserInfoRepositoryImpl
import com.sopt.domain.repository.UserInfoRepository
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
abstract class UserInfoModule {
@Binds
@Singleton
abstract fun bindsAuthDataSource(
authDataSourceImpl: UserDataSourceImpl
): UserDataSource

@Binds
@Singleton
abstract fun bindAuthRepository(
authDataSourceImpl: UserInfoRepositoryImpl
): UserInfoRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.sopt.core.designsystem.component.box

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.sopt.core.designsystem.theme.NoostakTheme
import com.sopt.core.type.CategoryType

@Composable
fun CategoryBox(
text: String
) {
val context = LocalContext.current
val categoryType = CategoryType.fromText(context, text)
val backgroundColor = when (categoryType) {
CategoryType.IMPORTANT -> NoostakTheme.colors.orange
CategoryType.SCHEDULE -> NoostakTheme.colors.blue
CategoryType.HOBBY -> NoostakTheme.colors.purple
CategoryType.ETC -> NoostakTheme.colors.mint
}

Box(
modifier = Modifier
.padding(
top = 5.dp,
start = 4.dp,
bottom = 5.dp,
end = 3.dp
)
.background(
color = backgroundColor,
shape = CircleShape
)
.size(13.dp)
)
}
3 changes: 3 additions & 0 deletions core/src/main/java/com/sopt/core/type/SocialType.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package com.sopt.core.type

enum class SocialType { KAKAO, GOOGLE }
45 changes: 45 additions & 0 deletions core/src/main/java/com/sopt/core/util/CalculateTime.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.sopt.core.util

import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.time.format.TextStyle
import java.util.Locale

class CalculateTime {
fun extractFullDateWithSlash(dateTime: String): String {
return parseDateTime(dateTime).toLocalDate().format(DateTimeFormatter.ofPattern("MM/dd"))
}

fun extractDateWithSlash(dateTime: String): String {
return parseDateTime(dateTime).toLocalDate().format(DateTimeFormatter.ofPattern("M/d"))
}

fun extractFullDateWithKorean(dateTime: String): String {
return parseDateTime(dateTime).toLocalDate().format(DateTimeFormatter.ofPattern("MM월 dd일"))
}

fun extractDateWithKorean(dateTime: String): String {
return parseDateTime(dateTime).toLocalDate().format(DateTimeFormatter.ofPattern("M월 d일"))
}

fun extractDayOfWeek(dateTime: String): String {
return parseDateTime(dateTime).dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.KOREAN)
}

fun extractDayOfWeekWithBraces(dateTime: String): String {
return "(${parseDateTime(dateTime).dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.KOREAN)})"
}

fun extractHourWithKorean(dateTime: String): String {
return "${parseDateTime(dateTime).hour}"
}

fun extractHourWithZero(dateTime: String): String {
return "${parseDateTime(dateTime).hour}:00"
}

private fun parseDateTime(dateTime: String): LocalDateTime {
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")
return LocalDateTime.parse(dateTime, formatter)
}
}
17 changes: 17 additions & 0 deletions core/src/main/java/com/sopt/core/util/RearrangeList.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.sopt.core.util

import com.sopt.domain.entity.IdentityEntity

class RearrangeList {
fun rearrangeMembersBasedOnAvailability(
identity: IdentityEntity,
data: List<String>
): List<String> {
val membersList = data.toMutableList()
if (identity.position in membersList.indices && membersList[identity.position] == identity.name) {
val myInfo = membersList.removeAt(identity.position)
membersList.add(0, myInfo)
}
return membersList
}
}
18 changes: 6 additions & 12 deletions core/src/main/java/com/sopt/core/util/timetable/TimeTable.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@ import androidx.compose.ui.graphics.Color
import com.sopt.core.designsystem.theme.NoostakTheme
import com.sopt.core.type.AvailabilityLevel
import com.sopt.core.type.CellType
import com.sopt.core.util.CalculateTime
import com.sopt.domain.entity.AvailableTimeEntity
import com.sopt.domain.entity.PeriodEntity
import com.sopt.domain.entity.TimeEntity
import com.sopt.domain.entity.TimeTableEntity
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.time.format.TextStyle
import java.util.Locale

class TimeTable {
fun calculateTimeSlots(startTime: String, endTime: String): Int {
Expand Down Expand Up @@ -118,7 +115,8 @@ class TimeTable {
selectedCellsByDate.forEach { (dateColumnIndex, cells) ->
val date = availablePeriods.dates.getOrNull(dateColumnIndex - 1) ?: return@forEach
val times = cells.map { (rowIndex, _) ->
val startHour = extractHour(extractTime(availablePeriods.startTime)) + (rowIndex - 1)
val startHour =
extractHour(extractTime(availablePeriods.startTime)) + (rowIndex - 1)
val endHour = startHour + 1
TimeEntity(
memberStartTime = "${extractDate(date)}T${String.format("%02d", startHour)}:00:00",
Expand All @@ -134,13 +132,9 @@ class TimeTable {
}

private fun formatDateTimeToCustomFormat(dateTime: String): String {
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")
val parsedDate = LocalDateTime.parse(dateTime, formatter)
val dayOfWeek = parsedDate.dayOfWeek.getDisplayName(TextStyle.SHORT, Locale.KOREAN)
val month = "%02d".format(parsedDate.monthValue)
val day = "%02d".format(parsedDate.dayOfMonth)

return "$dayOfWeek\n$month/$day"
val dayOfWeek = CalculateTime().extractDayOfWeek(dateTime)
val date = CalculateTime().extractDateWithSlash(dateTime)
return "$dayOfWeek\n$date"
}

private fun extractTime(dateTime: String): String = dateTime.substringAfter('T')
Expand Down
4 changes: 4 additions & 0 deletions data/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,8 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.espresso.core)

// DataStore
implementation(libs.androidx.datastore.core)
implementation(libs.androidx.datastore.preferences)
}
28 changes: 28 additions & 0 deletions data/src/main/java/com/sopt/data/datasource/UserDataSource.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.sopt.data.datasource

import kotlinx.coroutines.flow.Flow

interface UserDataSource {
val accessToken: Flow<String>
val refreshToken: Flow<String>
val userId: Flow<Int>
val isAutoLogin: Flow<Boolean>
val nickName: Flow<String>
val profileImage: Flow<String>

suspend fun updateAccessToken(accessToken: String)

suspend fun updateRefreshToken(refreshToken: String)

suspend fun updateUserId(userId: Int)

suspend fun updateIsAutoLogin(isAutoLogin: Boolean)

suspend fun updateNickName(nickName: String)

suspend fun updateProfileImage(profileImage: String)

suspend fun clear()

suspend fun clearForRefreshToken()
}
Loading

0 comments on commit c579be3

Please sign in to comment.