Skip to content

Commit

Permalink
Merge branch 'develop' into feat/add_popup
Browse files Browse the repository at this point in the history
  • Loading branch information
jihyun0v0 authored Sep 8, 2024
2 parents 27dd885 + 9d4a5d0 commit 0573627
Show file tree
Hide file tree
Showing 27 changed files with 552 additions and 321 deletions.
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

<uses-permission
android:name="android.permission.PACKAGE_USAGE_STATS"
Expand Down
19 changes: 15 additions & 4 deletions app/src/main/java/com/hmh/hamyeonham/HMHApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.hmh.hamyeonham
import android.app.Application
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.Configuration
import com.amplitude.api.Amplitude
import com.hmh.hamyeonham.core.notification.AppNotificationManager
import com.kakao.sdk.common.KakaoSdk
import dagger.hilt.EntryPoint
Expand All @@ -14,24 +15,34 @@ import javax.inject.Inject

@HiltAndroidApp
class HMHApplication : Application(), Configuration.Provider {

@EntryPoint
@InstallIn(SingletonComponent::class)
interface HiltWorkerFactoryEntryPoint {
fun workerFactory(): HiltWorkerFactory
}

@Inject
lateinit var notificationManager: AppNotificationManager

override val workManagerConfiguration: Configuration = Configuration.Builder()
.setWorkerFactory(
EntryPoints.get(this, HiltWorkerFactoryEntryPoint::class.java).workerFactory()
)
.build()
EntryPoints.get(this, HiltWorkerFactoryEntryPoint::class.java).workerFactory(),
).build()

override fun onCreate() {
super.onCreate()

setAmplitude()

KakaoSdk.init(this, BuildConfig.KAKAO_API_KEY)
notificationManager.setupNotificationChannel()
}

