Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a44b086
feat: 서비스 온보딩 보여주는지 여부 결정 시점 변경
ThirFir Sep 20, 2025
50f8be1
feat: 싫어하는 음식 선택 중, 앱 종료 후 재접속 시 다시 보여주지 않음
ThirFir Sep 20, 2025
d899b7e
feat: 로그인 건너뛰기 텍스트 색상 변경
ThirFir Sep 20, 2025
1a0599a
fix: App Update 예외 처리
ThirFir Sep 21, 2025
7eff526
fix: Presigned url get api 헤더 추가
ThirFir Sep 22, 2025
1bae1b5
refactor: 온보딩 순서 변경
ThirFir Sep 22, 2025
374b3de
fix: proto datastore 클래스 난독화 제외
ThirFir Sep 23, 2025
42090fb
chore: 빌드 Flavor 추가: production/qa
ThirFir Sep 23, 2025
1bbf143
fix: QA 빌드에서는 InAppUpdate 이용하지 않도록 수정
ThirFir Sep 23, 2025
777522a
feat: 장소 없을 시 등록 프로세스 - 웹 이동 대신 앱 내 등록 피쳐 이동으로 변경
ThirFir Sep 23, 2025
410e300
chore: 테스트 의존성 build-logic 관리 통합
ThirFir Sep 23, 2025
08e856e
fix: 광고 callToAction 클릭 시 무반응 수정
ThirFir Sep 24, 2025
dfdeb2c
chore: ads provider 모듈 제거 -> core로 통합
ThirFir Sep 24, 2025
34fe177
refactor: AdProvider interface 제거 -> Composable 직접 이용으로 변경
ThirFir Sep 24, 2025
3771351
chore: app -> acon 모듈명 변경
ThirFir Sep 24, 2025
b999a54
feat: 설정에서 지역인증 시 뒤로가기 아이콘 추가
ThirFir Sep 24, 2025
f1fafd0
fix: 지역인증, 건너뛰기 화면 1회 렌더했음에도 이후에 다시 보이는 문제 수정
ThirFir Sep 24, 2025
adbe932
fix: 비로그인 사용자 상세 페이지 진입 가능하게 수정
ThirFir Sep 25, 2025
bb4b219
fix: 회원탈퇴 시 프로필 캐시 초기화
ThirFir Sep 25, 2025
d94a86b
fix: 로그인 이력있던 유저는 앱 최초 진입 시 온보딩 소개 X
ThirFir Sep 25, 2025
200192c
refactor: 이미지 업로드 레포 함수 병렬 처리
ThirFir Sep 25, 2025
9168fcf
chore: 이미지 업로드 메서드 KDoc 작성
ThirFir Sep 25, 2025
46e80f8
fix: 비로그인 저장한 장소 클릭 시 로그인 바텀시트 표시
ThirFir Sep 25, 2025
49fa7c6
fix: 장소 등록 presignedUrlAPI 변경 사항 적용
1971123-seongmin Sep 25, 2025
f06ea79
merge: fix/#262-place-upload-presigned-fix -> feat/relax-guest-policy
ThirFir Sep 26, 2025
7cd2f3f
fix: app모듈명 변경에 따른 build workflow 수정
ThirFir Oct 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/debug_build_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
echo '${{ secrets.LOCAL_PROPERTIES }}' >> ./local.properties

- name: Access Google-Service file
run: echo '${{ secrets.GOOGLE_SERVICES_JSON }}' > ./app/google-services.json
run: echo '${{ secrets.GOOGLE_SERVICES_JSON }}' > ./acon/google-services.json

- name: Grant execute permission for gradlew
run: chmod +x gradlew
Expand Down
File renamed without changes.
35 changes: 22 additions & 13 deletions app/build.gradle.kts → acon/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import utils.androidTestImplementation

/** See AndroidApplicationConventionPlugin.kt */

