diff --git a/app/src/main/java/org/sopt/official/feature/home/HomeActivity.kt b/app/src/main/java/org/sopt/official/feature/home/HomeActivity.kt index d38ac7d68..c7ffab5be 100644 --- a/app/src/main/java/org/sopt/official/feature/home/HomeActivity.kt +++ b/app/src/main/java/org/sopt/official/feature/home/HomeActivity.kt @@ -49,8 +49,8 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import org.sopt.official.R -import org.sopt.official.analytics.AmplitudeTracker import org.sopt.official.analytics.EventType +import org.sopt.official.analytics.Tracker import org.sopt.official.auth.model.UserActiveState import org.sopt.official.auth.model.UserStatus import org.sopt.official.common.navigator.DeepLinkType @@ -90,7 +90,7 @@ class HomeActivity : AppCompatActivity() { private val args by serializableExtra(StartArgs(UserStatus.UNAUTHENTICATED)) @Inject - lateinit var tracker: AmplitudeTracker + lateinit var tracker: Tracker private val smallBlockAdapter: SmallBlockAdapter? get() = binding.smallBlockList.adapter as? SmallBlockAdapter diff --git a/core/analytics/build.gradle.kts b/core/analytics/build.gradle.kts index 53d059ded..91a87e343 100644 --- a/core/analytics/build.gradle.kts +++ b/core/analytics/build.gradle.kts @@ -25,6 +25,7 @@ plugins { sopt("feature") + sopt("compose") } android { diff --git a/core/analytics/src/main/java/org/sopt/official/analytics/Tracker.kt b/core/analytics/src/main/java/org/sopt/official/analytics/Tracker.kt new file mode 100644 index 000000000..b3b547bda --- /dev/null +++ b/core/analytics/src/main/java/org/sopt/official/analytics/Tracker.kt @@ -0,0 +1,30 @@ +/* + * MIT License + * Copyright 2024 SOPT - Shout Our Passion Together + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.sopt.official.analytics + +interface Tracker { + fun track(type: EventType, name: String, properties: Map = emptyMap()) + fun setNotificationStateToUserProperties(value: Boolean) +} diff --git a/core/analytics/src/main/java/org/sopt/official/analytics/TrackerModule.kt b/core/analytics/src/main/java/org/sopt/official/analytics/TrackerModule.kt new file mode 100644 index 000000000..61e0a958b --- /dev/null +++ b/core/analytics/src/main/java/org/sopt/official/analytics/TrackerModule.kt @@ -0,0 +1,40 @@ +/* + * MIT License + * Copyright 2024 SOPT - Shout Our Passion Together + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.sopt.official.analytics + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import org.sopt.official.analytics.impl.AmplitudeTracker +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +interface TrackerModule { + @Binds + @Singleton + fun bindAmplitudeTracker(amplitudeTracker: AmplitudeTracker): Tracker +} diff --git a/core/analytics/src/main/java/org/sopt/official/analytics/compose/CompositionLocal.kt b/core/analytics/src/main/java/org/sopt/official/analytics/compose/CompositionLocal.kt new file mode 100644 index 000000000..502709e7a --- /dev/null +++ b/core/analytics/src/main/java/org/sopt/official/analytics/compose/CompositionLocal.kt @@ -0,0 +1,41 @@ +/* + * MIT License + * Copyright 2024 SOPT - Shout Our Passion Together + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.sopt.official.analytics.compose + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import org.sopt.official.analytics.Tracker + +@Composable +fun ProvideTracker( + tracker: Tracker, + content: @Composable () -> Unit +) { + CompositionLocalProvider( + LocalTracker provides tracker + ) { + content() + } +} diff --git a/core/analytics/src/main/java/org/sopt/official/analytics/compose/LocalTracker.kt b/core/analytics/src/main/java/org/sopt/official/analytics/compose/LocalTracker.kt new file mode 100644 index 000000000..e5f1b8427 --- /dev/null +++ b/core/analytics/src/main/java/org/sopt/official/analytics/compose/LocalTracker.kt @@ -0,0 +1,32 @@ +/* + * MIT License + * Copyright 2024 SOPT - Shout Our Passion Together + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.sopt.official.analytics.compose + +import androidx.compose.runtime.staticCompositionLocalOf +import org.sopt.official.analytics.Tracker + +val LocalTracker = staticCompositionLocalOf { + error("No Tracker provided") +} diff --git a/core/analytics/src/main/java/org/sopt/official/analytics/AmplitudeTracker.kt b/core/analytics/src/main/java/org/sopt/official/analytics/impl/AmplitudeTracker.kt similarity index 86% rename from core/analytics/src/main/java/org/sopt/official/analytics/AmplitudeTracker.kt rename to core/analytics/src/main/java/org/sopt/official/analytics/impl/AmplitudeTracker.kt index 10197d1eb..1d6e154bc 100644 --- a/core/analytics/src/main/java/org/sopt/official/analytics/AmplitudeTracker.kt +++ b/core/analytics/src/main/java/org/sopt/official/analytics/impl/AmplitudeTracker.kt @@ -22,19 +22,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -package org.sopt.official.analytics +package org.sopt.official.analytics.impl import android.content.Context import com.amplitude.android.Amplitude import com.amplitude.android.Configuration import com.amplitude.android.events.Identify import dagger.hilt.android.qualifiers.ApplicationContext -import javax.inject.Inject +import org.sopt.official.analytics.BuildConfig +import org.sopt.official.analytics.EventType +import org.sopt.official.analytics.Tracker import timber.log.Timber +import javax.inject.Inject class AmplitudeTracker @Inject constructor( @ApplicationContext private val context: Context -) { +) : Tracker { private val amplitude = Amplitude( Configuration( apiKey = if (BuildConfig.DEBUG) { @@ -46,14 +49,14 @@ class AmplitudeTracker @Inject constructor( ) ) - fun track(type: EventType, name: String, properties: Map = emptyMap()) { + override fun track(type: EventType, name: String, properties: Map) { if (BuildConfig.DEBUG) { Timber.d("Amplitude: ${type.prefix}_$name properties: $properties") } amplitude.track(eventType = "${type.prefix}_$name", eventProperties = properties) } - fun setNotificationStateToUserProperties(value: Boolean) { + override fun setNotificationStateToUserProperties(value: Boolean) { val identify = Identify() identify.setOnce("state_of_push_notification", value) amplitude.identify(identify) diff --git a/core/analytics/src/main/java/org/sopt/official/analytics/impl/FakeTracker.kt b/core/analytics/src/main/java/org/sopt/official/analytics/impl/FakeTracker.kt new file mode 100644 index 000000000..a443ccf11 --- /dev/null +++ b/core/analytics/src/main/java/org/sopt/official/analytics/impl/FakeTracker.kt @@ -0,0 +1,33 @@ +/* + * MIT License + * Copyright 2024 SOPT - Shout Our Passion Together + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.sopt.official.analytics.impl + +import org.sopt.official.analytics.EventType +import org.sopt.official.analytics.Tracker + +object FakeTracker : Tracker { + override fun track(type: EventType, name: String, properties: Map) = Unit + override fun setNotificationStateToUserProperties(value: Boolean) = Unit +} diff --git a/feature/fortune/src/main/java/org/sopt/official/feature/fortune/FortuneActivity.kt b/feature/fortune/src/main/java/org/sopt/official/feature/fortune/FortuneActivity.kt index 7478a50ba..fedcc6ecb 100644 --- a/feature/fortune/src/main/java/org/sopt/official/feature/fortune/FortuneActivity.kt +++ b/feature/fortune/src/main/java/org/sopt/official/feature/fortune/FortuneActivity.kt @@ -29,12 +29,11 @@ import android.content.Intent import android.os.Bundle import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.staticCompositionLocalOf import com.airbnb.deeplinkdispatch.DeepLink import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.EntryPointAccessors -import org.sopt.official.analytics.AmplitudeTracker +import org.sopt.official.analytics.compose.ProvideTracker +import org.sopt.official.analytics.impl.AmplitudeTracker import org.sopt.official.common.context.appContext import org.sopt.official.common.navigator.NavigatorEntryPoint import org.sopt.official.designsystem.SoptTheme @@ -47,10 +46,6 @@ private val navigator by lazy { ).navigatorProvider() } -internal val LocalAmplitudeTracker = staticCompositionLocalOf { - error("No AmplitudeTracker provided") -} - @AndroidEntryPoint @DeepLink("sopt://fortune") class FortuneActivity : AppCompatActivity() { @@ -62,7 +57,7 @@ class FortuneActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContent { SoptTheme { - CompositionLocalProvider(LocalAmplitudeTracker provides amplitudeTracker) { + ProvideTracker(amplitudeTracker) { FoundationScreen( onClickLeadingIcon = ::finish, navigateToHome = { diff --git a/feature/fortune/src/main/java/org/sopt/official/feature/fortune/FoundationScreen.kt b/feature/fortune/src/main/java/org/sopt/official/feature/fortune/FoundationScreen.kt index 923fec849..7c9c20626 100644 --- a/feature/fortune/src/main/java/org/sopt/official/feature/fortune/FoundationScreen.kt +++ b/feature/fortune/src/main/java/org/sopt/official/feature/fortune/FoundationScreen.kt @@ -43,6 +43,8 @@ import androidx.compose.ui.unit.dp import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.rememberNavController +import org.sopt.official.analytics.compose.ProvideTracker +import org.sopt.official.analytics.impl.FakeTracker import org.sopt.official.designsystem.SoptTheme import org.sopt.official.feature.fortune.R.drawable.ic_alert import org.sopt.official.feature.fortune.R.drawable.ic_poke_check @@ -141,9 +143,11 @@ fun FoundationScreen( @Composable fun FoundationScreenPreview() { SoptTheme { - FoundationScreen( - onClickLeadingIcon = {}, - navigateToHome = {} - ) + ProvideTracker(FakeTracker) { + FoundationScreen( + onClickLeadingIcon = {}, + navigateToHome = {} + ) + } } } diff --git a/feature/fortune/src/main/java/org/sopt/official/feature/fortune/component/FortuneTopBar.kt b/feature/fortune/src/main/java/org/sopt/official/feature/fortune/component/FortuneTopBar.kt index 3c69e5cb9..449bdd3e5 100644 --- a/feature/fortune/src/main/java/org/sopt/official/feature/fortune/component/FortuneTopBar.kt +++ b/feature/fortune/src/main/java/org/sopt/official/feature/fortune/component/FortuneTopBar.kt @@ -36,9 +36,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import org.sopt.official.analytics.EventType +import org.sopt.official.analytics.compose.LocalTracker import org.sopt.official.designsystem.SoptTheme import org.sopt.official.designsystem.SoptTheme.colors -import org.sopt.official.feature.fortune.LocalAmplitudeTracker @Composable fun FortuneTopBar( @@ -46,7 +46,7 @@ fun FortuneTopBar( modifier: Modifier = Modifier, isEnabled: Boolean = true, ) { - val amplitudeTracker = LocalAmplitudeTracker.current + val amplitudeTracker = LocalTracker.current Box(modifier = modifier.fillMaxWidth()) { Icon( diff --git a/feature/fortune/src/main/java/org/sopt/official/feature/fortune/feature/fortuneAmulet/FortuneAmuletScreen.kt b/feature/fortune/src/main/java/org/sopt/official/feature/fortune/feature/fortuneAmulet/FortuneAmuletScreen.kt index 37c8dc7bf..b0d6cb75f 100644 --- a/feature/fortune/src/main/java/org/sopt/official/feature/fortune/feature/fortuneAmulet/FortuneAmuletScreen.kt +++ b/feature/fortune/src/main/java/org/sopt/official/feature/fortune/feature/fortuneAmulet/FortuneAmuletScreen.kt @@ -46,8 +46,8 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import org.sopt.official.analytics.EventType +import org.sopt.official.analytics.compose.LocalTracker import org.sopt.official.designsystem.SoptTheme -import org.sopt.official.feature.fortune.LocalAmplitudeTracker import org.sopt.official.feature.fortune.component.CircleShapeBorderButton import org.sopt.official.feature.fortune.component.UrlImage @@ -56,7 +56,7 @@ internal fun FortuneAmuletRoute( onHomeClick: () -> Unit, viewModel: FortuneAmuletViewModel = hiltViewModel(), ) { - val amplitudeTracker = LocalAmplitudeTracker.current + val amplitudeTracker = LocalTracker.current val state by viewModel.state.collectAsStateWithLifecycle() when { diff --git a/feature/fortune/src/main/java/org/sopt/official/feature/fortune/feature/fortuneDetail/FortuneDetailRoute.kt b/feature/fortune/src/main/java/org/sopt/official/feature/fortune/feature/fortuneDetail/FortuneDetailRoute.kt index 204d2d789..1ec13d43e 100644 --- a/feature/fortune/src/main/java/org/sopt/official/feature/fortune/feature/fortuneDetail/FortuneDetailRoute.kt +++ b/feature/fortune/src/main/java/org/sopt/official/feature/fortune/feature/fortuneDetail/FortuneDetailRoute.kt @@ -47,8 +47,8 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import kotlinx.coroutines.launch import org.sopt.official.analytics.EventType.CLICK import org.sopt.official.analytics.EventType.VIEW +import org.sopt.official.analytics.compose.LocalTracker import org.sopt.official.designsystem.SoptTheme.colors -import org.sopt.official.feature.fortune.LocalAmplitudeTracker import org.sopt.official.feature.fortune.feature.fortuneDetail.component.PokeMessageBottomSheetScreen import org.sopt.official.feature.fortune.feature.fortuneDetail.model.FortuneDetailUiState.Success import org.sopt.official.feature.fortune.feature.fortuneDetail.model.SnackBarUiState @@ -73,7 +73,7 @@ internal fun FortuneDetailRoute( var selectedIndex by remember { mutableIntStateOf(DEFAULT_ID) } val bottomSheetState = rememberModalBottomSheetState(initialValue = Hidden) val scope = rememberCoroutineScope() - val amplitudeTracker = LocalAmplitudeTracker.current + val amplitudeTracker = LocalTracker.current LaunchedEffect(key1 = uiState) { if (uiState is Success) { diff --git a/feature/fortune/src/main/java/org/sopt/official/feature/fortune/feature/home/HomeScreen.kt b/feature/fortune/src/main/java/org/sopt/official/feature/fortune/feature/home/HomeScreen.kt index 2eaceea6a..728a6710d 100644 --- a/feature/fortune/src/main/java/org/sopt/official/feature/fortune/feature/home/HomeScreen.kt +++ b/feature/fortune/src/main/java/org/sopt/official/feature/fortune/feature/home/HomeScreen.kt @@ -41,8 +41,8 @@ import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import org.sopt.official.analytics.EventType +import org.sopt.official.analytics.compose.LocalTracker import org.sopt.official.designsystem.SoptTheme -import org.sopt.official.feature.fortune.LocalAmplitudeTracker import org.sopt.official.feature.fortune.R import org.sopt.official.feature.fortune.component.FortuneButton import java.time.LocalDate @@ -55,7 +55,7 @@ internal fun HomeRoute( onFortuneDetailClick: (String) -> Unit, ) { val date = rememberSaveable { getToday() } - val amplitudeTracker = LocalAmplitudeTracker.current.also { + val amplitudeTracker = LocalTracker.current.also { it.track( type = EventType.VIEW, name = "view_soptmadi_title", diff --git a/feature/poke/src/main/java/org/sopt/official/feature/poke/friend/detail/FriendListDetailBottomSheetFragment.kt b/feature/poke/src/main/java/org/sopt/official/feature/poke/friend/detail/FriendListDetailBottomSheetFragment.kt index 09e9d1296..a42064a55 100644 --- a/feature/poke/src/main/java/org/sopt/official/feature/poke/friend/detail/FriendListDetailBottomSheetFragment.kt +++ b/feature/poke/src/main/java/org/sopt/official/feature/poke/friend/detail/FriendListDetailBottomSheetFragment.kt @@ -40,13 +40,12 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialogFragment import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import kotlinx.coroutines.delay import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -import org.sopt.official.analytics.AmplitudeTracker import org.sopt.official.analytics.EventType +import org.sopt.official.analytics.Tracker import org.sopt.official.common.util.colorOf import org.sopt.official.common.util.dp import org.sopt.official.common.util.ui.setVisible @@ -66,6 +65,7 @@ import org.sopt.official.feature.poke.user.PokeUserListItemViewType import org.sopt.official.feature.poke.util.addOnAnimationEndListener import org.sopt.official.feature.poke.util.setRelationStrokeColor import org.sopt.official.feature.poke.util.showPokeToast +import javax.inject.Inject @AndroidEntryPoint class FriendListDetailBottomSheetFragment : BottomSheetDialogFragment() { @@ -73,7 +73,7 @@ class FriendListDetailBottomSheetFragment : BottomSheetDialogFragment() { private lateinit var viewModel: FriendListDetailViewModel @Inject - lateinit var tracker: AmplitudeTracker + lateinit var tracker: Tracker private var messageListBottomSheet: MessageListBottomSheetFragment? = null diff --git a/feature/poke/src/main/java/org/sopt/official/feature/poke/friend/summary/FriendListSummaryActivity.kt b/feature/poke/src/main/java/org/sopt/official/feature/poke/friend/summary/FriendListSummaryActivity.kt index 73fe79260..7563b81be 100644 --- a/feature/poke/src/main/java/org/sopt/official/feature/poke/friend/summary/FriendListSummaryActivity.kt +++ b/feature/poke/src/main/java/org/sopt/official/feature/poke/friend/summary/FriendListSummaryActivity.kt @@ -35,14 +35,12 @@ import androidx.lifecycle.lifecycleScope import coil.load import coil.transform.CircleCropTransformation import dagger.hilt.android.AndroidEntryPoint -import java.io.Serializable -import javax.inject.Inject import kotlinx.coroutines.delay import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -import org.sopt.official.analytics.AmplitudeTracker import org.sopt.official.analytics.EventType +import org.sopt.official.analytics.Tracker import org.sopt.official.auth.model.UserStatus import org.sopt.official.common.util.colorOf import org.sopt.official.common.util.dp @@ -66,6 +64,8 @@ import org.sopt.official.feature.poke.user.PokeUserListItemViewType import org.sopt.official.feature.poke.util.addOnAnimationEndListener import org.sopt.official.feature.poke.util.setRelationStrokeColor import org.sopt.official.feature.poke.util.showPokeToast +import java.io.Serializable +import javax.inject.Inject @AndroidEntryPoint class FriendListSummaryActivity : AppCompatActivity() { @@ -76,7 +76,7 @@ class FriendListSummaryActivity : AppCompatActivity() { private var messageListBottomSheet: MessageListBottomSheetFragment? = null @Inject - lateinit var tracker: AmplitudeTracker + lateinit var tracker: Tracker private val newFriendListAdapter get() = binding.includeFriendListBlockNewFriend.recyclerView.adapter as PokeUserListAdapter? diff --git a/feature/poke/src/main/java/org/sopt/official/feature/poke/main/PokeMainActivity.kt b/feature/poke/src/main/java/org/sopt/official/feature/poke/main/PokeMainActivity.kt index 640bb2618..c93af04f8 100644 --- a/feature/poke/src/main/java/org/sopt/official/feature/poke/main/PokeMainActivity.kt +++ b/feature/poke/src/main/java/org/sopt/official/feature/poke/main/PokeMainActivity.kt @@ -39,8 +39,8 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -import org.sopt.official.analytics.AmplitudeTracker import org.sopt.official.analytics.EventType +import org.sopt.official.analytics.Tracker import org.sopt.official.auth.model.UserStatus import org.sopt.official.common.util.serializableExtra import org.sopt.official.common.util.ui.setVisible @@ -74,7 +74,7 @@ class PokeMainActivity : AppCompatActivity() { get() = binding.recyclerViewPokeMain.adapter as PokeMainListAdapter? @Inject - lateinit var tracker: AmplitudeTracker + lateinit var tracker: Tracker override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/feature/poke/src/main/java/org/sopt/official/feature/poke/notification/PokeNotificationActivity.kt b/feature/poke/src/main/java/org/sopt/official/feature/poke/notification/PokeNotificationActivity.kt index 8d11012ef..a9573d2c6 100644 --- a/feature/poke/src/main/java/org/sopt/official/feature/poke/notification/PokeNotificationActivity.kt +++ b/feature/poke/src/main/java/org/sopt/official/feature/poke/notification/PokeNotificationActivity.kt @@ -42,8 +42,8 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -import org.sopt.official.analytics.AmplitudeTracker import org.sopt.official.analytics.EventType +import org.sopt.official.analytics.Tracker import org.sopt.official.common.util.serializableExtra import org.sopt.official.common.util.viewBinding import org.sopt.official.domain.poke.entity.PokeUser @@ -68,7 +68,7 @@ class PokeNotificationActivity : AppCompatActivity() { private val args by serializableExtra(Argument("")) @Inject - lateinit var tracker: AmplitudeTracker + lateinit var tracker: Tracker private val pokeNotificationAdapter get() = binding.recyclerviewPokeNotification.adapter as PokeNotificationAdapter diff --git a/feature/poke/src/main/java/org/sopt/official/feature/poke/onboarding/OnboardingActivity.kt b/feature/poke/src/main/java/org/sopt/official/feature/poke/onboarding/OnboardingActivity.kt index e7c06c372..ba86ba13d 100644 --- a/feature/poke/src/main/java/org/sopt/official/feature/poke/onboarding/OnboardingActivity.kt +++ b/feature/poke/src/main/java/org/sopt/official/feature/poke/onboarding/OnboardingActivity.kt @@ -33,12 +33,10 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint -import java.io.Serializable -import javax.inject.Inject import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import org.sopt.official.analytics.AmplitudeTracker import org.sopt.official.analytics.EventType +import org.sopt.official.analytics.Tracker import org.sopt.official.common.util.serializableExtra import org.sopt.official.common.util.viewBinding import org.sopt.official.domain.poke.entity.PokeRandomUserList @@ -48,6 +46,8 @@ import org.sopt.official.feature.poke.databinding.ActivityOnboardingBinding import org.sopt.official.feature.poke.main.PokeMainActivity import org.sopt.official.feature.poke.util.addOnAnimationEndListener import org.sopt.official.feature.poke.util.showPokeToast +import java.io.Serializable +import javax.inject.Inject @AndroidEntryPoint class OnboardingActivity : AppCompatActivity() { @@ -59,7 +59,7 @@ class OnboardingActivity : AppCompatActivity() { private var onboardingBottomSheet: OnboardingBottomSheetFragment? = null @Inject - lateinit var tracker: AmplitudeTracker + lateinit var tracker: Tracker override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/feature/poke/src/main/java/org/sopt/official/feature/poke/onboarding/OnboardingPokeUserFragment.kt b/feature/poke/src/main/java/org/sopt/official/feature/poke/onboarding/OnboardingPokeUserFragment.kt index e82ec1a6d..34cc8c361 100644 --- a/feature/poke/src/main/java/org/sopt/official/feature/poke/onboarding/OnboardingPokeUserFragment.kt +++ b/feature/poke/src/main/java/org/sopt/official/feature/poke/onboarding/OnboardingPokeUserFragment.kt @@ -35,11 +35,10 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import org.sopt.official.analytics.AmplitudeTracker import org.sopt.official.analytics.EventType +import org.sopt.official.analytics.Tracker import org.sopt.official.common.util.serializableArgs import org.sopt.official.domain.poke.entity.PokeRandomUserList import org.sopt.official.domain.poke.entity.PokeUser @@ -54,6 +53,7 @@ import org.sopt.official.feature.poke.user.PokeUserListAdapter import org.sopt.official.feature.poke.user.PokeUserListClickListener import org.sopt.official.feature.poke.user.PokeUserListItemViewType import org.sopt.official.feature.poke.util.showPokeToast +import javax.inject.Inject @AndroidEntryPoint class OnboardingPokeUserFragment : Fragment() { @@ -66,7 +66,7 @@ class OnboardingPokeUserFragment : Fragment() { private val args by serializableArgs() @Inject - lateinit var tracker: AmplitudeTracker + lateinit var tracker: Tracker private var messageListBottomSheet: MessageListBottomSheetFragment? = null private val pokeUserListAdapter diff --git a/feature/soptamp/src/main/java/org/sopt/official/stamp/SoptampActivity.kt b/feature/soptamp/src/main/java/org/sopt/official/stamp/SoptampActivity.kt index beb4cc69a..f45831cdb 100644 --- a/feature/soptamp/src/main/java/org/sopt/official/stamp/SoptampActivity.kt +++ b/feature/soptamp/src/main/java/org/sopt/official/stamp/SoptampActivity.kt @@ -30,46 +30,40 @@ import android.graphics.Color import android.os.Bundle import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.SideEffect -import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat import com.ramcosta.composedestinations.DestinationsNavHost import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject -import org.sopt.official.analytics.AmplitudeTracker +import org.sopt.official.analytics.Tracker +import org.sopt.official.analytics.compose.ProvideTracker import org.sopt.official.stamp.feature.NavGraphs - -val LocalTracker = staticCompositionLocalOf { - error("No AmplitudeTracker provided") -} +import javax.inject.Inject @AndroidEntryPoint class SoptampActivity : AppCompatActivity() { - @Inject - lateinit var tracker: AmplitudeTracker + @Inject + lateinit var tracker: Tracker - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContent { - val view = LocalView.current - if (!view.isInEditMode) { - SideEffect { - window.statusBarColor = Color.WHITE - WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = true + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + window.statusBarColor = Color.WHITE + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = true + } + } + ProvideTracker(tracker) { + DestinationsNavHost(navGraph = NavGraphs.root) + } } - } - - CompositionLocalProvider(LocalTracker provides tracker) { - DestinationsNavHost(navGraph = NavGraphs.root) - } } - } - companion object { - fun getIntent(context: Context): Intent { - return Intent(context, SoptampActivity::class.java) + companion object { + fun getIntent(context: Context): Intent { + return Intent(context, SoptampActivity::class.java) + } } - } } diff --git a/feature/soptamp/src/main/java/org/sopt/official/stamp/feature/ranking/part/PartRankingScreen.kt b/feature/soptamp/src/main/java/org/sopt/official/stamp/feature/ranking/part/PartRankingScreen.kt index 84023ea45..89bfcfb28 100644 --- a/feature/soptamp/src/main/java/org/sopt/official/stamp/feature/ranking/part/PartRankingScreen.kt +++ b/feature/soptamp/src/main/java/org/sopt/official/stamp/feature/ranking/part/PartRankingScreen.kt @@ -47,7 +47,6 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -61,7 +60,7 @@ import com.ramcosta.composedestinations.result.ResultBackNavigator import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import org.sopt.official.analytics.EventType -import org.sopt.official.stamp.LocalTracker +import org.sopt.official.analytics.compose.LocalTracker import org.sopt.official.stamp.config.navigation.MissionNavGraph import org.sopt.official.stamp.designsystem.component.dialog.SingleOptionDialog import org.sopt.official.stamp.designsystem.component.layout.LoadingScreen diff --git a/feature/soptamp/src/main/java/org/sopt/official/stamp/feature/ranking/rank/RankingScreen.kt b/feature/soptamp/src/main/java/org/sopt/official/stamp/feature/ranking/rank/RankingScreen.kt index e07634077..72c8047bc 100644 --- a/feature/soptamp/src/main/java/org/sopt/official/stamp/feature/ranking/rank/RankingScreen.kt +++ b/feature/soptamp/src/main/java/org/sopt/official/stamp/feature/ranking/rank/RankingScreen.kt @@ -42,7 +42,6 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment @@ -59,7 +58,7 @@ import com.ramcosta.composedestinations.navigation.DestinationsNavigator import com.ramcosta.composedestinations.result.ResultBackNavigator import kotlinx.coroutines.launch import org.sopt.official.analytics.EventType -import org.sopt.official.stamp.LocalTracker +import org.sopt.official.analytics.compose.LocalTracker import org.sopt.official.stamp.R import org.sopt.official.stamp.config.navigation.MissionNavGraph import org.sopt.official.stamp.designsystem.component.button.SoptampFloatingButton