private fun setAmplitude() {
Amplitude
.getInstance()
.initialize(this, BuildConfig.AMPLITUDE_API_KEY)
.enableForegroundTracking(this)
.enableLogging(true)
}
}
1 change: 0 additions & 1 deletion app/src/main/java/com/hmh/hamyeonham/SampleActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import com.hmh.hamyeonham.common.view.viewBinding
import com.hmh.hamyeonham.databinding.ActivitySampleBinding
import com.hmh.hamyeonham.feature.login.LoginActivity
import com.hmh.hamyeonham.feature.onboarding.OnBoardingActivity
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ internal fun Project.configureAndroidCommonPlugin() {
val kakaoApiKey = properties["kakaoApiKey"] as? String ?: ""
manifestPlaceholders["kakaoApiKey"] = properties["kakaoApiKey"] as String
buildConfigField("String", "KAKAO_API_KEY", "\"${kakaoApiKey}\"")

val amplitudeApiKey = properties["amplitudeApiKey"] as? String ?: ""
buildConfigField("String", "AMPLITUDE_API_KEY", "\"${amplitudeApiKey}\"")
}
buildTypes {
getByName("debug") {
Expand All @@ -48,5 +51,6 @@ internal fun Project.configureAndroidCommonPlugin() {
"implementation"(libs.findLibrary("material").get())
"implementation"(libs.findLibrary("fragment.ktx").get())
"implementation"(libs.findLibrary("timber").get())
"implementation"(libs.findLibrary("amplitude").get())
}
}
2 changes: 1 addition & 1 deletion build-logic/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Fri Jan 13 12:46:38 KST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.hmh.hamyeonham.common.amplitude

import com.amplitude.api.Amplitude
import org.json.JSONObject

object AmplitudeUtils {
private val amplitude by lazy { Amplitude.getInstance() }

fun trackEventWithProperties(eventName: String, properties: JSONObject? = null) {
if (properties == null) {
amplitude.logEvent(eventName)
} else {
amplitude.logEvent(eventName, properties)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.hmh.hamyeonham.challenge.goals.ChallengeUsageGoalsAdapter
import com.hmh.hamyeonham.challenge.model.Apps
import com.hmh.hamyeonham.challenge.model.NewChallenge
import com.hmh.hamyeonham.challenge.newchallenge.NewChallengeActivity
import com.hmh.hamyeonham.common.amplitude.AmplitudeUtils
import com.hmh.hamyeonham.common.context.getAppNameFromPackageName
import com.hmh.hamyeonham.common.dialog.TwoButtonCommonDialog
import com.hmh.hamyeonham.common.fragment.snackBarWithAction
Expand Down Expand Up @@ -78,7 +79,10 @@ class ChallengeFragment : Fragment() {
return FragmentChallengeBinding.inflate(inflater, container, false).root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
override fun onViewCreated(
view: View,
savedInstanceState: Bundle?,
) {
super.onViewCreated(view, savedInstanceState)
initAppSelectionResultLauncher()
initNewChallengeResultLauncher()
Expand Down Expand Up @@ -147,6 +151,7 @@ class ChallengeFragment : Fragment() {
binding.tvModifierButton.setOnClickListener {
when (viewModel.challengeState.value.modifierState) {
ModifierState.DONE -> {
AmplitudeUtils.trackEventWithProperties("click_edit_button")
viewModel.updateModifierState(ModifierState.EDIT)
}

Expand All @@ -169,13 +174,14 @@ class ChallengeFragment : Fragment() {

private fun initChallengeCreateButton() {
binding.btnChallengeCreate.setOnClickListener {
AmplitudeUtils.trackEventWithProperties("click_newchallenge_button")
if (activityViewModel.isPointLeftToCollect) {
snackBarWithAction(
anchorView = binding.root,
message = getString(com.hmh.hamyeonham.feature.challenge.R.string.challenge_cannot_create),
actionMessage = getString(
com.hmh.hamyeonham.feature.challenge.R.string.all_move
)
com.hmh.hamyeonham.feature.challenge.R.string.all_move,
),
) {
navigateToPointView()
}
Expand Down Expand Up @@ -226,13 +232,12 @@ class ChallengeFragment : Fragment() {
tvChallengeStartDate.text = getString(
com.hmh.hamyeonham.feature.challenge.R.string.challenge_start_date,
startDate.monthNumber,
startDate.dayOfMonth
startDate.dayOfMonth,
)
tvChallengeDay.text = getString(
com.hmh.hamyeonham.feature.challenge.R.string.challenge_day,
todayIndexAsDate,
)
tvChallengeDay.text =
getString(
com.hmh.hamyeonham.feature.challenge.R.string.challenge_day,
todayIndexAsDate
)
}
}

Expand Down Expand Up @@ -262,8 +267,8 @@ class ChallengeFragment : Fragment() {
activityViewModel.generateNewChallenge(
NewChallenge(
period = period ?: 0,
goalTime = goalTime ?: 0
)
goalTime = goalTime ?: 0,
),
)
}
}
Expand Down Expand Up @@ -310,14 +315,18 @@ class ChallengeFragment : Fragment() {
binding.rvAppUsageGoals.run {
adapter = ChallengeUsageGoalsAdapter(
onAppListAddClicked = {
AmplitudeUtils.trackEventWithProperties("click_add_button")
val intent = Intent(requireContext(), AppAddActivity::class.java)
appSelectionResultLauncher.launch(intent)
},
onAppItemClicked = { challengeGoal ->
when (viewModel.challengeState.value.modifierState) {
ModifierState.EDIT -> {
if (challengeGoal.isDeletable) setDeleteAppDialog(challengeGoal.usageStatusAndGoal)
else toast(getString(com.hmh.hamyeonham.feature.challenge.R.string.challenge_cannot_delete))
if (challengeGoal.isDeletable) {
setDeleteAppDialog(challengeGoal.usageStatusAndGoal)
} else {
toast(getString(com.hmh.hamyeonham.feature.challenge.R.string.challenge_cannot_delete))
}
}

else -> Unit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope
import com.hmh.hamyeonham.challenge.model.Apps
import com.hmh.hamyeonham.challenge.usecase.AddUsageGoalsUseCase
import com.hmh.hamyeonham.challenge.usecase.DeleteUsageGoalUseCase
import com.hmh.hamyeonham.common.amplitude.AmplitudeUtils
import com.hmh.hamyeonham.core.domain.usagegoal.model.UsageGoal
import com.hmh.hamyeonham.core.viewmodel.CalendarToggleState
import com.hmh.hamyeonham.usagestats.model.UsageStatusAndGoal
Expand Down Expand Up @@ -40,17 +41,17 @@ data class ChallengeUsageGoal(
}

enum class ModifierState {
EDIT, DONE,
EDIT,
DONE,
}

@HiltViewModel
class ChallengeViewModel @Inject constructor(
private val addUsageGoalsUseCase: AddUsageGoalsUseCase,
private val deleteUsageGoalUseCase: DeleteUsageGoalUseCase,
private val deletedAppUsageStoreUseCase: DeletedAppUsageStoreUseCase,
private val checkAndDeleteDeletedAppUsageUseCase: CheckAndDeleteDeletedAppUsageUseCase
private val checkAndDeleteDeletedAppUsageUseCase: CheckAndDeleteDeletedAppUsageUseCase,
) : ViewModel() {

private val _challengeState = MutableStateFlow(ChallengeState())
val challengeState = _challengeState.asStateFlow()

Expand All @@ -70,17 +71,25 @@ class ChallengeViewModel @Inject constructor(

fun addApp(apps: Apps) {
viewModelScope.launch {
addUsageGoalsUseCase(apps)
runCatching {
addUsageGoalsUseCase(apps)
}.onSuccess {
AmplitudeUtils.trackEventWithProperties("complete_add_new")
}
checkAndDeleteDeletedAppUsageUseCase(apps.apps.map { it.appCode })
}
}

fun deleteApp(usageStatusAndGoal: UsageStatusAndGoal.App) {
viewModelScope.launch {
deleteUsageGoalUseCase(usageStatusAndGoal.packageName)
runCatching {
deleteUsageGoalUseCase(usageStatusAndGoal.packageName)
}.onSuccess {
AmplitudeUtils.trackEventWithProperties("click_delete_complete")
}
deletedAppUsageStoreUseCase(
usageStatusAndGoal.usageTime,
usageStatusAndGoal.packageName
usageStatusAndGoal.packageName,
)
}
}
Expand All @@ -96,5 +105,4 @@ class ChallengeViewModel @Inject constructor(
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.hmh.hamyeonham.common.amplitude.AmplitudeUtils
import com.hmh.hamyeonham.common.view.viewBinding
import com.hmh.hamyeonham.feature.challenge.databinding.ActivityAppAddBinding
import dagger.hilt.android.AndroidEntryPoint
Expand All @@ -15,7 +16,6 @@ import kotlinx.coroutines.flow.onEach

@AndroidEntryPoint
class AppAddActivity : AppCompatActivity() {

companion object {
const val SELECTED_APPS = "selected_apps"
const val GOAL_TIME = "goal_time"
Expand All @@ -24,6 +24,11 @@ class AppAddActivity : AppCompatActivity() {
private val binding by viewBinding(ActivityAppAddBinding::inflate)
private val viewModel by viewModels<AppAddViewModel>()

override fun onResume() {
super.onResume()
AmplitudeUtils.trackEventWithProperties("view_add_totaltime")
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
Expand All @@ -40,16 +45,14 @@ class AppAddActivity : AppCompatActivity() {
btAppSelection.setOnClickListener { handleNextClicked() }
ivBack.setOnClickListener { finish() }
}

}

private fun collectState() {
viewModel.isNextButtonActive.flowWithLifecycle(lifecycle)
.onEach { binding.btAppSelection.isEnabled = it }
.launchIn(lifecycleScope)
viewModel.isNextButtonActive.flowWithLifecycle(lifecycle).onEach {
binding.btAppSelection.isEnabled = it
}.launchIn(lifecycleScope)
}


private fun collectEffect() {
viewModel.effect.flowWithLifecycle(lifecycle).onEach {
when (it) {
Expand All @@ -67,7 +70,6 @@ class AppAddActivity : AppCompatActivity() {
}.launchIn(lifecycleScope)
}


private fun handleNextClicked() {
binding.vpAppAdd.run {
when (currentItem) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.hmh.hamyeonham.common.dialog.OneButtonCommonDialog
import com.hmh.hamyeonham.common.amplitude.AmplitudeUtils
import com.hmh.hamyeonham.common.view.viewBinding
import com.hmh.hamyeonham.feature.challenge.R
import com.hmh.hamyeonham.feature.challenge.databinding.ActivityNewChallengeBinding
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.json.JSONObject

class NewChallengeActivity : AppCompatActivity() {

private val binding by viewBinding(ActivityNewChallengeBinding::inflate)
private val viewModel by viewModels<NewChallengeViewModel>()

Expand All @@ -35,7 +36,16 @@ class NewChallengeActivity : AppCompatActivity() {
vpNewChallenge.adapter = NewChallengeViewPagerAdapter(this@NewChallengeActivity)
vpNewChallenge.isUserInputEnabled = false

btNewChallenge.setOnClickListener { handleNextClicked() }
btNewChallenge.setOnClickListener {
handleNextClicked()
if (vpNewChallenge.adapter?.itemCount == FRAGMENT.PERIODSELECTION.position) {
val properties = JSONObject().put("period", viewModel.state.value.goalDate)
AmplitudeUtils.trackEventWithProperties(
"click_newchallenge_totaltime",
properties
)
}
}
ivBack.setOnClickListener { finish() }
}
}
Expand All @@ -50,9 +60,9 @@ class NewChallengeActivity : AppCompatActivity() {
}

private fun collectNewChallengeState() {
viewModel.state.flowWithLifecycle(lifecycle)
.onEach { binding.btNewChallenge.isEnabled = it.isNextButtonActive }
.launchIn(lifecycleScope)
viewModel.state.flowWithLifecycle(lifecycle).onEach {
binding.btNewChallenge.isEnabled = it.isNextButtonActive
}.launchIn(lifecycleScope)
}

private fun showChallengeCreatedDialog() {
Expand All @@ -77,4 +87,4 @@ class NewChallengeActivity : AppCompatActivity() {
setResult(RESULT_OK, intent)
finish()
}
}
}
Loading

0 comments on commit 0573627

Please sign in to comment.