Skip to content

Commit b13fc70

Browse files
committed
Merge branch 'release/v2.1.2'
2 parents fc6fb45 + 5f2aaaa commit b13fc70

File tree

11 files changed

+350
-299
lines changed

11 files changed

+350
-299
lines changed

app/build.gradle

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ plugins {
1515

1616
// Add the Google services Gradle plugin
1717
id 'com.google.gms.google-services'
18+
19+
// Add the Firebase Crashlytics Gradle plugin
20+
id 'com.google.firebase.crashlytics'
1821
}
1922

2023
Properties properties = new Properties()
@@ -28,8 +31,8 @@ android {
2831
applicationId "com.runnect.runnect"
2932
minSdk 28
3033
targetSdk 35
31-
versionCode 25
32-
versionName "2.1.1"
34+
versionCode 26
35+
versionName "2.1.2"
3336

3437
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
3538
buildConfigField "String", "RUNNECT_DEV_URL", properties["RUNNECT_DEV_URL"]
@@ -199,6 +202,9 @@ dependencies {
199202

200203
//firebase remote config - update dialog
201204
implementation 'com.google.firebase:firebase-config-ktx'
205+
206+
// Firebase Crashlytics
207+
implementation 'com.google.firebase:firebase-crashlytics-ktx'
202208

203209
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.2'
204210
implementation 'androidx.activity:activity-compose:1.9.0'
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.runnect.runnect.binding
2+
3+
import android.content.Intent
4+
import android.os.Bundle
5+
import android.view.View
6+
import android.widget.Button
7+
import androidx.annotation.LayoutRes
8+
import androidx.core.view.isVisible
9+
import androidx.databinding.ViewDataBinding
10+
import com.runnect.runnect.R
11+
import com.runnect.runnect.presentation.MainActivity
12+
import com.runnect.runnect.presentation.login.LoginActivity
13+
14+
abstract class BaseVisitorFragment<T : ViewDataBinding>(
15+
@LayoutRes private val layoutRes: Int
16+
) : BindingFragment<T>(layoutRes) {
17+
18+
abstract val visitorContainer: View
19+
abstract val contentViews: List<View>
20+
21+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
22+
super.onViewCreated(view, savedInstanceState)
23+
24+
if (MainActivity.isVisitorMode) {
25+
showVisitorMode()
26+
} else {
27+
showContent()
28+
onContentModeInit()
29+
}
30+
}
31+
32+
private fun showVisitorMode() {
33+
visitorContainer.isVisible = true
34+
visitorContainer.findViewById<Button>(R.id.btn_visitor_mode)?.setOnClickListener {
35+
navigateToLogin()
36+
}
37+
contentViews.forEach { it.isVisible = false }
38+
}
39+
40+
private fun showContent() {
41+
visitorContainer.isVisible = false
42+
contentViews.forEach { it.isVisible = true }
43+
}
44+
45+
private fun navigateToLogin() {
46+
val intent = Intent(requireContext(), LoginActivity::class.java)
47+
startActivity(intent)
48+
requireActivity().finish()
49+
}
50+
51+
abstract fun onContentModeInit()
52+
}

app/src/main/java/com/runnect/runnect/presentation/MainActivity.kt

Lines changed: 65 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,35 +2,31 @@ package com.runnect.runnect.presentation
22

33
import android.app.AlertDialog
44
import android.content.Intent
5-
import android.net.Uri
65
import android.os.Bundle
76
import android.view.View
8-
import androidx.fragment.app.commit
7+
import androidx.core.net.toUri
98
import com.google.firebase.ktx.Firebase
109
import com.google.firebase.remoteconfig.ktx.remoteConfig
1110
import com.google.firebase.remoteconfig.ktx.remoteConfigSettings
1211
import com.runnect.runnect.BuildConfig.REMOTE_KEY_APP_VERSION
1312
import com.runnect.runnect.R
1413
import com.runnect.runnect.binding.BindingActivity
1514
import com.runnect.runnect.databinding.ActivityMainBinding
16-
import com.runnect.runnect.presentation.coursemain.CourseMainFragment
1715
import com.runnect.runnect.presentation.discover.DiscoverFragment
18-
import com.runnect.runnect.presentation.mypage.MyPageFragment
19-
import com.runnect.runnect.presentation.storage.StorageMainFragment
2016
import com.runnect.runnect.presentation.storage.StorageScrapFragment
2117
import com.runnect.runnect.util.analytics.Analytics
2218
import com.runnect.runnect.util.analytics.EventName
2319
import com.runnect.runnect.util.analytics.EventName.EVENT_VIEW_HOME
2420
import com.runnect.runnect.util.preference.AuthUtil.getAccessToken
2521
import com.runnect.runnect.util.preference.StatusType.LoginStatus
2622
import dagger.hilt.android.AndroidEntryPoint
27-
import timber.log.Timber
2823

2924
@AndroidEntryPoint
3025
class MainActivity : BindingActivity<ActivityMainBinding>(R.layout.activity_main) {
3126
private var isChangeToStorage: Boolean = false
3227
private var isChangeToDiscover: Boolean = false
3328
private var fragmentReplacementDirection: String? = null
29+
private lateinit var viewPagerAdapter: MainPager
3430

3531
override fun onCreate(savedInstanceState: Bundle?) {
3632
super.onCreate(savedInstanceState)
@@ -53,38 +49,58 @@ class MainActivity : BindingActivity<ActivityMainBinding>(R.layout.activity_main
5349
fragmentReplacementDirection = intent.getStringExtra(EXTRA_FRAGMENT_REPLACEMENT_DIRECTION)
5450

5551
when (fragmentReplacementDirection) {
56-
"fromDrawCourse", "fromDeleteMyDrawDetail", "fromMyDrawDetail" -> isChangeToStorage =
57-
true
58-
52+
"fromDrawCourse", "fromDeleteMyDrawDetail", "fromMyDrawDetail" -> isChangeToStorage = true
5953
"fromMyScrap", "fromCourseDetail" -> isChangeToDiscover = true
6054
}
6155
}
6256

6357
private fun initView() {
64-
val selectedItemId = when {
65-
isChangeToStorage -> R.id.menu_main_storage.also { isChangeToStorage = false }
66-
isChangeToDiscover -> R.id.menu_main_discover.also { isChangeToDiscover = false }
67-
else -> R.id.menu_main_drawing
58+
setupViewPager()
59+
val selectedPosition = when {
60+
isChangeToStorage -> 1.also { isChangeToStorage = false }
61+
isChangeToDiscover -> 2.also { isChangeToDiscover = false }
62+
else -> 0
63+
}
64+
binding.vpMain.currentItem = selectedPosition
65+
updateBottomNavigationSelection(selectedPosition)
66+
}
67+
68+
private fun setupViewPager() {
69+
viewPagerAdapter = MainPager(this)
70+
binding.vpMain.apply {
71+
adapter = viewPagerAdapter
72+
isUserInputEnabled = false
73+
offscreenPageLimit = 3
6874
}
69-
binding.btmNaviMain.menu.findItem(selectedItemId).isChecked = true
70-
changeFragment(selectedItemId)
7175
}
7276

7377
private fun changeFragment(menuItemId: Int) {
78+
val position = getPositionFromMenuId(menuItemId)
7479
logClickEvent(menuItemId)
75-
supportFragmentManager.commit {
76-
replace(
77-
R.id.fl_main, when (menuItemId) {
78-
R.id.menu_main_drawing -> CourseMainFragment()
79-
R.id.menu_main_storage -> StorageMainFragment()
80-
R.id.menu_main_discover -> DiscoverFragment()
81-
R.id.menu_main_my_page -> MyPageFragment()
82-
else -> throw IllegalArgumentException("${this@MainActivity::class.java.simpleName} Not found menu item id")
83-
}
84-
)
80+
binding.vpMain.setCurrentItem(position, false)
81+
}
82+
83+
private fun getPositionFromMenuId(menuItemId: Int): Int {
84+
return when (menuItemId) {
85+
R.id.menu_main_drawing -> 0
86+
R.id.menu_main_storage -> 1
87+
R.id.menu_main_discover -> 2
88+
R.id.menu_main_my_page -> 3
89+
else -> 0
8590
}
8691
}
8792

93+
private fun updateBottomNavigationSelection(position: Int) {
94+
val menuItemId = when (position) {
95+
0 -> R.id.menu_main_drawing
96+
1 -> R.id.menu_main_storage
97+
2 -> R.id.menu_main_discover
98+
3 -> R.id.menu_main_my_page
99+
else -> R.id.menu_main_drawing
100+
}
101+
binding.btmNaviMain.menu.findItem(menuItemId).isChecked = true
102+
}
103+
88104
private fun logClickEvent(menuItemId: Int) {
89105
with(EventName) {
90106
when (menuItemId) {
@@ -100,7 +116,6 @@ class MainActivity : BindingActivity<ActivityMainBinding>(R.layout.activity_main
100116
private fun addListener() {
101117
binding.btmNaviMain.setOnItemSelectedListener {
102118
changeFragment(it.itemId)
103-
Timber.tag("hu").d("fromDrawActivity when touch : $isChangeToStorage")
104119
true
105120
}
106121
}
@@ -114,54 +129,45 @@ class MainActivity : BindingActivity<ActivityMainBinding>(R.layout.activity_main
114129
}
115130

116131
private fun initRemoteConfig() {
117-
val remoteConfig = Firebase.remoteConfig
118-
val localAppVersion =
119-
packageManager.getPackageInfo(packageName, 0).versionName //현재 설치된 앱의 버전 (versionName)
120-
val configSettings = remoteConfigSettings {
121-
minimumFetchIntervalInSeconds = 3600 //1시간마다 최신 config를 가져오도록 설정
122-
}
123-
remoteConfig.setConfigSettingsAsync(configSettings)
124-
remoteConfig.setDefaultsAsync( //remote config 기본값 설정
125-
mapOf(
126-
REMOTE_KEY_APP_VERSION to DEFAULT_VERSION
132+
Firebase.remoteConfig.run {
133+
val localAppVersion = packageManager.getPackageInfo(packageName, 0).versionName
134+
val configSettings = remoteConfigSettings {
135+
minimumFetchIntervalInSeconds = REMOTE_CONFIG_FETCH_INTERVAL_SECONDS
136+
}
137+
setConfigSettingsAsync(configSettings)
138+
setDefaultsAsync( //remote config 기본값 설정
139+
mapOf(REMOTE_KEY_APP_VERSION to getString(R.string.default_version))
127140
)
128-
)
129-
130-
remoteConfig.fetchAndActivate().addOnCompleteListener {//remote confing에서 값 수신 및 활성화
131-
if (it.isSuccessful) { // fetch and activate 성공 }
132-
Timber.tag("remote_config").d("fetch and activate: Success")
133-
val updateAppVersion = remoteConfig.getString(REMOTE_KEY_APP_VERSION)
134-
Timber.tag("appVersion").d("local: $localAppVersion, remote: $updateAppVersion")
135-
if (localAppVersion != updateAppVersion) {
136-
initUpdateDialog()
141+
142+
fetchAndActivate().addOnCompleteListener { task ->
143+
if (task.isSuccessful) {
144+
val updateAppVersion = getString(REMOTE_KEY_APP_VERSION)
145+
if (localAppVersion != updateAppVersion) {
146+
initUpdateDialog()
147+
}
137148
}
138-
} else {// fetch and activate 실패
139-
Timber.tag("remote_config").d("fetch and activate: Fail")
140149
}
141150
}
142151
}
143152

144153
private fun initUpdateDialog() {
145-
val builder = AlertDialog.Builder(this)
146-
builder.setTitle(UPDATE_DIALOG_TITLE)
147-
.setMessage(UPDATE_DIALOG_MESSAGE)
148-
.setPositiveButton(UPDATE_DIALOG_BTN_TEXT) { _, _ -> loadPlayStore() }
149-
.setCancelable(false)
150-
builder.show()
154+
AlertDialog.Builder(this).apply {
155+
setTitle(R.string.update_dialog_title)
156+
setMessage(R.string.update_dialog_message)
157+
setPositiveButton(R.string.update_dialog_btn_text) { _, _ -> loadPlayStore() }
158+
setCancelable(false)
159+
show()
160+
}
151161
}
152162

153163
private fun loadPlayStore() {
154164
val uri = "market://details?id=$packageName"
155-
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(uri))
165+
val intent = Intent(Intent.ACTION_VIEW, uri.toUri())
156166
startActivity(intent)
157167
}
158168

159169
companion object {
160-
const val UPDATE_DIALOG_TITLE = "업데이트"
161-
const val UPDATE_DIALOG_MESSAGE = "더 좋아진 Runnect 앱을 사용하시기 위해서는 최신 버전으로 업데이트가 필요합니다."
162-
const val UPDATE_DIALOG_BTN_TEXT = "업데이트"
163-
const val DEFAULT_VERSION = "0.0.0"
164-
170+
const val REMOTE_CONFIG_FETCH_INTERVAL_SECONDS = 3600L
165171
const val EXTRA_FRAGMENT_REPLACEMENT_DIRECTION = "fragmentReplacementDirection"
166172

167173
var isVisitorMode = false
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.runnect.runnect.presentation
2+
3+
import androidx.fragment.app.Fragment
4+
import androidx.fragment.app.FragmentActivity
5+
import androidx.viewpager2.adapter.FragmentStateAdapter
6+
import com.runnect.runnect.presentation.coursemain.CourseMainFragment
7+
import com.runnect.runnect.presentation.discover.DiscoverFragment
8+
import com.runnect.runnect.presentation.mypage.MyPageFragment
9+
import com.runnect.runnect.presentation.storage.StorageMainFragment
10+
11+
class MainPager(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
12+
13+
private val fragments = mutableMapOf<Int, Fragment>()
14+
15+
override fun getItemCount(): Int = 4
16+
17+
override fun createFragment(position: Int): Fragment {
18+
return fragments.getOrPut(position) {
19+
when (position) {
20+
0 -> CourseMainFragment()
21+
1 -> StorageMainFragment()
22+
2 -> DiscoverFragment().apply {
23+
MainActivity.discoverFragment = this
24+
}
25+
26+
3 -> MyPageFragment()
27+
else -> CourseMainFragment()
28+
}
29+
}
30+
}
31+
}

0 commit comments

Comments
 (0)