diff --git a/app/build.gradle b/app/build.gradle index 0e8164e9..ccc71abb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ plugins { } android { - compileSdk 34 + compileSdk 35 Properties properties = new Properties() properties.load(project.rootProject.file('local.properties').newDataInputStream()) @@ -14,7 +14,7 @@ android { defaultConfig { applicationId "com.dongyang.android.youdongknowme" minSdk 24 - targetSdk 34 + targetSdk 35 versionCode 17 versionName "2.3.1" @@ -44,49 +44,50 @@ android { } dependencies { - implementation 'androidx.core:core-ktx:1.7.0' - implementation 'androidx.appcompat:appcompat:1.4.1' - implementation 'com.google.android.material:material:1.7.0' - implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.core:core-ktx:1.16.0' + implementation 'androidx.appcompat:appcompat:1.7.1' + implementation 'com.google.android.material:material:1.12.0' + implementation 'androidx.constraintlayout:constraintlayout:2.2.1' implementation 'androidx.legacy:legacy-support-v4:1.0.0' - implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1' + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.9.2' + implementation("androidx.activity:activity-ktx:1.10.1") testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - + androidTestImplementation 'androidx.test.ext:junit:1.3.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0' // preference - implementation 'androidx.preference:preference:1.2.0' + implementation 'androidx.preference:preference-ktx:1.2.1' // Coroutines - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.10.2" // ViewModelScope - implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.9.2" // Retrofit2 - implementation "com.squareup.retrofit2:retrofit:2.9.0" - implementation "com.squareup.retrofit2:converter-gson:2.9.0" + implementation "com.squareup.retrofit2:retrofit:3.0.0" + implementation "com.squareup.retrofit2:converter-gson:3.0.0" // OkHttp - implementation "com.squareup.okhttp3:okhttp:4.10.0" - implementation "com.squareup.okhttp3:logging-interceptor:4.10.0" - implementation "com.squareup.okhttp3:okhttp-urlconnection:4.9.1" + implementation "com.squareup.okhttp3:okhttp:5.1.0" + implementation "com.squareup.okhttp3:logging-interceptor:5.1.0" + implementation "com.squareup.okhttp3:okhttp-urlconnection:5.1.0" // Gson - implementation 'com.google.code.gson:gson:2.9.0' + implementation 'com.google.code.gson:gson:2.13.1' // Room - implementation 'androidx.room:room-common:2.4.3' - implementation 'androidx.room:room-ktx:2.4.3' - kapt "androidx.room:room-compiler:2.4.3" + implementation 'androidx.room:room-common:2.7.2' + implementation 'androidx.room:room-ktx:2.7.2' + //noinspection KaptUsageInsteadOfKsp + kapt "androidx.room:room-compiler:2.7.2" // Koin - implementation "io.insert-koin:koin-core:3.1.2" - implementation "io.insert-koin:koin-android:3.1.2" + implementation "io.insert-koin:koin-core:4.1.0" + implementation "io.insert-koin:koin-android:4.1.0" // Animation - implementation 'com.daimajia.easing:library:2.0@aar' + implementation 'com.daimajia.easing:library:2.4@aar' implementation 'com.daimajia.androidanimations:library:2.4@aar' // MaterialCalendarView @@ -94,13 +95,13 @@ dependencies { implementation 'com.jakewharton.threetenabp:threetenabp:1.2.0' // Glide - implementation 'com.github.bumptech.glide:glide:4.13.2' - annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2' + implementation 'com.github.bumptech.glide:glide:4.16.0' + annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' // Firebase - implementation platform('com.google.firebase:firebase-bom:30.0.0') + implementation platform('com.google.firebase:firebase-bom:34.1.0') implementation 'com.google.firebase:firebase-analytics' - implementation 'com.google.firebase:firebase-messaging:23.4.1' + implementation 'com.google.firebase:firebase-messaging:25.0.0' // Timber implementation 'com.jakewharton.timber:timber:5.0.1' @@ -112,15 +113,11 @@ dependencies { implementation 'com.google.android.flexbox:flexbox:3.0.0' // Lottie - implementation "com.airbnb.android:lottie:5.2.0" - - // Navigation - implementation("androidx.navigation:navigation-fragment-ktx:2.5.3") - implementation("androidx.navigation:navigation-ui-ktx:2.5.3") + implementation "com.airbnb.android:lottie:6.6.7" // MinSdk - coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5' + coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5' // Window Manager - implementation 'androidx.window:window:1.0.0' + implementation 'androidx.window:window:1.4.0' } diff --git a/app/src/main/java/com/dongyang/android/youdongknowme/standard/base/BaseActivity.kt b/app/src/main/java/com/dongyang/android/youdongknowme/standard/base/BaseActivity.kt index 89524e16..8904921e 100644 --- a/app/src/main/java/com/dongyang/android/youdongknowme/standard/base/BaseActivity.kt +++ b/app/src/main/java/com/dongyang/android/youdongknowme/standard/base/BaseActivity.kt @@ -1,12 +1,15 @@ package com.dongyang.android.youdongknowme.standard.base -import android.content.Context import android.os.Bundle import android.text.Spannable import android.text.SpannableStringBuilder import android.text.style.ForegroundColorSpan import android.widget.TextView +import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.updatePadding import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding import com.dongyang.android.youdongknowme.ui.view.LoadingDialog @@ -24,10 +27,21 @@ abstract class BaseActivity : AppCompatA override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + enableEdgeToEdge() binding = DataBindingUtil.setContentView(this, layoutResourceId) binding.lifecycleOwner = this setContentView(binding.root) + ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets -> + val inset = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + v.updatePadding( + top = inset.top, + bottom = inset.bottom, + left = inset.left, + right = inset.right, + ) + insets + } initStartView() initDataBinding() initAfterBinding() @@ -36,7 +50,7 @@ abstract class BaseActivity : AppCompatA protected fun setSpanText( spanTextView: TextView, startIdx: Int, - endIdx: Int + endIdx: Int, ) { SpannableStringBuilder(spanTextView.text).apply { setSpan( @@ -90,4 +104,4 @@ abstract class BaseActivity : AppCompatA abstract fun initAfterBinding() -} \ No newline at end of file +} diff --git a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/cafeteria/CafeteriaContainer.kt b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/cafeteria/CafeteriaContainer.kt index 9f73a5ae..373f834b 100644 --- a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/cafeteria/CafeteriaContainer.kt +++ b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/cafeteria/CafeteriaContainer.kt @@ -65,4 +65,4 @@ class CafeteriaContainer( tvItemCalendarMonth.setTextColor(color) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/cafeteria/CafeteriaFragment.kt b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/cafeteria/CafeteriaFragment.kt index ac125d7a..b4fa982c 100644 --- a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/cafeteria/CafeteriaFragment.kt +++ b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/cafeteria/CafeteriaFragment.kt @@ -18,7 +18,9 @@ import com.kizitonwose.calendarview.model.CalendarDay import com.kizitonwose.calendarview.ui.DayBinder import com.kizitonwose.calendarview.utils.Size import org.koin.androidx.viewmodel.ext.android.viewModel -import java.time.DayOfWeek.* +import java.time.DayOfWeek.MONDAY +import java.time.DayOfWeek.SATURDAY +import java.time.DayOfWeek.SUNDAY import java.time.LocalDate import java.time.YearMonth import java.time.temporal.TemporalAdjusters @@ -64,7 +66,11 @@ class CafeteriaFragment : BaseFragment updateCafeteriaState(selectedCategory) } + viewModel.selectedCategory.value?.let { selectedCategory -> + updateCafeteriaState( + selectedCategory + ) + } } } @@ -126,7 +132,8 @@ class CafeteriaFragment : BaseFragment() override fun initDataBinding() { // 효율을 위해 단 한번만 옵저빙하여 이미 구독중인 항목을 선택 처리 viewModel.localKeywordList.observe(this, object : Observer> { - override fun onChanged(t: List?) { - viewModel.setAllKeywords(t?.filter { it.isSubscribe }?.map { it.name } - ?: listOf("")) + override fun onChanged(value: List) { + viewModel.setAllKeywords(value.filter { it.isSubscribe }.map { it.name }) setCheckChipChange( binding.chipGroupKeywordClass, binding.chipGroupKeywordMoney, diff --git a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/keyword/OnboardingKeywordActivity.kt b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/keyword/OnboardingKeywordActivity.kt index a32c5b6c..fcbc3b6b 100644 --- a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/keyword/OnboardingKeywordActivity.kt +++ b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/keyword/OnboardingKeywordActivity.kt @@ -28,9 +28,8 @@ class OnboardingKeywordActivity : override fun initDataBinding() { // 효율을 위해 단 한번만 옵저빙하여 이미 구독중인 항목을 선택 처리 viewModel.localKeywordList.observe(this, object : Observer> { - override fun onChanged(t: List?) { - viewModel.setAllKeywords(t?.filter { it.isSubscribe }?.map { it.name } - ?: listOf("")) + override fun onChanged(value: List) { + viewModel.setAllKeywords(value.filter { it.isSubscribe }. map{it.name}) setCheckChipChange( binding.chipGroupOnboardingKeywordClass, binding.chipGroupOnboardingKeywordMoney, diff --git a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/main/MainActivity.kt b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/main/MainActivity.kt index 921f493e..6ec920f3 100644 --- a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/main/MainActivity.kt +++ b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/main/MainActivity.kt @@ -2,53 +2,114 @@ package com.dongyang.android.youdongknowme.ui.view.main import android.content.Context import android.content.Intent -import androidx.navigation.fragment.NavHostFragment -import androidx.navigation.plusAssign -import androidx.navigation.ui.setupWithNavController +import android.os.Bundle +import androidx.activity.enableEdgeToEdge +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.ViewCompat +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.updatePadding +import androidx.databinding.DataBindingUtil +import androidx.fragment.app.Fragment +import androidx.fragment.app.commit import com.dongyang.android.youdongknowme.R import com.dongyang.android.youdongknowme.databinding.ActivityMainBinding -import com.dongyang.android.youdongknowme.standard.base.BaseActivity -import com.dongyang.android.youdongknowme.ui.view.util.KeepStateNavigator +import com.dongyang.android.youdongknowme.ui.view.cafeteria.CafeteriaFragment +import com.dongyang.android.youdongknowme.ui.view.notice.NoticeFragment +import com.dongyang.android.youdongknowme.ui.view.schedule.ScheduleFragment +import com.dongyang.android.youdongknowme.ui.view.setting.SettingFragment import com.google.firebase.messaging.FirebaseMessaging import org.koin.androidx.viewmodel.ext.android.viewModel +import timber.log.Timber /* 메인 액티비티 */ -class MainActivity : BaseActivity() { +class MainActivity : AppCompatActivity() { + private lateinit var binding: ActivityMainBinding + val viewModel: MainViewModel by viewModel() - override val layoutResourceId: Int = R.layout.activity_main - override val viewModel: MainViewModel by viewModel() - - override fun initStartView() { - val navHostFragment = - supportFragmentManager.findFragmentById(R.id.main_nav_container) as NavHostFragment - val navController = navHostFragment.navController - - val navigator = - KeepStateNavigator( - this, - navHostFragment.childFragmentManager, - binding.mainNavContainer.id + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + binding = DataBindingUtil.setContentView(this, R.layout.activity_main) + binding.lifecycleOwner = this + setContentView(binding.root) + WindowCompat.setDecorFitsSystemWindows(window, false) + ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets -> + val inset = insets.getInsets(WindowInsetsCompat.Type.systemBars()) + v.updatePadding( + top = inset.top, + bottom = inset.bottom, + left = inset.left, + right = inset.right, ) - navController.navigatorProvider += navigator - navController.setGraph(R.navigation.dmu_navigation) - binding.mainNvBottom.setupWithNavController(navController) + insets + } + + initDataBinding() + initBottomNavigation() + if (savedInstanceState == null) { + binding.mainNvBottom.selectedItemId = + R.id.noticeFragment + } } - override fun initDataBinding() { + private fun initDataBinding() { viewModel.isFirstLaunch.observe(this) { boolean -> if (boolean) getFcmToken() } } - override fun initAfterBinding() = Unit - private fun getFcmToken() { viewModel.setIsFirstLaunch(false) FirebaseMessaging.getInstance().token.addOnCompleteListener { task -> - val token = task.result - if (task.isSuccessful) { + val token = task.result viewModel.setFCMToken(token).run { viewModel.setInitToken() } + } else { + Timber.e("토큰 재발급 실패 : ${task.exception}") + } + } + } + + private fun initBottomNavigation() { + binding.mainNvBottom.setOnItemSelectedListener { item -> + return@setOnItemSelectedListener when (item.itemId) { + R.id.noticeFragment -> { + replaceFragment() + true + } + + R.id.scheduleFragment -> { + replaceFragment() + true + } + + R.id.cafeteriaFragment -> { + replaceFragment() + true + } + + R.id.settingFragment -> { + replaceFragment() + true + } + + else -> false + } + } + } + + private inline fun replaceFragment() { + val tag: String = T::class.java.name + val fragment = + supportFragmentManager.findFragmentByTag(tag) as? T ?: T::class.java.newInstance() + supportFragmentManager.commit { + setReorderingAllowed(true) + supportFragmentManager.fragments.forEach { hide(it) } + if (fragment.isAdded) { + show(fragment) + } else { + add(binding.mainNavContainer.id, fragment, tag) } } } diff --git a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/notice/NoticeFragment.kt b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/notice/NoticeFragment.kt index 59409277..5e3311ba 100644 --- a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/notice/NoticeFragment.kt +++ b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/notice/NoticeFragment.kt @@ -1,7 +1,6 @@ package com.dongyang.android.youdongknowme.ui.view.notice import android.content.Intent -import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.dongyang.android.youdongknowme.R diff --git a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/SettingFragment.kt b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/SettingFragment.kt index 76688d2e..0870b145 100644 --- a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/SettingFragment.kt +++ b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/SettingFragment.kt @@ -123,7 +123,7 @@ class SettingFragment : BaseFragment() } } - private fun getAppVersion(): String { + private fun getAppVersion(): String? { val packageManager = requireContext().packageManager.getPackageInfo(requireContext().packageName, 0) return packageManager.versionName diff --git a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/util/Event.kt b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/util/Event.kt index 3e60c907..c42c7874 100644 --- a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/util/Event.kt +++ b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/util/Event.kt @@ -21,8 +21,8 @@ open class Event(private val content: T) { } class EventObserver(private val onEventUnhandledContent: (T) -> Unit) : Observer> { - override fun onChanged(event: Event?) { - event?.getContentIfNotHandled()?.let { + override fun onChanged(value: Event) { + value.getContentIfNotHandled()?.let { onEventUnhandledContent(it) } } diff --git a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/util/KeepStateNavigator.kt b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/util/KeepStateNavigator.kt deleted file mode 100644 index c9ff8f4f..00000000 --- a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/util/KeepStateNavigator.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.dongyang.android.youdongknowme.ui.view.util - -import android.content.Context -import android.os.Bundle -import androidx.fragment.app.FragmentManager -import androidx.navigation.NavDestination -import androidx.navigation.NavOptions -import androidx.navigation.Navigator -import androidx.navigation.fragment.FragmentNavigator - -@Navigator.Name("keep_state_fragment") -class KeepStateNavigator( - private val context: Context, - private val manager: FragmentManager, - private val containerId: Int -) : FragmentNavigator(context, manager, containerId) { - - override fun createDestination(): Destination = Destination(this) - override fun navigate( - destination: Destination, - args: Bundle?, - navOptions: NavOptions?, - navigatorExtras: Navigator.Extras? - ): NavDestination? { - - val tag = destination.id.toString() - val transaction = manager.beginTransaction() - var initialNavigate = false - val currentFragment = manager.primaryNavigationFragment - - if (currentFragment != null) { - transaction.hide(currentFragment) - } else { - initialNavigate = true - } - - var fragment = manager.findFragmentByTag(tag) - - if (fragment == null) { - val className = destination.className - fragment = manager.fragmentFactory.instantiate(context.classLoader, className) - transaction.add(containerId, fragment, tag) - } else { - transaction.show(fragment) - } - - transaction.setPrimaryNavigationFragment(fragment) - transaction.setReorderingAllowed(true) - transaction.commitNow() - - return if (initialNavigate) destination else null - } -} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index a7bd417b..a2f9d5c5 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -10,10 +10,8 @@ - - + app:menu="@menu/menu_main" /> - - \ No newline at end of file + diff --git a/app/src/main/res/layout/fragment_schedule.xml b/app/src/main/res/layout/fragment_schedule.xml index bbb8ddac..f5ac6313 100644 --- a/app/src/main/res/layout/fragment_schedule.xml +++ b/app/src/main/res/layout/fragment_schedule.xml @@ -27,8 +27,6 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/toolbar_schedule" app:mcv_headerTextAppearance="@style/CalendarHeader" - app:mcv_leftArrowMask="@drawable/ic_arrow_left" - app:mcv_rightArrowMask="@drawable/ic_arrow_right" app:mcv_tileHeight="50dp" app:mcv_tileWidth="0dp" /> diff --git a/app/src/main/res/navigation/dmu_navigation.xml b/app/src/main/res/navigation/dmu_navigation.xml deleted file mode 100644 index fccaaa9f..00000000 --- a/app/src/main/res/navigation/dmu_navigation.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - diff --git a/build.gradle b/build.gradle index ed4394f2..a01cd639 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,11 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '7.4.2' apply false - id 'com.android.library' version '7.4.2' apply false - id 'org.jetbrains.kotlin.android' version '1.6.21' apply false - id "com.google.gms.google-services" version "4.3.14" apply false + id 'com.android.application' version '8.6.1' apply false + id 'com.android.library' version '8.6.1' apply false + id 'org.jetbrains.kotlin.android' version '2.2.0' apply false + id "com.google.gms.google-services" version "4.4.3" apply false } -task clean(type: Delete) { +tasks.register('clean', Delete) { delete rootProject.buildDir -} \ No newline at end of file +} diff --git a/gradle.properties b/gradle.properties index e1c4e18b..ebe2551f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,4 +22,6 @@ kotlin.code.style=official # thereby reducing the size of the R class for that library android.nonTransitiveRClass=true -android.enableJetifier=true \ No newline at end of file +android.enableJetifier=true +android.defaults.buildfeatures.buildconfig=true +android.nonFinalResIds=false \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ae04661e..fdb55581 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Sun Jul 27 10:33:58 KST 2025 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle b/settings.gradle index c8fab12d..beb04529 100644 --- a/settings.gradle +++ b/settings.gradle @@ -10,7 +10,6 @@ dependencyResolutionManagement { repositories { google() mavenCentral() - jcenter() maven { url 'https://jitpack.io'} // calendar } }