From 718289b8f857aced19e2a433f1276a76c09d5d78 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 01:41:34 +0900 Subject: [PATCH 01/24] Change activity name --- frontend/app/src/main/AndroidManifest.xml | 2 +- .../example/frontend/{MapActivity.kt => MainActivity.kt} | 2 +- .../app/src/main/java/com/example/frontend/MeetupListUI.kt | 2 +- .../main/java/com/example/frontend/SplashScreenActivity.kt | 2 +- .../java/com/example/frontend/usecase/login/LoginUseCase.kt | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) rename frontend/app/src/main/java/com/example/frontend/{MapActivity.kt => MainActivity.kt} (99%) diff --git a/frontend/app/src/main/AndroidManifest.xml b/frontend/app/src/main/AndroidManifest.xml index 64a09753..63bf218f 100644 --- a/frontend/app/src/main/AndroidManifest.xml +++ b/frontend/app/src/main/AndroidManifest.xml @@ -36,7 +36,7 @@ android:theme="@style/Theme.Frontend" /> diff --git a/frontend/app/src/main/java/com/example/frontend/MapActivity.kt b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt similarity index 99% rename from frontend/app/src/main/java/com/example/frontend/MapActivity.kt rename to frontend/app/src/main/java/com/example/frontend/MainActivity.kt index 83a611f2..313132d7 100644 --- a/frontend/app/src/main/java/com/example/frontend/MapActivity.kt +++ b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt @@ -54,7 +54,7 @@ import kotlinx.coroutines.isActive @AndroidEntryPoint -class MapActivity : ComponentActivity() { +class MainActivity : ComponentActivity() { private lateinit var fusedLocationClient: FusedLocationProviderClient var currentLocation by mutableStateOf(null) diff --git a/frontend/app/src/main/java/com/example/frontend/MeetupListUI.kt b/frontend/app/src/main/java/com/example/frontend/MeetupListUI.kt index 4e7e47ed..fe00068b 100644 --- a/frontend/app/src/main/java/com/example/frontend/MeetupListUI.kt +++ b/frontend/app/src/main/java/com/example/frontend/MeetupListUI.kt @@ -182,7 +182,7 @@ fun ShowMeetUpUIPreview() { modifier = Modifier .size(46.dp) .clickable { - val nextIntent = Intent(context, MapActivity::class.java) + val nextIntent = Intent(context, MainActivity::class.java) context.startActivity(nextIntent) // finish current activity if (context is Activity) { diff --git a/frontend/app/src/main/java/com/example/frontend/SplashScreenActivity.kt b/frontend/app/src/main/java/com/example/frontend/SplashScreenActivity.kt index 8e1266b7..dfaba1b5 100644 --- a/frontend/app/src/main/java/com/example/frontend/SplashScreenActivity.kt +++ b/frontend/app/src/main/java/com/example/frontend/SplashScreenActivity.kt @@ -17,7 +17,7 @@ class SplashScreenActivity : AppCompatActivity() { if (userContextRepository.getIsLoggedIn()) { // User is already logged in, skip the login activity - startActivity(Intent(this, MapActivity::class.java)) + startActivity(Intent(this, MainActivity::class.java)) } else { // User is not logged in, go to the login activity startActivity(Intent(this, LoginActivity::class.java)) diff --git a/frontend/app/src/main/java/com/example/frontend/usecase/login/LoginUseCase.kt b/frontend/app/src/main/java/com/example/frontend/usecase/login/LoginUseCase.kt index a1623e8c..444ba84d 100644 --- a/frontend/app/src/main/java/com/example/frontend/usecase/login/LoginUseCase.kt +++ b/frontend/app/src/main/java/com/example/frontend/usecase/login/LoginUseCase.kt @@ -5,7 +5,7 @@ import android.content.Context import android.content.Intent import android.widget.Toast import androidx.compose.runtime.MutableState -import com.example.frontend.MapActivity +import com.example.frontend.MainActivity import com.example.frontend.api.AuthService import com.example.frontend.model.AuthResponse import com.example.frontend.model.LoginModel @@ -29,7 +29,7 @@ class LoginUseCase( val loginModel = LoginModel(email, password) if (BYPASS_LOGIN) { // TODO(heka1024): Remove this flag - val nextIntent = Intent(context, MapActivity::class.java) + val nextIntent = Intent(context, MainActivity::class.java) context.startActivity(nextIntent) if (context is Activity) { context.finish() @@ -44,7 +44,7 @@ class LoginUseCase( saveAuthToken(authToken) result.value = "Logged in successfully" - val nextIntent = Intent(context, MapActivity::class.java) + val nextIntent = Intent(context, MainActivity::class.java) context.startActivity(nextIntent) if (context is Activity) { From 922fdcd7cba1c389c446ad6fa24fba3c4f350246 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 03:52:11 +0900 Subject: [PATCH 02/24] =?UTF-8?q?=ED=8F=B4=EB=A6=AC=EA=B3=A4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/frontend/MainActivity.kt | 9 ++------ .../example/frontend/ui/component/MapUI.kt | 12 +++++++++- .../example/frontend/utilities/Location.kt | 22 +++++++++++++++++++ 3 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 frontend/app/src/main/java/com/example/frontend/utilities/Location.kt diff --git a/frontend/app/src/main/java/com/example/frontend/MainActivity.kt b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt index 313132d7..174151cd 100644 --- a/frontend/app/src/main/java/com/example/frontend/MainActivity.kt +++ b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt @@ -41,6 +41,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.example.frontend.ui.component.BottomBar import com.example.frontend.ui.component.MapWithMarker import com.example.frontend.ui.theme.FrontendTheme +import com.example.frontend.utilities.SNU_POLYGON import com.example.frontend.viewmodel.FriendsViewModel import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationCallback @@ -248,19 +249,13 @@ fun FriendsMapUI(currentLocation: LatLng?, onClick: () -> Unit) { .fillMaxSize(), contentAlignment = Alignment.BottomEnd ) { - MapWithMarker(currentLocation, friendsList) + MapWithMarker(currentLocation, friendsList, SNU_POLYGON) FloatingActionButton( onClick = { onClick() }, modifier = Modifier.padding(16.dp) ) { Icon(Icons.Filled.Add, contentDescription = null) } - } - } - - } - - diff --git a/frontend/app/src/main/java/com/example/frontend/ui/component/MapUI.kt b/frontend/app/src/main/java/com/example/frontend/ui/component/MapUI.kt index bbe55060..303e4a2f 100644 --- a/frontend/app/src/main/java/com/example/frontend/ui/component/MapUI.kt +++ b/frontend/app/src/main/java/com/example/frontend/ui/component/MapUI.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import com.example.frontend.model.UserWithLocationModel import com.example.frontend.ui.theme.FrontendTheme @@ -14,13 +15,15 @@ import com.google.android.gms.maps.model.LatLng import com.google.maps.android.compose.GoogleMap import com.google.maps.android.compose.Marker import com.google.maps.android.compose.MarkerState +import com.google.maps.android.compose.Polygon import com.google.maps.android.compose.rememberCameraPositionState import kotlin.random.Random @Composable fun MapWithMarker( currentLocation: LatLng?, - friends: List + friends: List, + polygon: List? = null ) { Box( modifier = Modifier @@ -41,6 +44,13 @@ fun MapWithMarker( snippet = "You are here" ) + polygon?.let { locations -> + Polygon( + points = locations, + fillColor = Color(0x89CFF0FF) + ) + } + friends.forEach { buildMarkerIcon(it) } } } diff --git a/frontend/app/src/main/java/com/example/frontend/utilities/Location.kt b/frontend/app/src/main/java/com/example/frontend/utilities/Location.kt new file mode 100644 index 00000000..d2035967 --- /dev/null +++ b/frontend/app/src/main/java/com/example/frontend/utilities/Location.kt @@ -0,0 +1,22 @@ +package com.example.frontend.utilities + +import com.google.android.gms.maps.model.LatLng + +/* + * 서울대 폴리곤모양을 적어놓은 것 + */ +val SNU_POLYGON = listOf( + LatLng(37.469020, 126.952321), + LatLng(37.467113, 126.947597), + LatLng(37.461482, 126.948941), + LatLng(37.459540, 126.947481), + LatLng(37.455836, 126.948220), + LatLng(37.450913, 126.949656), + LatLng(37.447540, 126.949270), + LatLng(37.447097, 126.951417), + LatLng(37.453400, 126.953478), + LatLng(37.457326, 126.956584), + LatLng(37.462478, 126.959963), + LatLng(37.467095, 126.960976), + LatLng(37.468567, 126.957310), +) From d714ec67f8f04263bea9121c6654d76d0397ded4 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 03:54:03 +0900 Subject: [PATCH 03/24] Move FriendsMapUI --- .../java/com/example/frontend/MainActivity.kt | 59 +---------------- .../example/frontend/ui/map/FriendsMapUI.kt | 65 +++++++++++++++++++ 2 files changed, 66 insertions(+), 58 deletions(-) create mode 100644 frontend/app/src/main/java/com/example/frontend/ui/map/FriendsMapUI.kt diff --git a/frontend/app/src/main/java/com/example/frontend/MainActivity.kt b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt index 174151cd..e7da18e8 100644 --- a/frontend/app/src/main/java/com/example/frontend/MainActivity.kt +++ b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt @@ -10,39 +10,20 @@ import android.os.Bundle import android.provider.Settings import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Add import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button -import androidx.compose.material3.FloatingActionButton -import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.SnackbarHost -import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue -import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat -import androidx.lifecycle.viewmodel.compose.viewModel -import com.example.frontend.ui.component.BottomBar -import com.example.frontend.ui.component.MapWithMarker +import com.example.frontend.ui.map.FriendsMapUI import com.example.frontend.ui.theme.FrontendTheme -import com.example.frontend.utilities.SNU_POLYGON -import com.example.frontend.viewmodel.FriendsViewModel import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationCallback import com.google.android.gms.location.LocationRequest @@ -50,8 +31,6 @@ import com.google.android.gms.location.LocationResult import com.google.android.gms.location.LocationServices import com.google.android.gms.maps.model.LatLng import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.delay -import kotlinx.coroutines.isActive @AndroidEntryPoint @@ -223,39 +202,3 @@ class MainActivity : ComponentActivity() { } } -@Composable -fun FriendsMapUI(currentLocation: LatLng?, onClick: () -> Unit) { - val viewModel: FriendsViewModel = viewModel() - val friendsList by viewModel.friendsList.observeAsState(emptyList()) - val snackbarHostState = remember { SnackbarHostState() } - LaunchedEffect(Unit) { - while (isActive) { - viewModel.fetchFriends() - delay(3000) - } - } - - Scaffold( - snackbarHost = { - SnackbarHost(hostState = snackbarHostState) - }, - bottomBar = { - BottomBar(currentLocation) - } - ) { paddingValues -> - Box( - modifier = Modifier - .padding(paddingValues) - .fillMaxSize(), - contentAlignment = Alignment.BottomEnd - ) { - MapWithMarker(currentLocation, friendsList, SNU_POLYGON) - FloatingActionButton( - onClick = { onClick() }, - modifier = Modifier.padding(16.dp) - ) { - Icon(Icons.Filled.Add, contentDescription = null) - } - } - } -} diff --git a/frontend/app/src/main/java/com/example/frontend/ui/map/FriendsMapUI.kt b/frontend/app/src/main/java/com/example/frontend/ui/map/FriendsMapUI.kt new file mode 100644 index 00000000..3e5ac574 --- /dev/null +++ b/frontend/app/src/main/java/com/example/frontend/ui/map/FriendsMapUI.kt @@ -0,0 +1,65 @@ +package com.example.frontend.ui.map + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add +import androidx.compose.material3.FloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.example.frontend.ui.component.BottomBar +import com.example.frontend.ui.component.MapWithMarker +import com.example.frontend.utilities.SNU_POLYGON +import com.example.frontend.viewmodel.FriendsViewModel +import com.google.android.gms.maps.model.LatLng +import kotlinx.coroutines.delay +import kotlinx.coroutines.isActive + +@Composable +fun FriendsMapUI(currentLocation: LatLng?, onClick: () -> Unit) { + val viewModel: FriendsViewModel = viewModel() + val friendsList by viewModel.friendsList.observeAsState(emptyList()) + val snackbarHostState = remember { SnackbarHostState() } + LaunchedEffect(Unit) { + while (isActive) { + viewModel.fetchFriends() + delay(3000) + } + } + + Scaffold( + snackbarHost = { + SnackbarHost(hostState = snackbarHostState) + }, + bottomBar = { + BottomBar(currentLocation) + } + ) { paddingValues -> + Box( + modifier = Modifier + .padding(paddingValues) + .fillMaxSize(), + contentAlignment = Alignment.BottomEnd + ) { + MapWithMarker(currentLocation, friendsList, SNU_POLYGON) + FloatingActionButton( + onClick = { onClick() }, + modifier = Modifier.padding(16.dp) + ) { + Icon(Icons.Filled.Add, contentDescription = null) + } + } + } +} From dbf9015b35fbc56391a6c5b35634323de21508d9 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 03:57:37 +0900 Subject: [PATCH 04/24] Add CheckInModel --- .../example/frontend/api/CheckInService.kt | 38 +++++++++++++++++++ .../example/frontend/model/CheckInModel.kt | 6 +++ 2 files changed, 44 insertions(+) create mode 100644 frontend/app/src/main/java/com/example/frontend/api/CheckInService.kt create mode 100644 frontend/app/src/main/java/com/example/frontend/model/CheckInModel.kt diff --git a/frontend/app/src/main/java/com/example/frontend/api/CheckInService.kt b/frontend/app/src/main/java/com/example/frontend/api/CheckInService.kt new file mode 100644 index 00000000..4de8f05e --- /dev/null +++ b/frontend/app/src/main/java/com/example/frontend/api/CheckInService.kt @@ -0,0 +1,38 @@ +package com.example.frontend.api + +import com.example.frontend.model.CheckInModel +import com.example.frontend.utilities.BASE_URL +import com.example.frontend.utilities.GsonProvider +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Call +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.http.Body +import retrofit2.http.POST + +/** + * Used to connect to the server + * About check in domain + */ +interface CheckInService { + @POST("/check_ins") + fun login(@Body checkInModel: CheckInModel): Call? + + companion object { + fun create(): CheckInService { + val logger = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BASIC } + + val client = OkHttpClient.Builder() + .addInterceptor(logger) + .build() + + return Retrofit.Builder() + .baseUrl(BASE_URL) + .client(client) + .addConverterFactory(GsonConverterFactory.create(GsonProvider.gson)) + .build() + .create(CheckInService::class.java) + } + } +} diff --git a/frontend/app/src/main/java/com/example/frontend/model/CheckInModel.kt b/frontend/app/src/main/java/com/example/frontend/model/CheckInModel.kt new file mode 100644 index 00000000..c1d6bb59 --- /dev/null +++ b/frontend/app/src/main/java/com/example/frontend/model/CheckInModel.kt @@ -0,0 +1,6 @@ +package com.example.frontend.model + +data class CheckInModel( + val latitude: Double, + val longitude: Double, +) From 686b83350dda8929df742188314ebb3158be7feb Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 04:13:33 +0900 Subject: [PATCH 05/24] Add CheckInUseCase --- .../example/frontend/api/CheckInService.kt | 5 ++- .../frontend/usecase/CheckInUseCase.kt | 31 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 frontend/app/src/main/java/com/example/frontend/usecase/CheckInUseCase.kt diff --git a/frontend/app/src/main/java/com/example/frontend/api/CheckInService.kt b/frontend/app/src/main/java/com/example/frontend/api/CheckInService.kt index 4de8f05e..d7f01a5f 100644 --- a/frontend/app/src/main/java/com/example/frontend/api/CheckInService.kt +++ b/frontend/app/src/main/java/com/example/frontend/api/CheckInService.kt @@ -1,5 +1,7 @@ package com.example.frontend.api +import android.content.Context +import com.example.frontend.interceptor.AuthInterceptor import com.example.frontend.model.CheckInModel import com.example.frontend.utilities.BASE_URL import com.example.frontend.utilities.GsonProvider @@ -20,11 +22,12 @@ interface CheckInService { fun login(@Body checkInModel: CheckInModel): Call? companion object { - fun create(): CheckInService { + fun create(context: Context): CheckInService { val logger = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BASIC } val client = OkHttpClient.Builder() .addInterceptor(logger) + .addInterceptor(AuthInterceptor(context)) .build() return Retrofit.Builder() diff --git a/frontend/app/src/main/java/com/example/frontend/usecase/CheckInUseCase.kt b/frontend/app/src/main/java/com/example/frontend/usecase/CheckInUseCase.kt new file mode 100644 index 00000000..6f3862d4 --- /dev/null +++ b/frontend/app/src/main/java/com/example/frontend/usecase/CheckInUseCase.kt @@ -0,0 +1,31 @@ +package com.example.frontend.usecase + +import android.content.Context +import android.util.Log +import com.example.frontend.api.CheckInService +import com.example.frontend.model.CheckInModel +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class CheckInUseCase(context: Context) { + private val checkInService = CheckInService.create(context) + + fun execute(latitude: Double, longitude: Double) { + val checkInModel = CheckInModel(latitude, longitude) + checkInService.login(checkInModel)?.enqueue(object : Callback { + override fun onResponse(call: Call, response: Response) { + if (response.isSuccessful) { + val body = response.body() + Log.d("CheckInUseCase", "Check in successful: $body") + } else { + Log.d("CheckInUseCase", "Check in failed: ${response.message()}") + } + } + + override fun onFailure(call: Call, t: Throwable) { + Log.d("CheckInUseCase", "Check in failed: ${t.message}") + } + }) + } +} From 287f514c496e2c4122e2ae975f800ba827c67053 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 04:13:44 +0900 Subject: [PATCH 06/24] Add Location --- .../src/main/java/com/example/frontend/utilities/Location.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/app/src/main/java/com/example/frontend/utilities/Location.kt b/frontend/app/src/main/java/com/example/frontend/utilities/Location.kt index d2035967..3856a635 100644 --- a/frontend/app/src/main/java/com/example/frontend/utilities/Location.kt +++ b/frontend/app/src/main/java/com/example/frontend/utilities/Location.kt @@ -20,3 +20,5 @@ val SNU_POLYGON = listOf( LatLng(37.467095, 126.960976), LatLng(37.468567, 126.957310), ) + +val BUILDING_302 = LatLng(37.466967, 126.950302) From f18652ea5874328978a70d9fc17e062e3af9dbf0 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 04:14:03 +0900 Subject: [PATCH 07/24] Add debuging --- .../frontend/ui/settings/UserInfoActivity.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/frontend/app/src/main/java/com/example/frontend/ui/settings/UserInfoActivity.kt b/frontend/app/src/main/java/com/example/frontend/ui/settings/UserInfoActivity.kt index d20962d7..3867b04d 100644 --- a/frontend/app/src/main/java/com/example/frontend/ui/settings/UserInfoActivity.kt +++ b/frontend/app/src/main/java/com/example/frontend/ui/settings/UserInfoActivity.kt @@ -58,7 +58,9 @@ import com.example.frontend.ui.component.MyTopAppBar import com.example.frontend.ui.login.LoginActivity import com.example.frontend.ui.settings.component.MissionCard import com.example.frontend.ui.theme.FrontendTheme +import com.example.frontend.usecase.CheckInUseCase import com.example.frontend.usecase.LogOutUseCase +import com.example.frontend.utilities.BUILDING_302 class UserInfoActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -258,6 +260,17 @@ fun UserInfoUI(name: String, modifier: Modifier = Modifier) { } } ) + + // TODO(heka1024): remove this button + CustomButton( + buttonText = "수동 체크인 (디버깅)", + modifier = Modifier + .fillMaxWidth() + .padding(top = 30.dp), + onClickHandler = { + CheckInUseCase(context).execute(BUILDING_302.latitude, BUILDING_302.longitude) + } + ) } } } From 7d74c7fce3310213e1089fe43626db18d8ef87f9 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 05:13:32 +0900 Subject: [PATCH 08/24] =?UTF-8?q?=EC=B2=B4=ED=81=AC=EC=9D=B8=20=EC=88=98?= =?UTF-8?q?=ED=96=89=20=EC=9C=A0=EC=A6=88=EC=BC=80=EC=9D=B4=EC=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/frontend/usecase/CheckInUseCase.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/frontend/app/src/main/java/com/example/frontend/usecase/CheckInUseCase.kt b/frontend/app/src/main/java/com/example/frontend/usecase/CheckInUseCase.kt index 6f3862d4..ba2ab379 100644 --- a/frontend/app/src/main/java/com/example/frontend/usecase/CheckInUseCase.kt +++ b/frontend/app/src/main/java/com/example/frontend/usecase/CheckInUseCase.kt @@ -8,7 +8,12 @@ import retrofit2.Call import retrofit2.Callback import retrofit2.Response -class CheckInUseCase(context: Context) { +/* + * 체크인을 수행하는 메서드 + */ +class CheckInUseCase( + context: Context +) { private val checkInService = CheckInService.create(context) fun execute(latitude: Double, longitude: Double) { From df3cf72444313ffd26d5bcafeab5c3f0a7ed4c25 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 05:25:20 +0900 Subject: [PATCH 09/24] Refactor using hilt --- .../java/com/example/frontend/MainActivity.kt | 12 ++++++--- .../com/example/frontend/di/LocationModule.kt | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 frontend/app/src/main/java/com/example/frontend/di/LocationModule.kt diff --git a/frontend/app/src/main/java/com/example/frontend/MainActivity.kt b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt index e7da18e8..ca7764b9 100644 --- a/frontend/app/src/main/java/com/example/frontend/MainActivity.kt +++ b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt @@ -24,18 +24,20 @@ import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import com.example.frontend.ui.map.FriendsMapUI import com.example.frontend.ui.theme.FrontendTheme +import com.example.frontend.usecase.CheckInUseCase import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationCallback import com.google.android.gms.location.LocationRequest import com.google.android.gms.location.LocationResult -import com.google.android.gms.location.LocationServices import com.google.android.gms.maps.model.LatLng import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject @AndroidEntryPoint class MainActivity : ComponentActivity() { - private lateinit var fusedLocationClient: FusedLocationProviderClient + @Inject + lateinit var fusedLocationClient: FusedLocationProviderClient var currentLocation by mutableStateOf(null) private fun hasBackgroundLocationPermission(context: Context): Boolean { @@ -88,7 +90,6 @@ class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - fusedLocationClient = LocationServices.getFusedLocationProviderClient(this) setContent { FrontendTheme { @@ -107,11 +108,14 @@ class MainActivity : ComponentActivity() { } checkAndRequestLocationPermissions() + + currentLocation?.let { + CheckInUseCase(this).execute(it.latitude, it.longitude) + } } override fun onResume() { super.onResume() - fusedLocationClient = LocationServices.getFusedLocationProviderClient(this) setContent { FrontendTheme { diff --git a/frontend/app/src/main/java/com/example/frontend/di/LocationModule.kt b/frontend/app/src/main/java/com/example/frontend/di/LocationModule.kt new file mode 100644 index 00000000..cd242dc7 --- /dev/null +++ b/frontend/app/src/main/java/com/example/frontend/di/LocationModule.kt @@ -0,0 +1,26 @@ +package com.example.frontend.di + +import android.content.Context +import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationServices +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + + +/* + * 지리정보 관련 데이터를 제공하는 모듈 + */ +@Module +@InstallIn(SingletonComponent::class) +object LocationModule { + + @Provides + @Singleton + fun provideFusedLocationProviderClient(@ApplicationContext context: Context): FusedLocationProviderClient { + return LocationServices.getFusedLocationProviderClient(context) + } +} From a6f28a6a2dba23d1ce4714ae7667627bab1f5eb9 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 05:28:15 +0900 Subject: [PATCH 10/24] Disable zoom setting --- .../src/main/java/com/example/frontend/ui/component/MapUI.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/app/src/main/java/com/example/frontend/ui/component/MapUI.kt b/frontend/app/src/main/java/com/example/frontend/ui/component/MapUI.kt index 303e4a2f..c758592d 100644 --- a/frontend/app/src/main/java/com/example/frontend/ui/component/MapUI.kt +++ b/frontend/app/src/main/java/com/example/frontend/ui/component/MapUI.kt @@ -13,6 +13,7 @@ import com.google.android.gms.maps.model.BitmapDescriptorFactory import com.google.android.gms.maps.model.CameraPosition import com.google.android.gms.maps.model.LatLng import com.google.maps.android.compose.GoogleMap +import com.google.maps.android.compose.MapUiSettings import com.google.maps.android.compose.Marker import com.google.maps.android.compose.MarkerState import com.google.maps.android.compose.Polygon @@ -36,7 +37,8 @@ fun MapWithMarker( GoogleMap( modifier = Modifier.fillMaxSize(), - cameraPositionState = cameraPositionState + cameraPositionState = cameraPositionState, + uiSettings = MapUiSettings(zoomControlsEnabled = false) ) { Marker( state = MarkerState(position = location), From 435f0c15e570af2f828226663407793c10a3eec2 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 05:30:52 +0900 Subject: [PATCH 11/24] Add lib --- frontend/app/build.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/app/build.gradle.kts b/frontend/app/build.gradle.kts index f0d6aa0f..557166b5 100644 --- a/frontend/app/build.gradle.kts +++ b/frontend/app/build.gradle.kts @@ -73,6 +73,10 @@ dependencies { implementation("androidx.test.ext:junit-ktx:1.1.5") implementation("androidx.compose.foundation:foundation-layout-android:1.5.4") implementation("io.coil-kt:coil-compose:2.5.0") + + implementation("androidx.work:work-runtime-ktx:2.8.0") + androidTestImplementation("androidx.work:work-testing:2.8.0") + testImplementation("junit:junit:4.13.2") testImplementation("org.mockito:mockito-core:4.11.0") testImplementation("org.junit.jupiter:junit-jupiter:5.8.1") From 8fd766612f33c71f8bd8b414261b2b16d029ff4d Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 08:40:43 +0900 Subject: [PATCH 12/24] Inject --- .../app/src/main/java/com/example/frontend/MainActivity.kt | 5 ++++- .../java/com/example/frontend/usecase/CheckInUseCase.kt | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/frontend/app/src/main/java/com/example/frontend/MainActivity.kt b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt index ca7764b9..2fa058d5 100644 --- a/frontend/app/src/main/java/com/example/frontend/MainActivity.kt +++ b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt @@ -40,6 +40,9 @@ class MainActivity : ComponentActivity() { lateinit var fusedLocationClient: FusedLocationProviderClient var currentLocation by mutableStateOf(null) + @Inject + lateinit var checkInUseCase: CheckInUseCase + private fun hasBackgroundLocationPermission(context: Context): Boolean { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ContextCompat.checkSelfPermission( @@ -110,7 +113,7 @@ class MainActivity : ComponentActivity() { checkAndRequestLocationPermissions() currentLocation?.let { - CheckInUseCase(this).execute(it.latitude, it.longitude) + checkInUseCase.execute(it.latitude, it.longitude) } } diff --git a/frontend/app/src/main/java/com/example/frontend/usecase/CheckInUseCase.kt b/frontend/app/src/main/java/com/example/frontend/usecase/CheckInUseCase.kt index ba2ab379..f6e8df1f 100644 --- a/frontend/app/src/main/java/com/example/frontend/usecase/CheckInUseCase.kt +++ b/frontend/app/src/main/java/com/example/frontend/usecase/CheckInUseCase.kt @@ -4,15 +4,17 @@ import android.content.Context import android.util.Log import com.example.frontend.api.CheckInService import com.example.frontend.model.CheckInModel +import dagger.hilt.android.qualifiers.ApplicationContext import retrofit2.Call import retrofit2.Callback import retrofit2.Response +import javax.inject.Inject /* * 체크인을 수행하는 메서드 */ -class CheckInUseCase( - context: Context +class CheckInUseCase @Inject constructor( + @ApplicationContext context: Context ) { private val checkInService = CheckInService.create(context) From 03539228b003e4890c61d1b122d25d7dfa569d4c Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 08:56:24 +0900 Subject: [PATCH 13/24] =?UTF-8?q?=EC=B2=B4=ED=81=AC=EC=9D=B8=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontend/ui/settings/UserInfoActivity.kt | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/frontend/app/src/main/java/com/example/frontend/ui/settings/UserInfoActivity.kt b/frontend/app/src/main/java/com/example/frontend/ui/settings/UserInfoActivity.kt index 3867b04d..d20962d7 100644 --- a/frontend/app/src/main/java/com/example/frontend/ui/settings/UserInfoActivity.kt +++ b/frontend/app/src/main/java/com/example/frontend/ui/settings/UserInfoActivity.kt @@ -58,9 +58,7 @@ import com.example.frontend.ui.component.MyTopAppBar import com.example.frontend.ui.login.LoginActivity import com.example.frontend.ui.settings.component.MissionCard import com.example.frontend.ui.theme.FrontendTheme -import com.example.frontend.usecase.CheckInUseCase import com.example.frontend.usecase.LogOutUseCase -import com.example.frontend.utilities.BUILDING_302 class UserInfoActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -260,17 +258,6 @@ fun UserInfoUI(name: String, modifier: Modifier = Modifier) { } } ) - - // TODO(heka1024): remove this button - CustomButton( - buttonText = "수동 체크인 (디버깅)", - modifier = Modifier - .fillMaxWidth() - .padding(top = 30.dp), - onClickHandler = { - CheckInUseCase(context).execute(BUILDING_302.latitude, BUILDING_302.longitude) - } - ) } } } From c8b2fab602440d320ad540a2a7c59473a5692e75 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 08:56:37 +0900 Subject: [PATCH 14/24] =?UTF-8?q?=EB=82=B4=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=96=BB=EC=96=B4=EC=98=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/example/frontend/api/UserService.kt | 5 ++++- .../java/com/example/frontend/repository/UsersRepository.kt | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/frontend/app/src/main/java/com/example/frontend/api/UserService.kt b/frontend/app/src/main/java/com/example/frontend/api/UserService.kt index 73935121..83c03373 100644 --- a/frontend/app/src/main/java/com/example/frontend/api/UserService.kt +++ b/frontend/app/src/main/java/com/example/frontend/api/UserService.kt @@ -11,6 +11,9 @@ interface UserService { @GET("/users") suspend fun getAllUsers(): List + @GET("/users/me") + suspend fun getMyInfo(): UserModel + @GET("/friends") suspend fun getAllFriends(): List @@ -22,4 +25,4 @@ interface UserService { @POST("/friends/{id}/confirm") suspend fun confirmRequest(@Path("id") friendId: Long) -} \ No newline at end of file +} diff --git a/frontend/app/src/main/java/com/example/frontend/repository/UsersRepository.kt b/frontend/app/src/main/java/com/example/frontend/repository/UsersRepository.kt index 6c357a04..8cc27440 100644 --- a/frontend/app/src/main/java/com/example/frontend/repository/UsersRepository.kt +++ b/frontend/app/src/main/java/com/example/frontend/repository/UsersRepository.kt @@ -10,6 +10,10 @@ class UsersRepository @Inject constructor(private val userService: UserService) return userService.getAllUsers() } + suspend fun getMyInfo(): UserModel { + return userService.getMyInfo() + } + suspend fun getFriends(): List { return userService.getAllFriends() } From d861787ef148a0deacc2850cc30b8b43ae54572d Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 08:56:45 +0900 Subject: [PATCH 15/24] =?UTF-8?q?UserID=20=EC=A0=80=EC=9E=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/frontend/repository/UserContextRepository.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/app/src/main/java/com/example/frontend/repository/UserContextRepository.kt b/frontend/app/src/main/java/com/example/frontend/repository/UserContextRepository.kt index 194c83b4..7eeb6964 100644 --- a/frontend/app/src/main/java/com/example/frontend/repository/UserContextRepository.kt +++ b/frontend/app/src/main/java/com/example/frontend/repository/UserContextRepository.kt @@ -52,6 +52,14 @@ class UserContextRepository( return store.getBoolean(IS_LOGGED_IN) ?: false } + fun getUserId(): Int? { + return store.getInt(USER_ID) + } + + fun saveUserId(userId: Int) { + store.putInt(USER_ID, userId) + } + fun clear() { store.clear() } @@ -75,5 +83,6 @@ class UserContextRepository( private const val AUTH_TOKEN = "AUTH_TOKEN" private const val SELECTED_PREDEFINED_IMAGE = "SELECTED_PREDEFINED_IMAGE" private const val IS_LOGGED_IN = "IS_LOGGED_IN" + private const val USER_ID = "USER_ID" } } From 81aa8a56489d0f482c063a67f1daaabec2353c0b Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 08:56:55 +0900 Subject: [PATCH 16/24] =?UTF-8?q?UseCase=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/frontend/MainActivity.kt | 10 +++++++++ .../frontend/usecase/SaveMyInfoUseCase.kt | 22 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 frontend/app/src/main/java/com/example/frontend/usecase/SaveMyInfoUseCase.kt diff --git a/frontend/app/src/main/java/com/example/frontend/MainActivity.kt b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt index 2fa058d5..8c22e394 100644 --- a/frontend/app/src/main/java/com/example/frontend/MainActivity.kt +++ b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt @@ -22,15 +22,18 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat +import androidx.lifecycle.lifecycleScope import com.example.frontend.ui.map.FriendsMapUI import com.example.frontend.ui.theme.FrontendTheme import com.example.frontend.usecase.CheckInUseCase +import com.example.frontend.usecase.SaveMyInfoUseCase import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationCallback import com.google.android.gms.location.LocationRequest import com.google.android.gms.location.LocationResult import com.google.android.gms.maps.model.LatLng import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch import javax.inject.Inject @@ -43,6 +46,9 @@ class MainActivity : ComponentActivity() { @Inject lateinit var checkInUseCase: CheckInUseCase + @Inject + lateinit var saveMyInfoUseCase: SaveMyInfoUseCase + private fun hasBackgroundLocationPermission(context: Context): Boolean { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ContextCompat.checkSelfPermission( @@ -115,6 +121,10 @@ class MainActivity : ComponentActivity() { currentLocation?.let { checkInUseCase.execute(it.latitude, it.longitude) } + + lifecycleScope.launch { + saveMyInfoUseCase.execute() + } } override fun onResume() { diff --git a/frontend/app/src/main/java/com/example/frontend/usecase/SaveMyInfoUseCase.kt b/frontend/app/src/main/java/com/example/frontend/usecase/SaveMyInfoUseCase.kt new file mode 100644 index 00000000..5b4648ad --- /dev/null +++ b/frontend/app/src/main/java/com/example/frontend/usecase/SaveMyInfoUseCase.kt @@ -0,0 +1,22 @@ +package com.example.frontend.usecase + +import android.content.Context +import com.example.frontend.repository.UserContextRepository +import com.example.frontend.repository.UsersRepository +import dagger.hilt.android.qualifiers.ApplicationContext +import javax.inject.Inject + +class SaveMyInfoUseCase @Inject constructor( + private val repository: UsersRepository, + @ApplicationContext context: Context +) { + private val userContextRepository = UserContextRepository.ofContext(context) + + suspend fun execute() { + repository.getMyInfo().apply { + userContextRepository.saveUserName(name) + userContextRepository.saveUserMail(email) + userContextRepository.saveUserId(id.toInt()) + } + } +} From ee0174df5d8ecdf548684b47272f50eba90323a4 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 08:58:10 +0900 Subject: [PATCH 17/24] Move appmodule --- .../java/com/example/frontend/di/AppModule.kt | 52 +++++++++++++++++++ .../frontend/repository/FriendsRepository.kt | 48 ----------------- 2 files changed, 52 insertions(+), 48 deletions(-) create mode 100644 frontend/app/src/main/java/com/example/frontend/di/AppModule.kt diff --git a/frontend/app/src/main/java/com/example/frontend/di/AppModule.kt b/frontend/app/src/main/java/com/example/frontend/di/AppModule.kt new file mode 100644 index 00000000..0117efcb --- /dev/null +++ b/frontend/app/src/main/java/com/example/frontend/di/AppModule.kt @@ -0,0 +1,52 @@ +package com.example.frontend.di + +import android.content.Context +import com.example.frontend.api.FriendService +import com.example.frontend.api.UserService +import com.example.frontend.interceptor.AuthInterceptor +import com.example.frontend.repository.FriendsRepository +import com.example.frontend.utilities.BASE_URL +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import okhttp3.OkHttpClient +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +@Module +@InstallIn(SingletonComponent::class) +object AppModule { + + @Provides + fun provideRetrofit(@ApplicationContext context: Context): Retrofit { + val authInterceptor = AuthInterceptor(context) + + val okHttpClient = OkHttpClient.Builder() + .addInterceptor(authInterceptor) + .build() + + return Retrofit.Builder() + .baseUrl(BASE_URL) + .client(okHttpClient) + .addConverterFactory(GsonConverterFactory.create()) + .build() + } + + @Provides + fun provideFriendsRepository(api: FriendService): FriendsRepository { + return FriendsRepository(api) + } + + @Provides + fun provideFriendAPI(retrofit: Retrofit): FriendService { + return retrofit.create(FriendService::class.java) + } + + @Provides + fun provideUserService(retrofit: Retrofit): UserService { + return retrofit.create(UserService::class.java) + } + +} diff --git a/frontend/app/src/main/java/com/example/frontend/repository/FriendsRepository.kt b/frontend/app/src/main/java/com/example/frontend/repository/FriendsRepository.kt index 4a316374..78614bc2 100644 --- a/frontend/app/src/main/java/com/example/frontend/repository/FriendsRepository.kt +++ b/frontend/app/src/main/java/com/example/frontend/repository/FriendsRepository.kt @@ -1,23 +1,11 @@ package com.example.frontend.repository -import android.content.Context import com.example.frontend.api.FriendService -import com.example.frontend.api.UserService import com.example.frontend.callback.FriendLocationCallback -import com.example.frontend.interceptor.AuthInterceptor import com.example.frontend.model.UserWithLocationModel -import com.example.frontend.utilities.BASE_URL -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import okhttp3.OkHttpClient import retrofit2.Call import retrofit2.Callback import retrofit2.Response -import retrofit2.Retrofit -import retrofit2.converter.gson.GsonConverterFactory class FriendsRepository(private val friendService: FriendService) { @@ -43,39 +31,3 @@ class FriendsRepository(private val friendService: FriendService) { }) } } - -@Module -@InstallIn(SingletonComponent::class) -object AppModule { - - @Provides - fun provideRetrofit(@ApplicationContext context: Context): Retrofit { - val authInterceptor = AuthInterceptor(context) - - val okHttpClient = OkHttpClient.Builder() - .addInterceptor(authInterceptor) - .build() - - return Retrofit.Builder() - .baseUrl(BASE_URL) - .client(okHttpClient) - .addConverterFactory(GsonConverterFactory.create()) - .build() - } - - @Provides - fun provideFriendsRepository(api: FriendService): FriendsRepository { - return FriendsRepository(api) - } - - @Provides - fun provideFriendAPI(retrofit: Retrofit): FriendService { - return retrofit.create(FriendService::class.java) - } - - @Provides - fun provideUserService(retrofit: Retrofit): UserService { - return retrofit.create(UserService::class.java) - } - -} From e04e81eab2b1a547ed7626ceaccabaec0bbe198c Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 08:58:35 +0900 Subject: [PATCH 18/24] Add log --- .../java/com/example/frontend/usecase/SaveMyInfoUseCase.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/app/src/main/java/com/example/frontend/usecase/SaveMyInfoUseCase.kt b/frontend/app/src/main/java/com/example/frontend/usecase/SaveMyInfoUseCase.kt index 5b4648ad..14c0c380 100644 --- a/frontend/app/src/main/java/com/example/frontend/usecase/SaveMyInfoUseCase.kt +++ b/frontend/app/src/main/java/com/example/frontend/usecase/SaveMyInfoUseCase.kt @@ -1,6 +1,7 @@ package com.example.frontend.usecase import android.content.Context +import android.util.Log import com.example.frontend.repository.UserContextRepository import com.example.frontend.repository.UsersRepository import dagger.hilt.android.qualifiers.ApplicationContext @@ -13,6 +14,8 @@ class SaveMyInfoUseCase @Inject constructor( private val userContextRepository = UserContextRepository.ofContext(context) suspend fun execute() { + Log.i("SaveMyInfoUseCase", "execute") + repository.getMyInfo().apply { userContextRepository.saveUserName(name) userContextRepository.saveUserMail(email) From 2630023f8b429c6fb389339d329fd83be14f27b0 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 09:09:04 +0900 Subject: [PATCH 19/24] Add doc --- .../java/com/example/frontend/usecase/SaveMyInfoUseCase.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/frontend/app/src/main/java/com/example/frontend/usecase/SaveMyInfoUseCase.kt b/frontend/app/src/main/java/com/example/frontend/usecase/SaveMyInfoUseCase.kt index 14c0c380..7757caed 100644 --- a/frontend/app/src/main/java/com/example/frontend/usecase/SaveMyInfoUseCase.kt +++ b/frontend/app/src/main/java/com/example/frontend/usecase/SaveMyInfoUseCase.kt @@ -7,6 +7,9 @@ import com.example.frontend.repository.UsersRepository import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject +/* + * users/me API를 바탕으로 사용자 정보를 저장하는 UseCase + */ class SaveMyInfoUseCase @Inject constructor( private val repository: UsersRepository, @ApplicationContext context: Context From 0413655537569931e485e46281326d6207b53fd2 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 09:14:18 +0900 Subject: [PATCH 20/24] =?UTF-8?q?=ED=95=84=EC=9A=94=20=EC=97=86=EB=8A=94?= =?UTF-8?q?=20=EC=9D=B8=EC=9E=90=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../frontend/ui/component/BottomBar.kt | 19 +++++++++++-------- .../example/frontend/ui/map/FriendsMapUI.kt | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/frontend/app/src/main/java/com/example/frontend/ui/component/BottomBar.kt b/frontend/app/src/main/java/com/example/frontend/ui/component/BottomBar.kt index 36f1e4e6..41c9c78d 100644 --- a/frontend/app/src/main/java/com/example/frontend/ui/component/BottomBar.kt +++ b/frontend/app/src/main/java/com/example/frontend/ui/component/BottomBar.kt @@ -22,15 +22,14 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.example.frontend.MeetupActivity +import com.example.frontend.MainActivity import com.example.frontend.MeetupListUI import com.example.frontend.MissionActivity import com.example.frontend.ui.friend.FriendActivity import com.example.frontend.ui.settings.UserInfoActivity -import com.google.android.gms.maps.model.LatLng @Composable -fun BottomBar(currentLocation: LatLng?) { +fun BottomBar() { val context = LocalContext.current val icons = listOf( Icons.Default.Star, @@ -57,10 +56,14 @@ fun BottomBar(currentLocation: LatLng?) { IconToggleButton(icon = icon) { when (icon) { icons[0] -> { - // MeetUp 생성으로 이동 - val nextIntent = Intent(context, MeetupActivity::class.java) - nextIntent.putExtra("currentLocation", currentLocation) - context.startActivity(nextIntent) + // If current activity is MainActivity, do nothing + if (context.javaClass.simpleName == "MainActivity") { + return@IconToggleButton + } else { + // MainActivity 이동 + val nextIntent = Intent(context, MainActivity::class.java) + context.startActivity(nextIntent) + } } icons[1] -> { @@ -96,5 +99,5 @@ fun BottomBar(currentLocation: LatLng?) { @Composable @Preview private fun BottomBarPreview() { - BottomBar(null) + BottomBar() } diff --git a/frontend/app/src/main/java/com/example/frontend/ui/map/FriendsMapUI.kt b/frontend/app/src/main/java/com/example/frontend/ui/map/FriendsMapUI.kt index 3e5ac574..d5dcc140 100644 --- a/frontend/app/src/main/java/com/example/frontend/ui/map/FriendsMapUI.kt +++ b/frontend/app/src/main/java/com/example/frontend/ui/map/FriendsMapUI.kt @@ -44,7 +44,7 @@ fun FriendsMapUI(currentLocation: LatLng?, onClick: () -> Unit) { SnackbarHost(hostState = snackbarHostState) }, bottomBar = { - BottomBar(currentLocation) + BottomBar() } ) { paddingValues -> Box( From 7e8cabb8f0a1a9b54af850134759638b18f7823d Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 09:31:21 +0900 Subject: [PATCH 21/24] Add ProfileDialog --- .../example/frontend/ui/map/ProfileDialog.kt | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 frontend/app/src/main/java/com/example/frontend/ui/map/ProfileDialog.kt diff --git a/frontend/app/src/main/java/com/example/frontend/ui/map/ProfileDialog.kt b/frontend/app/src/main/java/com/example/frontend/ui/map/ProfileDialog.kt new file mode 100644 index 00000000..a5611244 --- /dev/null +++ b/frontend/app/src/main/java/com/example/frontend/ui/map/ProfileDialog.kt @@ -0,0 +1,87 @@ +package com.example.frontend.ui.map + +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.DialogProperties +import com.example.frontend.data.predefinedImages + +/* + * 유저의 프로필을 보여주는 Dialog + */ +@Composable +internal fun ProfileDialog( + title: String, + description: String, + onDismiss: () -> Unit = {}, + painter: Painter, +) { + return AlertDialog( + properties = DialogProperties(usePlatformDefaultWidth = false), + onDismissRequest = { onDismiss() }, + title = { + Row( + modifier = Modifier.padding(bottom = 16.dp), + verticalAlignment = Alignment.CenterVertically, + ) + { + Image( + painter = painter, + contentDescription = "Profile Image", + modifier = Modifier + .size(80.dp) + .clip(RoundedCornerShape(40.dp)) + ) + Text( + text = title, + style = MaterialTheme.typography.headlineLarge, + modifier = Modifier.padding(start = 16.dp), + ) + } + }, + text = { + HorizontalDivider() + Text( + text = description, + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.padding(vertical = 16.dp), + ) + }, + confirmButton = { + Text( + text = "닫기", + style = MaterialTheme.typography.labelLarge, + color = MaterialTheme.colorScheme.primary, + modifier = Modifier + .padding(horizontal = 8.dp) + .clickable { onDismiss() }, + ) + }, + ) +} + + +@Composable +@Preview +private fun ProfileDialogPreview() { + ProfileDialog( + title = "호에엥맨", + description = "큭큭", + painter = painterResource(id = predefinedImages[0]), + ) +} From c6214a0647a3a3bbd224eaefd5c8d6c0a1388826 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 10:06:43 +0900 Subject: [PATCH 22/24] Add resource --- frontend/app/build.gradle.kts | 2 ++ .../app/src/main/res/drawable/map_pin_svgrepo_com.xml | 9 +++++++++ frontend/app/src/main/res/drawable/white_circle.xml | 5 +++++ 3 files changed, 16 insertions(+) create mode 100644 frontend/app/src/main/res/drawable/map_pin_svgrepo_com.xml create mode 100644 frontend/app/src/main/res/drawable/white_circle.xml diff --git a/frontend/app/build.gradle.kts b/frontend/app/build.gradle.kts index 557166b5..df5b57eb 100644 --- a/frontend/app/build.gradle.kts +++ b/frontend/app/build.gradle.kts @@ -77,6 +77,8 @@ dependencies { implementation("androidx.work:work-runtime-ktx:2.8.0") androidTestImplementation("androidx.work:work-testing:2.8.0") + implementation("com.squareup.picasso:picasso:2.8") + testImplementation("junit:junit:4.13.2") testImplementation("org.mockito:mockito-core:4.11.0") testImplementation("org.junit.jupiter:junit-jupiter:5.8.1") diff --git a/frontend/app/src/main/res/drawable/map_pin_svgrepo_com.xml b/frontend/app/src/main/res/drawable/map_pin_svgrepo_com.xml new file mode 100644 index 00000000..90f1f34d --- /dev/null +++ b/frontend/app/src/main/res/drawable/map_pin_svgrepo_com.xml @@ -0,0 +1,9 @@ + + + diff --git a/frontend/app/src/main/res/drawable/white_circle.xml b/frontend/app/src/main/res/drawable/white_circle.xml new file mode 100644 index 00000000..522eb166 --- /dev/null +++ b/frontend/app/src/main/res/drawable/white_circle.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file From 78d567c6c654fd4306caa6009ef2760e9dc0a9f0 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 13:22:56 +0900 Subject: [PATCH 23/24] Update lib --- frontend/app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/app/build.gradle.kts b/frontend/app/build.gradle.kts index df5b57eb..f1b4305f 100644 --- a/frontend/app/build.gradle.kts +++ b/frontend/app/build.gradle.kts @@ -92,8 +92,8 @@ dependencies { androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.5.4") debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-test-manifest") - implementation("com.google.android.gms:play-services-location:17.0.0") - implementation("com.google.android.gms:play-services-maps:17.0.0") + implementation("com.google.android.gms:play-services-location:21.0.1") + implementation("com.google.android.gms:play-services-maps:18.2.0") implementation("com.google.maps.android:maps-compose:2.11.4") implementation("androidx.activity:activity-ktx:1.3.1") implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1") From ccbc2d6df6547c7faa3cae8be7ecc34a963baaa4 Mon Sep 17 00:00:00 2001 From: heka1024 Date: Thu, 7 Dec 2023 13:23:19 +0900 Subject: [PATCH 24/24] Add checkinjob --- .../java/com/example/frontend/MainActivity.kt | 5 +- .../usecase/PeriodicCheckInUseCase.kt | 46 +++++++++++++++++++ .../frontend/utilities/PeriodicTask.kt | 28 +++++++++++ frontend/settings.gradle.kts | 1 - 4 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 frontend/app/src/main/java/com/example/frontend/usecase/PeriodicCheckInUseCase.kt create mode 100644 frontend/app/src/main/java/com/example/frontend/utilities/PeriodicTask.kt diff --git a/frontend/app/src/main/java/com/example/frontend/MainActivity.kt b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt index 8c22e394..81fbe33d 100644 --- a/frontend/app/src/main/java/com/example/frontend/MainActivity.kt +++ b/frontend/app/src/main/java/com/example/frontend/MainActivity.kt @@ -26,6 +26,7 @@ import androidx.lifecycle.lifecycleScope import com.example.frontend.ui.map.FriendsMapUI import com.example.frontend.ui.theme.FrontendTheme import com.example.frontend.usecase.CheckInUseCase +import com.example.frontend.usecase.PeriodicCheckInUseCase import com.example.frontend.usecase.SaveMyInfoUseCase import com.google.android.gms.location.FusedLocationProviderClient import com.google.android.gms.location.LocationCallback @@ -118,9 +119,7 @@ class MainActivity : ComponentActivity() { checkAndRequestLocationPermissions() - currentLocation?.let { - checkInUseCase.execute(it.latitude, it.longitude) - } + PeriodicCheckInUseCase(this).execute() lifecycleScope.launch { saveMyInfoUseCase.execute() diff --git a/frontend/app/src/main/java/com/example/frontend/usecase/PeriodicCheckInUseCase.kt b/frontend/app/src/main/java/com/example/frontend/usecase/PeriodicCheckInUseCase.kt new file mode 100644 index 00000000..596f8625 --- /dev/null +++ b/frontend/app/src/main/java/com/example/frontend/usecase/PeriodicCheckInUseCase.kt @@ -0,0 +1,46 @@ +package com.example.frontend.usecase + +import android.Manifest +import android.content.Context +import android.content.pm.PackageManager +import android.util.Log +import androidx.core.app.ActivityCompat +import com.example.frontend.utilities.PeriodicTask +import com.google.android.gms.location.LocationServices +import com.google.android.gms.location.Priority + +class PeriodicCheckInUseCase(private val context: Context) { + private val checkInUseCase = CheckInUseCase(context) + private val locationClient = LocationServices.getFusedLocationProviderClient(context) + + fun execute() { + + PeriodicTask( + command = { recordLocation() }, + intervalInMinutes = INTERVAL_IN_MINUTES + ).execute() + } + + private fun recordLocation() { + Log.i(TAG, "execute recordLocation") + if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED + && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED + ) { + Log.e(TAG, "No location permission") + return + } + + locationClient.getCurrentLocation(PRIORITY, null).addOnSuccessListener { location -> + location?.let { + Log.i(TAG, "Location: $location") + checkInUseCase.execute(location.latitude, location.longitude) + } + } + } + + companion object { + private const val TAG = "PeriodicCheckInUseCase" + private const val PRIORITY = Priority.PRIORITY_HIGH_ACCURACY + private const val INTERVAL_IN_MINUTES = 5L + } +} diff --git a/frontend/app/src/main/java/com/example/frontend/utilities/PeriodicTask.kt b/frontend/app/src/main/java/com/example/frontend/utilities/PeriodicTask.kt new file mode 100644 index 00000000..669a18d2 --- /dev/null +++ b/frontend/app/src/main/java/com/example/frontend/utilities/PeriodicTask.kt @@ -0,0 +1,28 @@ +package com.example.frontend.utilities + +import android.os.Handler +import android.os.Looper +import android.util.Log +import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit + +/* + * Run a periodic task + */ +class PeriodicTask( + private val command: Runnable, + private val intervalInMinutes: Long = 5, +) { + + fun execute() { + Log.i("PeriodicTask", "execute") + + val service = Executors.newSingleThreadScheduledExecutor() + val handler = Handler(Looper.getMainLooper()) + service.scheduleAtFixedRate( + handler.run { command }, + 0, intervalInMinutes, TimeUnit.MINUTES + ) + } +} + diff --git a/frontend/settings.gradle.kts b/frontend/settings.gradle.kts index 08a0d6ae..9cee02fb 100644 --- a/frontend/settings.gradle.kts +++ b/frontend/settings.gradle.kts @@ -15,4 +15,3 @@ dependencyResolutionManagement { rootProject.name = "frontend" include(":app") - \ No newline at end of file