plugins {
Expand All @@ -9,11 +7,24 @@ plugins {
alias(libs.plugins.acon.android.library.haze)
alias(libs.plugins.acon.android.library.naver.map)
alias(libs.plugins.acon.firebase)
alias(libs.plugins.acon.common.unit.test)
}

android {
namespace = "com.acon.acon"

flavorDimensions += "distributionChannel"
productFlavors {
create("qa") {
dimension = "distributionChannel"
buildConfigField("boolean", "IS_QA_BUILD", "true")
}
create("production") {
dimension = "distributionChannel"
buildConfigField("boolean", "IS_QA_BUILD", "false")
}
}

buildTypes {
debug {
applicationIdSuffix = ".debug"
Expand All @@ -35,11 +46,19 @@ android {
}
}

androidComponents {
beforeVariants(selector().all()) { variant ->
if (variant.name == "productionDebug") {
variant.enable = false
}
}
}

dependencies {

implementation(projects.core.designsystem)
implementation(projects.core.map)
implementation(projects.core.adsApi)
implementation(projects.core.ads)
implementation(projects.core.analytics)
implementation(projects.core.navigation)
implementation(projects.core.ui)
Expand All @@ -56,20 +75,10 @@ dependencies {
implementation(projects.feature.settings)
implementation(projects.feature.profile)

implementation(projects.provider.adsImpl)

implementation(libs.branch.io)
implementation(libs.google.services.ads)
implementation(libs.play.services.location)
implementation(libs.startup)

implementation(libs.androidx.core.splashscreen)

testImplementation(libs.bundles.non.android.test)
testRuntimeOnly(libs.bundles.junit5.runtime)
androidTestImplementation(libs.bundles.android.test)
}

tasks.withType<Test> {
useJUnitPlatform()
}
File renamed without changes.
4 changes: 3 additions & 1 deletion app/proguard-rules.pro → acon/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,6 @@

-dontwarn androidx.**
-keep class androidx.** { *; }
-keep interface androidx.** { *; }
-keep interface androidx.** { *; }

-keep class com.acon.core.data.dto.entity.OnboardingPreferencesEntity { *; }
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ import androidx.core.view.WindowCompat
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.navigation.compose.rememberNavController
import com.acon.acon.core.ads_api.AdProvider
import com.acon.acon.core.ads_api.LocalSpotListAdProvider
import com.acon.acon.core.analytics.amplitude.AconAmplitude
import com.acon.acon.core.analytics.constants.EventNames
import com.acon.acon.core.common.DeepLinkHandler
Expand All @@ -50,6 +48,7 @@ import com.acon.acon.core.designsystem.effect.rememberHazeState
import com.acon.acon.core.designsystem.theme.AconTheme
import com.acon.acon.core.navigation.LocalNavController
import com.acon.acon.core.navigation.route.AreaVerificationRoute
import com.acon.acon.core.navigation.route.OnboardingRoute
import com.acon.acon.core.navigation.route.SpotRoute
import com.acon.acon.core.navigation.utils.navigateAndClear
import com.acon.acon.core.ui.activityComponentEntryPoint
Expand All @@ -58,16 +57,15 @@ import com.acon.acon.core.ui.compose.LocalDeepLinkHandler
import com.acon.acon.core.ui.compose.LocalLocation
import com.acon.acon.core.ui.compose.LocalRequestLocationPermission
import com.acon.acon.core.ui.compose.LocalRequestSignIn
import com.acon.acon.core.ui.compose.LocalSnackbarHostState
import com.acon.acon.core.ui.compose.LocalSignInStatus
import com.acon.acon.core.ui.compose.LocalSnackbarHostState
import com.acon.acon.domain.repository.AconAppRepository
import com.acon.acon.domain.repository.OnboardingRepository
import com.acon.acon.domain.repository.UserRepository
import com.acon.acon.navigation.AconNavigation
import com.acon.acon.provider.ads_impl.SpotListAdProvider
import com.acon.acon.update.AppUpdateHandler
import com.acon.acon.update.AppUpdateHandlerImpl
import com.acon.acon.update.UpdateState
import com.acon.core.social.client.GoogleAuthClient
import com.acon.core.social.di.AuthClientEntryPoint
import com.google.android.gms.common.api.ResolvableApiException
import com.google.android.gms.location.LocationCallback
Expand Down Expand Up @@ -105,14 +103,16 @@ class MainActivity : ComponentActivity() {
@Inject
lateinit var userRepository: UserRepository

@Inject
lateinit var onboardingRepository: OnboardingRepository

@Inject
lateinit var aconAppRepository: AconAppRepository

private val viewModel by viewModels<MainViewModel>()

private val deepLinkHandler = DeepLinkHandler()

private val spotListAdProvider: AdProvider = SpotListAdProvider()
private val gpsResolutionResultLauncher = registerForActivityResult(
ActivityResultContracts.StartIntentSenderForResult()
) { result ->
Expand All @@ -124,8 +124,11 @@ class MainActivity : ComponentActivity() {
}

private val appUpdateManager by lazy {
AppUpdateManagerFactory.create(application)
if (!BuildConfig.IS_QA_BUILD)
AppUpdateManagerFactory.create(application)
else null
}

private val appUpdateActivityResultLauncher =
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
when (result.resultCode) {
Expand All @@ -152,22 +155,22 @@ class MainActivity : ComponentActivity() {
)
when (result) {
SnackbarResult.ActionPerformed -> {
appUpdateManager.completeUpdate()
appUpdateManager?.completeUpdate()
}

SnackbarResult.Dismissed -> Unit
}
}
} else if (state.installStatus() == InstallStatus.INSTALLED) {
appUpdateManager.unregisterListener(this)
appUpdateManager?.unregisterListener(this)
}
}
}
}

private val appUpdateHandler: AppUpdateHandler by lazy {
AppUpdateHandlerImpl(
appUpdateManager = appUpdateManager.apply {
appUpdateManager = appUpdateManager?.apply {
registerListener(appInstallStateListener)
},
aconAppRepository = aconAppRepository,
Expand Down Expand Up @@ -328,7 +331,6 @@ class MainActivity : ComponentActivity() {
viewModel.updateAmplPropertyKey(it)
},
LocalRequestLocationPermission provides ::requestLocationPermission,
LocalSpotListAdProvider provides spotListAdProvider,
LocalDeepLinkHandler provides deepLinkHandler
) {
AconNavigation(
Expand All @@ -346,25 +348,28 @@ class MainActivity : ComponentActivity() {
val code = client.getCredentialCode() ?: return@launch

userRepository.signIn(client.platform, code)
.onSuccess { verificationStatus ->
if (verificationStatus.hasVerifiedArea) {
navController.navigate(SpotRoute.SpotList) {
popUpTo(navController.graph.id) {
inclusive = true
}
}
} else {
navController.navigateAndClear(
AreaVerificationRoute.AreaVerification
)
}
.onSuccess { externalUUID ->
if (appState.propertyKey.isNotBlank()) {
AconAmplitude.trackEvent(
eventName = EventNames.GUEST,
property = appState.propertyKey to true
)
}
AconAmplitude.setUserId(verificationStatus.externalUUID)
AconAmplitude.setUserId(externalUUID.value)

onboardingRepository.getOnboardingPreferences().onSuccess { pref ->
if (pref.shouldShowIntroduce) {
navController.navigateAndClear(OnboardingRoute.Introduce)
} else if (pref.shouldVerifyArea) {
navController.navigateAndClear(AreaVerificationRoute.AreaVerification)
} else if (pref.shouldChooseDislikes) {
navController.navigateAndClear(OnboardingRoute.ChooseDislikes)
} else {
navController.navigateAndClear(SpotRoute.SpotList)
}
}.onFailure {
navController.navigateAndClear(SpotRoute.SpotList)
}
}.onFailure { e ->
Timber.e(e)
}
Expand Down Expand Up @@ -478,9 +483,9 @@ class MainActivity : ComponentActivity() {
}

DisposableEffect(appUpdateManager) {
appUpdateManager.registerListener(appInstallStateListener)
appUpdateManager?.registerListener(appInstallStateListener)
onDispose {
appUpdateManager.unregisterListener(appInstallStateListener)
appUpdateManager?.unregisterListener(appInstallStateListener)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ fun NavGraphBuilder.areaVerificationNavigation(
skippable = LocalNavController.current.hasPreviousBackStackEntry().not(),
onNavigateToChooseDislikes = { navController.navigateAndClear(OnboardingRoute.ChooseDislikes) },
onNavigateToIntroduce = { navController.navigateAndClear(OnboardingRoute.Introduce) },
onNavigateToSpotList = { navController.navigateAndClear(SpotRoute.SpotList) }
onNavigateToSpotList = { navController.navigateAndClear(SpotRoute.SpotList) },
onNavigateBack = navController::navigateUp
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.navigation
import com.acon.acon.core.designsystem.effect.screenDefault
import com.acon.acon.core.navigation.LocalNavController
import com.acon.acon.core.navigation.route.AreaVerificationRoute
import com.acon.acon.core.navigation.route.OnboardingRoute
import com.acon.acon.core.navigation.route.SettingsRoute
import com.acon.acon.core.navigation.route.SpotRoute
Expand Down Expand Up @@ -51,6 +52,12 @@ internal fun NavGraphBuilder.onboardingNavigation(
modifier = Modifier.screenDefault().statusBarsPadding(),
onNavigateToHome = {
navController.navigateAndClear(SpotRoute.Graph)
},
onNavigateToAreaVerification = {
navController.navigateAndClear(AreaVerificationRoute.Graph)
},
onNavigateToChooseDislikes = {
navController.navigateAndClear(OnboardingRoute.ChooseDislikes)
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ internal fun NavGraphBuilder.spotNavigation(
onNavigateToAreaVerificationScreen = { lat, lon ->
navController.navigate(AreaVerificationRoute.VerifyInMap)
},
onNavigateToUploadPlace = {
navController.navigate(UploadRoute.Place)
},
modifier = Modifier
.fillMaxSize()
.background(AconTheme.color.Gray900)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,17 @@ interface AppUpdateHandler {
}

class AppUpdateHandlerImpl(
private val appUpdateManager: AppUpdateManager,
private val appUpdateManager: AppUpdateManager?,
private val aconAppRepository: AconAppRepository,
private val appUpdateActivityResultLauncher: ActivityResultLauncher<IntentSenderRequest>,
private val application: Application,
private val scope: CoroutineScope
) : AppUpdateHandler {

private val appUpdateInfo = flow {
emit(appUpdateManager.appUpdateInfo.await())
appUpdateManager?.appUpdateInfo?.let {
emit(it.await())
}
}.stateIn(
scope = scope,
started = SharingStarted.WhileSubscribed(5_000),
Expand All @@ -56,7 +58,7 @@ class AppUpdateHandlerImpl(
val packageInfo =
application.packageManager.getPackageInfo(application.packageName, 0)
packageInfo.versionName
} catch (e: Exception) {
} catch (_: Exception) {
null
}
if (currentAppVersion == null)
Expand All @@ -80,7 +82,7 @@ class AppUpdateHandlerImpl(
}

override fun startFlexibleUpdate() {
appUpdateManager.startUpdateFlowForResult(
appUpdateManager?.startUpdateFlowForResult(
appUpdateInfo.value ?: return,
appUpdateActivityResultLauncher,
AppUpdateOptions.defaultOptions(AppUpdateType.FLEXIBLE)
Expand Down
File renamed without changes.
File renamed without changes.
22 changes: 0 additions & 22 deletions app/src/androidTest/java/com/acon/acon/ExampleInstrumentedTest.kt

This file was deleted.

8 changes: 8 additions & 0 deletions build-logic/convention/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,13 @@ gradlePlugin {
id = "com.acon.firebase"
implementationClass = "FirebaseConventionPlugin"
}
register("featureTest") {
id = "com.acon.feature.test"
implementationClass = "test.FeatureTestConventionPlugin"
}
register("commonUnitTest") {
id = "com.acon.common.unit.test"
implementationClass = "test.CommonUnitTestConventionPlugin"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class AndroidApplicationComposeConventionPlugin: Plugin<Project> {
extensions.configure<ApplicationExtension> {
buildFeatures {
compose = true
buildConfig = true
}
composeOptions {
kotlinCompilerExtensionVersion =
Expand Down
Loading