diff --git a/.gitignore b/.gitignore
index aa724b7..2cf9b31 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,4 @@
.externalNativeBuild
.cxx
local.properties
+/app/release
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index ae388c2..2437a51 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -12,6 +12,7 @@
+
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 51bc3be..a07a278 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -151,6 +151,10 @@ dependencies {
// DataStore
implementation("androidx.datastore:datastore-core:1.0.0")
+ // Maps
+ implementation(project(":maps"))
+
+
// SystemUIController
val accompanistVersion = "0.30.1"
implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion")
diff --git a/app/src/main/java/ai/travel/app/home/HomeViewModel.kt b/app/src/main/java/ai/travel/app/home/HomeViewModel.kt
index 8259197..645ec4c 100644
--- a/app/src/main/java/ai/travel/app/home/HomeViewModel.kt
+++ b/app/src/main/java/ai/travel/app/home/HomeViewModel.kt
@@ -3,6 +3,7 @@ package ai.travel.app.home
import ai.travel.app.database.ArrayListConverter
import ai.travel.app.database.DatabaseRepo
import ai.travel.app.database.travel.TripsEntity
+import ai.travel.app.datastore.UserDatastore
import ai.travel.app.dto.ApiPrompt
import ai.travel.app.dto.PalmApi
import ai.travel.app.dto.Prompt
@@ -18,12 +19,16 @@ import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withContext
import javax.inject.Inject
@HiltViewModel
@@ -54,8 +59,11 @@ class HomeViewModel @Inject constructor(
dbRepository.getMoreInfo(destination)
val allTrips: Flow> = dbRepository.allTrips
- fun getCurrentTrip(destination: String): Flow> = dbRepository.getCurrentTrip(destination)
- fun uniqueDays(destination: String): Flow> = dbRepository.distinctDays(destination)
+ fun getCurrentTrip(destination: String): Flow> =
+ dbRepository.getCurrentTrip(destination)
+
+ fun uniqueDays(destination: String): Flow> =
+ dbRepository.distinctDays(destination)
val tripName = mutableStateOf(TextFieldValue(""))
val tripBudget = mutableStateOf(TextFieldValue(""))
@@ -86,11 +94,20 @@ class HomeViewModel @Inject constructor(
private val _loginStatus = MutableStateFlow(false)
val loginStatus: StateFlow = _loginStatus.asStateFlow()
+ init {
+ viewModelScope.launch {
+ val dataStore = UserDatastore(application.applicationContext)
+ dataStore.getLoginStatus.collectLatest {
+ _loginStatus.value = it
+ }
+ }
+ }
+
fun updateUserDetails(
userName: String,
gender: String,
userPhoneNumber: String,
- loginStatus: Boolean
+ loginStatus: Boolean,
) {
_userName.value = userName
_userPhoneNumber.value = userPhoneNumber
@@ -104,108 +121,158 @@ class HomeViewModel @Inject constructor(
}
-
fun getApiData() {
viewModelScope.launch {
- delay(1000)
- val apiData =
- repository.getApiData(
- ApiPrompt(
- prompt = Prompt(
- text = _message.value
+ withContext(Dispatchers.IO) {
+ val apiData =
+ repository.getApiData(
+ ApiPrompt(
+ prompt = Prompt(
+ text = _message.value
+ )
)
)
- )
- _imageState.value = ApiState.Loaded(apiData)
- extractTourDetails(apiData.candidates?.get(0)?.output ?: "")
- getGeoCodes()
- }
- }
+ _imageState.value = ApiState.Loaded(apiData)
+ extractTourDetails(apiData.candidates?.get(0)?.output ?: "")
+ _data.value.forEachIndexed { index, location ->
+ val geoCodes = mutableMapOf()
+ val day = location.getOrDefault("Day", "-2")
+ if (day != "-2") {
+ val locationName = location.getOrDefault("Name", "")
+ if (locationName != "") {
+ val apiData =
+ repository.getGeocodingData(
+ query = "$locationName, ${_location.value}",
+ )
+ geoCodes["latitude"] =
+ apiData.items?.get(0)?.position?.lat?.toString() ?: ""
+ geoCodes["longitude"] =
+ apiData.items?.get(0)?.position?.lng?.toString() ?: ""
+ _geoCodesData.value[index].geoCode = GeoCode(
+ latitude = geoCodes["latitude"] ?: "",
+ longitude = geoCodes["longitude"] ?: ""
+ )
+ }
+ }
- private fun getGeoCodes() {
- viewModelScope.launch {
- delay(1000)
- _data.value.forEachIndexed { index, location ->
- val geoCodes = mutableMapOf()
- val day = location.getOrDefault("Day", "-2")
- if (day != "-2") {
- val locationName = location.getOrDefault("Name", "")
- if (locationName != "") {
- val apiData =
- repository.getGeocodingData(
- query = "$locationName, ${_location.value}",
+ }
+ _imageState.value = ApiState.ReceivedGeoCodes
+ _geoCodesData.value.forEachIndexed { index, location ->
+ val apiData =
+ repository.getPlaceIdData(
+ PlaceIdBody(
+ textQuery = location.name
)
- geoCodes["latitude"] =
- apiData.items?.get(0)?.position?.lat?.toString() ?: ""
- geoCodes["longitude"] =
- apiData.items?.get(0)?.position?.lng?.toString() ?: ""
- _geoCodesData.value[index].geoCode = GeoCode(
- latitude = geoCodes["latitude"] ?: "",
- longitude = geoCodes["longitude"] ?: ""
)
- }
+ _geoCodesData.value[index].placeId = apiData.places?.get(0)?.id ?: ""
+ println("placeIddddd: ${_geoCodesData.value[index].placeId}")
}
-
+ _imageState.value = ApiState.ReceivedPlaceId
+ _geoCodesData.value.forEachIndexed { index, location ->
+ val apiData =
+ repository.getPhotoId(
+ photoId = _geoCodesData.value[index].placeId ?: ""
+ )
+ _geoCodesData.value[index].photoID =
+ apiData.result?.photos?.get(0)?.photo_reference ?: ""
+ println("photoIddddd: ${apiData.result}")
+ println("photoIddddd 111: ${_geoCodesData.value[index].placeId}")
+ }
+ _imageState.value = ApiState.ReceivedPhotoId
+ _geoCodesData.value.forEachIndexed { index, location ->
+ val apiData =
+ repository.getPhoto(
+ photoReference = _geoCodesData.value[index].photoID ?: "",
+ maxWidth = 1200,
+ )
+ _geoCodesData.value[index].photo = apiData
+ }
+ dbRepository.insertAllTrips(_geoCodesData.value.take(8).map {
+ TripsEntity(
+ day = it.day,
+ timeOfDay = it.timeOfDay,
+ name = it.name,
+ budget = it.budget,
+ latitude = it.geoCode?.latitude?.toDouble(),
+ longitude = it.geoCode?.longitude?.toDouble(),
+ photoBase64 = byteArrayToBase64(it.photo ?: ByteArray(0)),
+ source = source.value.text,
+ destination = destination.value.text,
+ travelActivity = "",
+ )
+ })
+ _imageState.value = ApiState.ReceivedPhoto
}
- _imageState.value = ApiState.ReceivedGeoCodes
- getPlaceId()
}
}
- private fun getPlaceId() {
- viewModelScope.launch {
- delay(1000)
- _geoCodesData.value.forEachIndexed { index, location ->
- val apiData =
- repository.getPlaceIdData(
- PlaceIdBody(
- textQuery = location.name
+ private suspend fun getGeoCodes() {
+ _data.value.forEachIndexed { index, location ->
+ val geoCodes = mutableMapOf()
+ val day = location.getOrDefault("Day", "-2")
+ if (day != "-2") {
+ val locationName = location.getOrDefault("Name", "")
+ if (locationName != "") {
+ val apiData =
+ repository.getGeocodingData(
+ query = "$locationName, ${_location.value}",
)
+ geoCodes["latitude"] =
+ apiData.items?.get(0)?.position?.lat?.toString() ?: ""
+ geoCodes["longitude"] =
+ apiData.items?.get(0)?.position?.lng?.toString() ?: ""
+ _geoCodesData.value[index].geoCode = GeoCode(
+ latitude = geoCodes["latitude"] ?: "",
+ longitude = geoCodes["longitude"] ?: ""
)
- _geoCodesData.value[index].placeId = apiData.places?.get(0)?.id ?: ""
- println("placeIddddd: ${_geoCodesData.value[index].placeId}")
+ }
}
- _imageState.value = ApiState.ReceivedPlaceId
- getPhotoId()
- }
+ }
+ _imageState.value = ApiState.ReceivedGeoCodes
}
- private fun getPhoto() {
- viewModelScope.launch {
- delay(1000)
- _geoCodesData.value.forEachIndexed { index, location ->
- val apiData =
- repository.getPhoto(
- photoReference = _geoCodesData.value[index].photoID ?: "",
- maxWidth = 1200,
+ private suspend fun getPlaceId() {
+ _geoCodesData.value.forEachIndexed { index, location ->
+ val apiData =
+ repository.getPlaceIdData(
+ PlaceIdBody(
+ textQuery = location.name
)
- _geoCodesData.value[index].photo = apiData
- }
- addTripToDatabase()
- _imageState.value = ApiState.ReceivedPhoto
-
+ )
+ _geoCodesData.value[index].placeId = apiData.places?.get(0)?.id ?: ""
+ println("placeIddddd: ${_geoCodesData.value[index].placeId}")
}
-
+ _imageState.value = ApiState.ReceivedPlaceId
}
- private fun addTripToDatabase() {
- viewModelScope.launch {
- println("Adding to databasesssssssssss")
- dbRepository.insertAllTrips(_geoCodesData.value.map {
- TripsEntity(
- day = it.day,
- timeOfDay = it.timeOfDay,
- name = it.name,
- budget = it.budget,
- latitude = it.geoCode?.latitude?.toDouble(),
- longitude = it.geoCode?.longitude?.toDouble(),
- photoBase64 = byteArrayToBase64(it.photo ?: ByteArray(0)),
- source = source.value.text,
- destination = destination.value.text,
- travelActivity = "",
+ private suspend fun getPhoto() {
+ _geoCodesData.value.forEachIndexed { index, location ->
+ val apiData =
+ repository.getPhoto(
+ photoReference = _geoCodesData.value[index].photoID ?: "",
+ maxWidth = 1200,
)
- })
+ _geoCodesData.value[index].photo = apiData
+ }
+ }
+
+ private suspend fun addTripToDatabase() {
+ println("Adding to databasesssssssssss")
+ dbRepository.insertAllTrips(_geoCodesData.value.map {
+ TripsEntity(
+ day = it.day,
+ timeOfDay = it.timeOfDay,
+ name = it.name,
+ budget = it.budget,
+ latitude = it.geoCode?.latitude?.toDouble(),
+ longitude = it.geoCode?.longitude?.toDouble(),
+ photoBase64 = byteArrayToBase64(it.photo ?: ByteArray(0)),
+ source = source.value.text,
+ destination = destination.value.text,
+ travelActivity = "",
+ )
+ })
// _geoCodesData.value.forEachIndexed { _, location ->
// dbRepository.insertTrip(
@@ -223,32 +290,24 @@ class HomeViewModel @Inject constructor(
// )
// )
// }
-
- }
-
}
private fun byteArrayToBase64(byteArray: ByteArray): String {
return Base64.encodeToString(byteArray, Base64.DEFAULT)
}
- private fun getPhotoId() {
- viewModelScope.launch {
- delay(1000)
- _geoCodesData.value.forEachIndexed { index, location ->
- val apiData =
- repository.getPhotoId(
- photoId = _geoCodesData.value[index].placeId ?: ""
- )
- _geoCodesData.value[index].photoID =
- apiData.result?.photos?.get(0)?.photo_reference ?: ""
- println("photoIddddd: ${apiData.result}")
- println("photoIddddd 111: ${_geoCodesData.value[index].placeId}")
- }
- _imageState.value = ApiState.ReceivedPhotoId
- getPhoto()
+ private suspend fun getPhotoId() {
+ _geoCodesData.value.forEachIndexed { index, location ->
+ val apiData =
+ repository.getPhotoId(
+ photoId = _geoCodesData.value[index].placeId ?: ""
+ )
+ _geoCodesData.value[index].photoID =
+ apiData.result?.photos?.get(0)?.photo_reference ?: ""
+ println("photoIddddd: ${apiData.result}")
+ println("photoIddddd 111: ${_geoCodesData.value[index].placeId}")
}
-
+ _imageState.value = ApiState.ReceivedPhotoId
}
fun updateMessage(message: String, location: String, noOfDays: String) {
diff --git a/app/src/main/java/ai/travel/app/home/ui/CollapsedTopBar.kt b/app/src/main/java/ai/travel/app/home/ui/CollapsedTopBar.kt
index 82dd1da..ed11df0 100644
--- a/app/src/main/java/ai/travel/app/home/ui/CollapsedTopBar.kt
+++ b/app/src/main/java/ai/travel/app/home/ui/CollapsedTopBar.kt
@@ -23,7 +23,6 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -39,11 +38,15 @@ import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.ArrowBackIos
+import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Divider
+import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
@@ -57,17 +60,19 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
+import androidx.compose.ui.draw.drawWithCache
+import androidx.compose.ui.graphics.BlendMode
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.withStyle
-import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import androidx.navigation.NavController
@Composable
fun CollapsedTopBarHomeScreen(
@@ -130,3 +135,51 @@ fun CollapsedTopBarHomeScreen(
}
}
+@Composable
+fun CollapsedTopBarDetailsScreen(
+ text: String,
+ isCollapsed: Boolean,
+ navController: NavController
+) {
+ AnimatedVisibility(
+ visible = isCollapsed,
+ enter = fadeIn(),
+ exit = fadeOut()
+ ) {
+ Column(modifier = Modifier) {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .background(appGradient)
+ .padding(vertical = 10.dp, horizontal = 20.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ Icon(
+ imageVector = Icons.Filled.ArrowBackIos,
+ contentDescription = "Arrow Back",
+ tint = textColor,
+ modifier = Modifier
+ .padding(start = 0.dp)
+ .size(25.dp)
+ .clickable {
+ navController.popBackStack()
+ }
+ )
+ Spacer(modifier = Modifier.width(15.dp))
+
+ Text(text = buildAnnotatedString {
+ withStyle(
+ style = SpanStyle(
+ color = textColor,
+ fontSize = 32.sp,
+ fontWeight = FontWeight.Black
+ )
+ ) {
+ append(text)
+ }
+ }, modifier = Modifier.padding(end = 10.dp))
+ }
+ Divider(thickness = 1.dp, color = textColor.copy(0.5f))
+ }
+ }
+}
diff --git a/app/src/main/java/ai/travel/app/home/ui/HomeScreenMain.kt b/app/src/main/java/ai/travel/app/home/ui/HomeScreenMain.kt
index 6a37688..7d5d30c 100644
--- a/app/src/main/java/ai/travel/app/home/ui/HomeScreenMain.kt
+++ b/app/src/main/java/ai/travel/app/home/ui/HomeScreenMain.kt
@@ -2,6 +2,7 @@ package ai.travel.app.home.ui
import ai.travel.app.R
import ai.travel.app.bottomBar.items
+import ai.travel.app.home.ApiState
import ai.travel.app.home.HomeViewModel
import ai.travel.app.newTrip.NewTripScreen
import ai.travel.app.newTrip.NewTripViewModel
@@ -59,17 +60,22 @@ import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.draw.clip
+import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
+import com.airbnb.lottie.compose.LottieAnimation
+import com.airbnb.lottie.compose.LottieCompositionSpec
+import com.airbnb.lottie.compose.rememberLottieComposition
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable
@@ -286,6 +292,106 @@ fun HomeScreenMain(
}
}
+ if (viewModel.isAnimationVisible.value) {
+ Box(
+ modifier = Modifier.fillMaxSize(),
+ contentAlignment = Alignment.Center
+ ) {
+ Column(horizontalAlignment = Alignment.CenterHorizontally) {
+ when (state.value) {
+ is ApiState.Error -> {
+
+ }
+
+ is ApiState.Loaded -> {
+ val currenanim by rememberLottieComposition(
+ spec = LottieCompositionSpec.Asset("location.json")
+ )
+ LottieAnimation(
+ composition = currenanim,
+ iterations = Int.MAX_VALUE,
+ contentScale = ContentScale.Crop,
+ speed = 1f,
+ modifier = Modifier
+ .size(250.dp)
+ )
+
+ Text(text = "Fetching your location", color = textColor, fontSize = 18.sp)
+ }
+
+ ApiState.Loading -> {
+ val currenanim by rememberLottieComposition(
+ spec = LottieCompositionSpec.Asset("location.json")
+ )
+ LottieAnimation(
+ composition = currenanim,
+ iterations = Int.MAX_VALUE,
+ contentScale = ContentScale.Crop,
+ speed = 1f,
+ modifier = Modifier
+ .size(250.dp)
+ )
+
+ Text(text = "Fetching your location", color = textColor, fontSize = 18.sp)
+ }
+
+ ApiState.NotStarted -> {
+
+ }
+
+ ApiState.ReceivedGeoCodes -> {
+ val currenanim by rememberLottieComposition(
+ spec = LottieCompositionSpec.Asset("itineary.json")
+ )
+ LottieAnimation(
+ composition = currenanim,
+ iterations = Int.MAX_VALUE,
+ contentScale = ContentScale.Crop,
+ speed = 1f,
+ modifier = Modifier
+ .size(250.dp)
+ )
+ Text(text = "Planning Itineary", color = textColor, fontSize = 18.sp)
+ }
+
+ ApiState.ReceivedPhoto -> {
+ viewModel.isAnimationVisible.value = false
+
+ }
+
+ ApiState.ReceivedPhotoId -> {
+ val currenanim by rememberLottieComposition(
+ spec = LottieCompositionSpec.Asset("getset.json")
+ )
+ LottieAnimation(
+ composition = currenanim,
+ iterations = Int.MAX_VALUE,
+ contentScale = ContentScale.Crop,
+ speed = 1f,
+ modifier = Modifier
+ .size(250.dp)
+ )
+ Text(text = "Get Set Go", color = textColor, fontSize = 18.sp)
+ }
+
+ ApiState.ReceivedPlaceId -> {
+ val currenanim by rememberLottieComposition(
+ spec = LottieCompositionSpec.Asset("onyourmark.json")
+ )
+ LottieAnimation(
+ composition = currenanim,
+ iterations = Int.MAX_VALUE,
+ contentScale = ContentScale.Crop,
+ speed = 1f,
+ modifier = Modifier
+ .size(250.dp)
+ )
+ Text(text = "ON your Mark", color = textColor, fontSize = 18.sp)
+ }
+ }
+ }
+ }
+ }
}
}
}
diff --git a/app/src/main/java/ai/travel/app/navigation/NavController.kt b/app/src/main/java/ai/travel/app/navigation/NavController.kt
index 217d7a3..121baaa 100644
--- a/app/src/main/java/ai/travel/app/navigation/NavController.kt
+++ b/app/src/main/java/ai/travel/app/navigation/NavController.kt
@@ -32,7 +32,7 @@ fun NavController(
val newTripViewModel: NewTripViewModel = hiltViewModel()
val loginStatus = homeViewModel.loginStatus.collectAsState()
- NavHost(navController = navHostController, startDestination = if (!loginStatus.value) Screens.Home.route else Screens.Login.route) {
+ NavHost(navController = navHostController, startDestination = if (loginStatus.value) Screens.Home.route else Screens.Login.route) {
composable(Screens.Home.route) {
HomeScreenMain(
viewModel = homeViewModel,
diff --git a/app/src/main/java/ai/travel/app/riveanimation/LoginUI.kt b/app/src/main/java/ai/travel/app/riveanimation/LoginUI.kt
index 5a19ed5..3f02a14 100644
--- a/app/src/main/java/ai/travel/app/riveanimation/LoginUI.kt
+++ b/app/src/main/java/ai/travel/app/riveanimation/LoginUI.kt
@@ -280,8 +280,8 @@ fun LoginUI(
exit = slideOutHorizontally()
) {
TextFieldWithIconsLogin(
- textValue = "Password",
- placeholder = "Enter Your Password",
+ textValue = "OTP",
+ placeholder = "Enter OTP Sent to your Phone Number",
icon = Icons.Filled.Lock,
mutableText = password,
onValueChanged = {
diff --git a/app/src/main/java/ai/travel/app/tripDetails/MoreInfoTrips.kt b/app/src/main/java/ai/travel/app/tripDetails/MoreInfoTrips.kt
index fb8e122..aafd064 100644
--- a/app/src/main/java/ai/travel/app/tripDetails/MoreInfoTrips.kt
+++ b/app/src/main/java/ai/travel/app/tripDetails/MoreInfoTrips.kt
@@ -104,7 +104,7 @@ fun MoreInfoTrips(viewModel: HomeViewModel, paddingValues: PaddingValues) {
Card(
modifier = Modifier
.fillMaxWidth()
- .fillMaxHeight(0.24f),
+ .fillMaxHeight(0.34f),
shape = RoundedCornerShape(0.dp),
elevation = CardDefaults.cardElevation(7.dp),
colors = CardDefaults.cardColors(
@@ -136,7 +136,7 @@ fun MoreInfoTrips(viewModel: HomeViewModel, paddingValues: PaddingValues) {
)
}
},
- contentScale = ContentScale.FillWidth
+ contentScale = ContentScale.Crop
)
}
}
diff --git a/app/src/main/java/ai/travel/app/tripDetails/TripDetails.kt b/app/src/main/java/ai/travel/app/tripDetails/TripDetails.kt
index 6f30d59..5a4eaa8 100644
--- a/app/src/main/java/ai/travel/app/tripDetails/TripDetails.kt
+++ b/app/src/main/java/ai/travel/app/tripDetails/TripDetails.kt
@@ -1,8 +1,11 @@
package ai.travel.app.tripDetails
+import ai.travel.app.R
import ai.travel.app.database.travel.TripsEntity
import ai.travel.app.home.HomeViewModel
import ai.travel.app.home.base64ToByteArray
+import ai.travel.app.home.ui.CollapsedTopBarDetailsScreen
+import ai.travel.app.home.ui.CollapsedTopBarHomeScreen
import ai.travel.app.home.ui.convertImageByteArrayToBitmap
import ai.travel.app.ui.theme.CardBackground
import ai.travel.app.ui.theme.appGradient
@@ -10,8 +13,11 @@ import ai.travel.app.ui.theme.bottomBarBackground
import ai.travel.app.ui.theme.bottomBarBorder
import ai.travel.app.ui.theme.lightText
import ai.travel.app.ui.theme.textColor
+import android.graphics.Point
import androidx.compose.foundation.BorderStroke
+import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
+import androidx.compose.foundation.LocalOverscrollConfiguration
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
@@ -34,11 +40,13 @@ import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CalendarToday
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.LocationOn
+import androidx.compose.material.icons.filled.Map
import androidx.compose.material.icons.filled.Public
import androidx.compose.material.icons.filled.Wallet
import androidx.compose.material.icons.filled.WbSunny
@@ -50,20 +58,27 @@ import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
+import androidx.compose.material3.Scaffold
import androidx.compose.material3.SheetState
import androidx.compose.material3.SheetValue
import androidx.compose.material3.Text
import androidx.compose.material3.rememberBottomSheetScaffoldState
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithCache
+import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
@@ -73,16 +88,19 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
+import com.example.mapbox_map.MapBoxMap
+import com.example.mapbox_map.MapBoxPoint
+import com.example.mapbox_map.MapItem
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
-@OptIn(ExperimentalMaterial3Api::class)
+@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable
fun TripDetailsScreen(
viewModel: HomeViewModel,
paddingValues: PaddingValues,
- navController: NavController
+ navController: NavController,
) {
val cardData1 = listOf(
GridCardData(
@@ -115,6 +133,22 @@ fun TripDetailsScreen(
skipPartiallyExpanded = false
)
)
+ var currentPoint = remember { mutableStateOf(null) }
+ val collapseThreshold = remember {
+ mutableFloatStateOf(0.25f)
+ }
+ val listState = rememberLazyListState()
+ val isCollapsed = remember(listState) {
+ derivedStateOf {
+ val firstVisibleItemOffset = listState.firstVisibleItemScrollOffset
+ val firstItemHeight = listState.layoutInfo.visibleItemsInfo.firstOrNull()?.size ?: 0
+ val totalOffset =
+ (firstVisibleItemOffset.toFloat() / firstItemHeight.toFloat())
+
+ totalOffset > collapseThreshold.floatValue
+ }
+ }
+
BottomSheetScaffold(
sheetContent = {
MoreInfoTrips(viewModel = viewModel, paddingValues = paddingValues)
@@ -124,206 +158,313 @@ fun TripDetailsScreen(
sheetShape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp),
sheetPeekHeight = 0.dp,
) {
- Column(
- modifier = Modifier
- .fillMaxSize()
- .background(appGradient)
- .padding(paddingValues)
- ) {
-
- val trips = viewModel.getCurrentTrip(viewModel.currentDestination.value).collectAsState(initial = emptyList())
- val days = viewModel.uniqueDays(viewModel.currentDestination.value).collectAsState(initial = emptyList())
- val currentDay = remember { mutableStateOf("1") }
- var dayTrips =
- viewModel.getTrips(currentDay.value, viewModel.currentDestination.value).collectAsState(initial = emptyList())
+ Scaffold(
+ topBar = {
+ CollapsedTopBarDetailsScreen(
+ isCollapsed = isCollapsed.value,
+ text = viewModel.currentDestination.value,
+ navController = navController
+ )
+ },
+ ) { padding ->
+ println(padding)
+ CompositionLocalProvider(LocalOverscrollConfiguration provides null) {
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(appGradient)
+ .padding(paddingValues)
+ ) {
+
+ val trips = viewModel.getCurrentTrip(viewModel.currentDestination.value)
+ .collectAsState(initial = emptyList())
+ val days = viewModel.uniqueDays(viewModel.currentDestination.value)
+ .collectAsState(initial = emptyList())
+ val currentDay = remember { mutableStateOf("1") }
+ var point: Point? by remember {
+ mutableStateOf(null)
+ }
+ var dayTrips =
+ viewModel.getTrips(currentDay.value, viewModel.currentDestination.value)
+ .collectAsState(initial = emptyList())
- val newItems = remember {
- mutableStateListOf()
- }
- LaunchedEffect(key1 = viewModel.getCurrentTrip(viewModel.currentDestination.value)) {
- viewModel.getCurrentTrip(viewModel.currentDestination.value).collectLatest {
- if (it.isNotEmpty() && viewModel.currentDestination.value != "") {
- newItems.clear()
- newItems.addAll(
- extractTripsByDestination(
- it,
- viewModel.currentDestination.value
- )
- )
+ val newItems = remember {
+ mutableStateListOf()
+ }
+ LaunchedEffect(key1 = viewModel.getCurrentTrip(viewModel.currentDestination.value)) {
+ viewModel.getCurrentTrip(viewModel.currentDestination.value).collectLatest {
+ if (it.isNotEmpty() && viewModel.currentDestination.value != "") {
+ newItems.clear()
+ newItems.addAll(
+ extractTripsByDestination(
+ it,
+ viewModel.currentDestination.value
+ )
+ )
+ }
+ }
}
- }
- }
- if (trips.value.isEmpty()) {
- CircularProgressIndicator()
- } else {
- Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.TopStart) {
- trips.value[0]?.photoBase64?.let {
- Card(
- modifier = Modifier
- .fillMaxWidth()
- .fillMaxHeight(0.24f),
- shape = RoundedCornerShape(0.dp),
- elevation = CardDefaults.cardElevation(7.dp),
- colors = CardDefaults.cardColors(
- containerColor = Color.Transparent
- )
+ if (trips.value.isEmpty()) {
+ Box(
+ modifier = Modifier.fillMaxSize(),
+ contentAlignment = Alignment.Center
) {
- convertImageByteArrayToBitmap(base64ToByteArray(it))?.asImageBitmap()
- ?.let { it1 ->
- Image(
- bitmap = it1,
- contentDescription = "some useful description",
- modifier = Modifier
- .fillMaxWidth()
- .fillMaxHeight()
- .drawWithCache {
- val gradient = Brush.verticalGradient(
- colors = listOf(
- Color.Transparent,
- Color.Black.copy(0.8f)
- ),
- startY = size.height / 5.5f,
- endY = size.height
- )
- onDrawWithContent {
- drawContent()
- drawRect(
- gradient,
- blendMode = BlendMode.Multiply
+ CircularProgressIndicator(color = lightText)
+ }
+ } else {
+ trips.value[0]?.photoBase64?.let {
+ LazyColumn(
+ modifier = Modifier
+ .fillMaxSize(),
+ state = listState
+ ) {
+ item {
+ Box(
+ modifier = Modifier.fillMaxSize(),
+ contentAlignment = Alignment.TopStart
+ ) {
+ Card(
+ modifier = Modifier
+ .fillMaxWidth()
+ .fillMaxHeight(0.34f),
+ shape = RoundedCornerShape(0.dp),
+ elevation = CardDefaults.cardElevation(7.dp),
+ colors = CardDefaults.cardColors(
+ containerColor = Color.Transparent
+ )
+ ) {
+ convertImageByteArrayToBitmap(base64ToByteArray(it))?.asImageBitmap()
+ ?.let { it1 ->
+ Image(
+ bitmap = it1,
+ contentDescription = "some useful description",
+ modifier = Modifier
+ .fillMaxWidth()
+ .fillMaxHeight()
+ .drawWithCache {
+ val gradient =
+ Brush.verticalGradient(
+ colors = listOf(
+ Color.Transparent,
+ Color.Black.copy(
+ 0.8f
+ )
+ ),
+ startY = size.height / 5.5f,
+ endY = size.height
+ )
+ onDrawWithContent {
+ drawContent()
+ drawRect(
+ gradient,
+ blendMode = BlendMode.Multiply
+ )
+ }
+ },
+ contentScale = ContentScale.FillWidth
)
}
- },
- contentScale = ContentScale.FillWidth
- )
- }
- }
+ }
- Column {
- Icon(
- imageVector = Icons.Filled.Close,
- contentDescription = "Arrow Back",
- tint = Color.Black,
- modifier = Modifier
- .padding(start = 15.dp, top=10.dp)
- .size(25.dp)
- .clickable {
- navController.popBackStack()
- }
- )
- Spacer(modifier = Modifier.fillMaxHeight(0.13f))
- Text(
- text = viewModel.currentDestination.value,
- color = textColor,
- fontSize = 35.sp,
- modifier = Modifier.padding(
- start = 20.dp,
- top = 20.dp,
- bottom = 8.dp
- )
- )
+ Column(modifier = Modifier.fillMaxSize()) {
+ Icon(
+ imageVector = Icons.Filled.Close,
+ contentDescription = "Arrow Back",
+ tint = lightText,
+ modifier = Modifier
+ .padding(start = 15.dp, top = 10.dp)
+ .size(25.dp)
+ .clickable {
+ navController.popBackStack()
+ }
+ )
+ Spacer(modifier = Modifier.height(70.dp))
+ Text(
+ text = viewModel.currentDestination.value,
+ color = textColor,
+ fontSize = 35.sp,
+ modifier = Modifier.padding(
+ start = 20.dp,
+ top = 20.dp,
+ bottom = 8.dp
+ )
+ )
- LazyVerticalGrid(
- columns = GridCells.Fixed(2),
- modifier = Modifier.height(200.dp)
- ) {
- items(cardData1) {
- GridCard(
- topText = it.topText,
- bottomText = it.bottomText,
- icon = it.icon
- )
- }
- items(cardData2) {
- GridCard(
- topText = it.topText,
- bottomText = it.bottomText,
- icon = it.icon
- )
- }
+ LazyVerticalGrid(
+ columns = GridCells.Fixed(2),
+ modifier = Modifier.height(200.dp)
+ ) {
+ items(cardData1) {
+ GridCard(
+ topText = it.topText,
+ bottomText = it.bottomText,
+ icon = it.icon
+ )
+ }
- }
+ items(cardData2) {
+ GridCard(
+ topText = it.topText,
+ bottomText = it.bottomText,
+ icon = it.icon
+ )
+ }
- Row(
- verticalAlignment = Alignment.CenterVertically, modifier = Modifier
- .padding(
- start = 12.dp,
- top = 0.dp,
- bottom = 0.dp,
- end = 12.dp
- )
- ) {
- Icon(
- imageVector = Icons.Filled.LocationOn,
- contentDescription = "topText",
- tint = lightText,
- modifier = Modifier.size(20.dp)
- )
- Spacer(modifier = Modifier.width(7.dp))
- Text(
- text = "Your Schedule",
- color = textColor,
- fontSize = 12.sp,
- )
- }
+ }
- Spacer(modifier = Modifier.height(10.dp))
-
- LazyRow(contentPadding = PaddingValues(7.dp)) {
- items(days.value) { day ->
- Card(
- colors = CardDefaults.cardColors(
- containerColor = if (day == currentDay.value) lightText else bottomBarBackground,
- ),
- border = BorderStroke(1.dp, bottomBarBorder),
- shape = RoundedCornerShape(20.dp),
- elevation = CardDefaults.cardElevation(0.dp),
- modifier = Modifier
- .width(120.dp)
- .padding(
- start = 12.dp,
- top = 0.dp,
- bottom = 12.dp,
- end = 12.dp
- )
- .clickable(
- interactionSource = MutableInteractionSource(),
- indication = null
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier
+ .padding(
+ start = 12.dp,
+ top = 0.dp,
+ bottom = 0.dp,
+ end = 12.dp
+ )
) {
- coroutineScope.launch {
- currentDay.value = day ?: "1"
- }
+ Icon(
+ imageVector = Icons.Filled.Map,
+ contentDescription = "topText",
+ tint = lightText,
+ modifier = Modifier.size(30.dp)
+ )
+ Spacer(modifier = Modifier.width(7.dp))
+ Text(
+ text = "Map View",
+ color = textColor,
+ fontSize = 25.sp,
+ )
}
- ) {
- Column(
- horizontalAlignment = Alignment.CenterHorizontally,
- verticalArrangement = Arrangement.Center,
- modifier = Modifier
- .fillMaxWidth()
- .padding(
- start = 0.dp,
- top = 10.dp,
- bottom = 10.dp
+ Spacer(modifier = Modifier.height(20.dp))
+
+ Card(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(start = 12.dp, end = 12.dp)
+ .height(200.dp)
+ .shadow(10.dp),
+ shape = RoundedCornerShape(10.dp),
+ elevation = CardDefaults.cardElevation(40.dp),
+ colors = CardDefaults.cardColors(
+ containerColor = Color.Transparent
+ ),
+ ) {
+ MapBoxMap(
+ onPointChange = { point ->
+
+ },
+ points = dayTrips.value.map {
+ MapItem(
+ image = R.drawable.app_icon,
+ latitude = it?.latitude ?: 0.0,
+ longitude = it?.longitude ?: 0.0,
+ location = it?.destination ?: "",
+ time = it?.timeOfDay ?: "",
+ )
+ },
+ currentPoint = currentPoint.apply {
+ value = MapBoxPoint(
+ latitude = dayTrips.value[0]?.latitude
+ ?: 0.0,
+ longitude = dayTrips.value[0]?.longitude
+ ?: 0.0,
+ zoom = 15.0
+ )
+ },
+ latitude = dayTrips.value[0]?.latitude
+ ?: 0.0,
+ longitude = dayTrips.value[0]?.longitude
+ ?: 0.0,
)
- ) {
- Text(
- text = "Day $day",
- color = textColor,
- fontSize = 18.sp,
- modifier = Modifier.padding(start = 2.dp)
- )
+ }
+
+ Spacer(modifier = Modifier.height(20.dp))
+
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ modifier = Modifier
+ .padding(
+ start = 12.dp,
+ top = 0.dp,
+ bottom = 0.dp,
+ end = 12.dp
+ )
+ ) {
+ Icon(
+ imageVector = Icons.Filled.LocationOn,
+ contentDescription = "topText",
+ tint = lightText,
+ modifier = Modifier.size(30.dp)
+ )
+ Spacer(modifier = Modifier.width(7.dp))
+ Text(
+ text = "Your Schedule",
+ color = textColor,
+ fontSize = 25.sp,
+ )
+ }
+
+ Spacer(modifier = Modifier.height(20.dp))
}
}
+ }
+ item {
+ LazyRow {
+ items(days.value) { day ->
+ Card(
+ colors = CardDefaults.cardColors(
+ containerColor = if (day == currentDay.value) lightText else bottomBarBackground,
+ ),
+ border = BorderStroke(1.dp, bottomBarBorder),
+ shape = RoundedCornerShape(20.dp),
+ elevation = CardDefaults.cardElevation(0.dp),
+ modifier = Modifier
+ .width(120.dp)
+ .padding(
+ start = 12.dp,
+ top = 0.dp,
+ bottom = 12.dp,
+ end = 12.dp
+ )
+ .clickable(
+ interactionSource = MutableInteractionSource(),
+ indication = null
+ ) {
+ coroutineScope.launch {
+ currentDay.value = day ?: "1"
+ }
+ }
- }
- }
+ ) {
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
+ verticalArrangement = Arrangement.Center,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(
+ start = 0.dp,
+ top = 10.dp,
+ bottom = 10.dp
+ )
+ ) {
+ Text(
+ text = "Day $day",
+ color = textColor,
+ fontSize = 18.sp,
+ modifier = Modifier.padding(start = 2.dp)
+ )
+ }
+ }
- Spacer(modifier = Modifier.height(10.dp))
- LazyColumn() {
+ }
+ }
+ }
+
items(dayTrips.value) {
Row(
modifier = Modifier
@@ -397,9 +538,12 @@ fun TripDetailsScreen(
Row(verticalAlignment = Alignment.CenterVertically) {
Button(
onClick = {
- viewModel.currentDay.value = currentDay.value
- viewModel.currentTimeOfDay.value = it?.timeOfDay ?: ""
- viewModel.currentNewDestination.value = it?.name ?: ""
+ viewModel.currentDay.value =
+ currentDay.value
+ viewModel.currentTimeOfDay.value =
+ it?.timeOfDay ?: ""
+ viewModel.currentNewDestination.value =
+ it?.name ?: ""
coroutineScope.launch {
modalSheetStates.bottomSheetState.expand()
}
@@ -433,16 +577,14 @@ fun TripDetailsScreen(
}
}
}
-
-
}
}
}
+
}
}
-
}
}
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0bbd5aa..00bc7cc 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,4 +1,5 @@
Tripify
BaseActivity
+ pk.eyJ1IjoidGhla2FhaWxhc2hzaGFybWEiLCJhIjoiY2xtNm9sbW00MnY4bTNlbzl2c2Y2Z3g3byJ9.HZmK-5aP8z6hVA8IIU0q6A
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 09ebc54..2684dd4 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -12,6 +12,7 @@ buildscript {
plugins {
id("com.android.application") version "8.1.1" apply false
+ id("com.android.library") version "8.1.0" apply false
id("org.jetbrains.kotlin.android") version "1.8.10" apply false
id("com.google.dagger.hilt.android") version "2.48" apply false
id("com.google.devtools.ksp") version "1.8.10-1.0.9" apply false
diff --git a/gradle.properties b/gradle.properties
index 3c5031e..cc3196d 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -20,4 +20,5 @@ kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
-android.nonTransitiveRClass=true
\ No newline at end of file
+android.nonTransitiveRClass=true
+MAPBOX_DOWNLOADS_TOKEN=sk.eyJ1IjoidGhla2FhaWxhc2hzaGFybWEiLCJhIjoiY2xtNnBxNmFxMG1qeTNkbW1oazhjMHhreSJ9.3AKIgPKr9iqO8JeCTDtbDw
\ No newline at end of file
diff --git a/maps/.gitignore b/maps/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/maps/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/maps/build.gradle b/maps/build.gradle
new file mode 100644
index 0000000..8bd33c8
--- /dev/null
+++ b/maps/build.gradle
@@ -0,0 +1,75 @@
+plugins {
+ id 'com.android.library'
+ id 'org.jetbrains.kotlin.android'
+}
+
+android {
+ namespace 'com.example.requestlocation'
+ compileSdk 33
+
+ defaultConfig {
+ minSdk 25
+ targetSdk 33
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ vectorDrawables {
+ useSupportLibrary true
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+ buildFeatures {
+ compose true
+ }
+ composeOptions {
+ kotlinCompilerExtensionVersion '1.4.3'
+ }
+ packagingOptions {
+ resources {
+ excludes += '/META-INF/{AL2.0,LGPL2.1}'
+ }
+ }
+}
+
+dependencies {
+
+ implementation 'androidx.core:core-ktx:1.8.0'
+ implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.0')
+ implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
+ implementation 'androidx.activity:activity-compose:1.5.1'
+ implementation platform('androidx.compose:compose-bom:2022.10.00')
+ implementation 'androidx.compose.ui:ui'
+ implementation 'androidx.compose.ui:ui-graphics'
+ implementation 'androidx.compose.ui:ui-tooling-preview'
+ implementation 'androidx.compose.material3:material3'
+ implementation 'androidx.appcompat:appcompat-resources:1.6.1'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+ androidTestImplementation platform('androidx.compose:compose-bom:2022.10.00')
+ androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
+ debugImplementation 'androidx.compose.ui:ui-tooling'
+ debugImplementation 'androidx.compose.ui:ui-test-manifest'
+
+ implementation 'com.google.android.gms:play-services-location:21.0.1'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.6.4'
+ implementation 'com.mapbox.maps:android:10.14.0'
+ implementation 'com.mapbox.mapboxsdk:mapbox-android-gestures:0.8.0'
+
+ implementation("com.mapbox.navigation:ui-dropin:2.14.2")
+
+}
\ No newline at end of file
diff --git a/maps/proguard-rules.pro b/maps/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/maps/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/maps/src/androidTest/java/com/example/mapbox_map/ExampleInstrumentedTest.kt b/maps/src/androidTest/java/com/example/mapbox_map/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..c2d4604
--- /dev/null
+++ b/maps/src/androidTest/java/com/example/mapbox_map/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.example.mapbox_map
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppConText() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.example.requestlocation", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/maps/src/main/AndroidManifest.xml b/maps/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..8c3de62
--- /dev/null
+++ b/maps/src/main/AndroidManifest.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/maps/src/main/java/com/example/mapbox_map/MainActivity.kt b/maps/src/main/java/com/example/mapbox_map/MainActivity.kt
new file mode 100644
index 0000000..97135a5
--- /dev/null
+++ b/maps/src/main/java/com/example/mapbox_map/MainActivity.kt
@@ -0,0 +1,400 @@
+package com.example.mapbox_map
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.rememberLauncherForActivityResult
+import androidx.activity.compose.setContent
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.core.tween
+import androidx.compose.animation.slideInVertically
+import androidx.compose.animation.slideOutVertically
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxHeight
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.lazy.LazyRow
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.LocationOn
+import androidx.compose.material3.Button
+import androidx.compose.material3.Card
+import androidx.compose.material3.CardDefaults
+import androidx.compose.material3.Icon
+import androidx.compose.material3.OutlinedButton
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+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.graphics.Color
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.lifecycle.DefaultLifecycleObserver
+import androidx.lifecycle.LifecycleOwner
+import com.example.mapbox_map.ui.LocationService
+import com.example.requestlocation.R
+import com.mapbox.geojson.Point
+import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
+
+class MainActivity : ComponentActivity() {
+
+ init {
+ lifecycle.addObserver(object : DefaultLifecycleObserver {
+ override fun onResume(owner: LifecycleOwner) {
+ MapboxNavigationApp.attach(owner)
+ }
+ })
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContent {
+ MapScreen()
+ }
+ }
+
+}
+
+@Composable
+fun MapScreen() {
+
+ var point: Point? by remember {
+ mutableStateOf(null)
+ }
+ var relaunch by remember {
+ mutableStateOf(false)
+ }
+
+ val context = LocalContext.current
+
+
+ val permissionRequest = rememberLauncherForActivityResult(
+ contract = ActivityResultContracts.RequestMultiplePermissions(),
+ onResult = { permissions ->
+ if (!permissions.values.all { it }) {
+ //handle permission denied
+ } else {
+ relaunch = !relaunch
+ }
+ }
+ )
+ var isClicked = remember { mutableStateOf(false) }
+ var isReset = remember { mutableStateOf(false) }
+ var currentPoint = remember { mutableStateOf(null) }
+
+
+ Box(modifier = Modifier.fillMaxSize()) {
+ Column(
+ modifier = Modifier.fillMaxSize(),
+ ) {
+ MapBoxMap(
+ onPointChange = { point = it },
+ modifier = Modifier
+ .fillMaxSize(),
+ isClicked = isClicked,
+ currentPoint = currentPoint,
+ isReset = isReset,
+ latitude = 0.0,
+ longitude = 0.0,
+ points = listOf()
+ )
+ }
+ AnimatedVisibility(
+ visible = !isClicked.value,
+ enter = slideInVertically(tween(1000), initialOffsetY = {
+ it
+ }),
+ exit = slideOutVertically(tween(1000), targetOffsetY = {
+ it
+ })
+ ) {
+// Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
+// LazyRow(
+// modifier = Modifier.fillMaxWidth(),
+// contentPadding = PaddingValues(30.dp)
+// ) {
+// items(items) { item ->
+// Card(
+// modifier = Modifier
+// .width(300.dp)
+// .height(200.dp)
+// .padding(end = 10.dp),
+// shape = RoundedCornerShape(10.dp),
+// elevation = CardDefaults.cardElevation(10.dp)
+// ) {
+// Row(
+// modifier = Modifier.fillMaxSize(),
+// verticalAlignment = Alignment.CenterVertically,
+// horizontalArrangement = Arrangement.Center
+// ) {
+// Image(
+// painter = painterResource(id = item.image),
+// contentDescription = null,
+// contentScale = ContentScale.Crop,
+// modifier = Modifier
+// .fillMaxWidth(0.5f)
+// .fillMaxHeight()
+// )
+// Spacer(modifier = Modifier.width(10.dp))
+// Column(modifier = Modifier.fillMaxWidth()) {
+// Spacer(modifier = Modifier.height(10.dp))
+// Text(
+// text = item.location,
+// color = Color.Black,
+// fontSize = 20.sp,
+// fontWeight = FontWeight.Bold,
+// softWrap = true
+// )
+// Spacer(modifier = Modifier.height(10.dp))
+// Text(
+// text = item.time,
+// color = Color.Black,
+// fontSize = 10.sp,
+// fontWeight = FontWeight.Normal
+// )
+// Spacer(modifier = Modifier.height(10.dp))
+// OutlinedButton(
+// onClick = {
+// isReset.value = false
+// isClicked.value = true
+//// currentPoint.value = item.point
+// },
+// shape = RoundedCornerShape(10.dp)
+// ) {
+// Row(verticalAlignment = Alignment.CenterVertically) {
+// Icon(
+// imageVector = Icons.Filled.LocationOn,
+// contentDescription = null,
+// modifier = Modifier.size(20.dp),
+// tint = Color.Black
+// )
+// Spacer(modifier = Modifier.width(10.dp))
+// Text(
+// text = "Navigate",
+// color = Color.Black,
+// fontSize = 10.sp,
+// fontWeight = FontWeight.Normal
+// )
+// }
+// }
+// }
+// Spacer(modifier = Modifier.width(10.dp))
+// }
+// }
+// }
+//
+// }
+ }
+// }
+ }
+ Box(
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(horizontal = 10.dp, vertical = 25.dp),
+ contentAlignment = Alignment.TopEnd
+ ) {
+ Card(
+ modifier = Modifier
+ .padding(end = 10.dp),
+ shape = RoundedCornerShape(10.dp),
+ elevation = CardDefaults.cardElevation(10.dp)
+ ) {
+ Button(
+ onClick = {
+ isReset.value = true
+ isClicked.value = false
+
+ },
+ shape = RoundedCornerShape(10.dp)
+ ) {
+ Text(
+ text = "Reset",
+ color = Color.White,
+ fontSize = 10.sp,
+ fontWeight = FontWeight.Normal,
+
+ )
+ }
+
+ }
+ }
+
+ LaunchedEffect(key1 = relaunch) {
+ try {
+ val location = LocationService().getCurrentLocation(context)
+ point = Point.fromLngLat(location.longitude, location.latitude)
+
+ } catch (e: LocationService.LocationServiceException) {
+ when (e) {
+ is LocationService.LocationServiceException.LocationDisabledException -> {
+ //handle location disabled, show dialog or a snack-bar to enable location
+ }
+
+ is LocationService.LocationServiceException.MissingPermissionException -> {
+ permissionRequest.launch(
+ arrayOf(
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION
+ )
+ )
+ }
+
+ is LocationService.LocationServiceException.NoNetworkEnabledException -> {
+ //handle no network enabled, show dialog or a snack-bar to enable network
+ }
+
+ is LocationService.LocationServiceException.UnknownException -> {
+ //handle unknown exception
+ }
+ }
+ }
+ }
+}
+
+//val items = listOf(
+// MapItem(
+// image = R.drawable.one,
+// location = "Taj Mahal, Agra",
+// time = "2 hours ago",
+// point = Point.fromLngLat(78.0421, 27.1750) // Taj Mahal's latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.two,
+// location = "Jaipur Palace, Jaipur",
+// time = "1 day ago",
+// point = Point.fromLngLat(75.8376, 26.9124) // Jaipur Palace's latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.three,
+// location = "Kerala Backwaters, Alappuzha",
+// time = "3 days ago",
+// point = Point.fromLngLat(76.3300, 9.4981) // Kerala Backwaters' latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.two,
+// location = "SIES GST NERUL",
+// time = "3 days ago",
+// point = Point.fromLngLat(73.0231, 19.0428) // Kerala Backwaters' latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.one, // Repeating image
+// location = "Hampi, Karnataka",
+// time = "4 days ago",
+// point = Point.fromLngLat(76.4741, 15.3350) // Hampi's latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.two, // Repeating image
+// location = "Lotus Temple, Delhi",
+// time = "5 days ago",
+// point = Point.fromLngLat(77.2647, 28.5535) // Lotus Temple's latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.three, // Repeating image
+// location = "Goa Beach, Goa",
+// time = "6 days ago",
+// point = Point.fromLngLat(73.7319, 15.2993) // Goa Beach's latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.one, // Repeating image
+// location = "Mysore Palace, Mysore",
+// time = "7 days ago",
+// point = Point.fromLngLat(76.6550, 12.3051) // Mysore Palace's latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.two, // Repeating image
+// location = "Jaisalmer Fort, Jaisalmer",
+// time = "8 days ago",
+// point = Point.fromLngLat(70.9100, 26.9124) // Jaisalmer Fort's latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.three, // Repeating image
+// location = "Kanchipuram Temples, Tamil Nadu",
+// time = "9 days ago",
+// point = Point.fromLngLat(79.7006, 12.8431) // Kanchipuram Temples' latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.one, // Repeating image
+// location = "Ajanta Caves, Maharashtra",
+// time = "10 days ago",
+// point = Point.fromLngLat(75.7050, 20.5513) // Ajanta Caves' latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.two, // Repeating image
+// location = "Sundarbans, West Bengal",
+// time = "11 days ago",
+// point = Point.fromLngLat(88.9763, 21.9497) // Sundarbans' latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.three, // Repeating image
+// location = "Dudhsagar Falls, Goa",
+// time = "12 days ago",
+// point = Point.fromLngLat(74.3192, 15.3145) // Dudhsagar Falls' latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.one, // Repeating image
+// location = "Shimla, Himachal Pradesh",
+// time = "13 days ago",
+// point = Point.fromLngLat(77.1734, 31.1048) // Shimla's latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.two, // Repeating image
+// location = "Kaziranga National Park, Assam",
+// time = "14 days ago",
+// point = Point.fromLngLat(93.2277, 26.6340) // Kaziranga National Park's latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.three, // Repeating image
+// location = "Puducherry Beach, Puducherry",
+// time = "15 days ago",
+// point = Point.fromLngLat(79.8083, 11.9416) // Puducherry Beach's latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.one, // Repeating image
+// location = "Mount Abu, Rajasthan",
+// time = "16 days ago",
+// point = Point.fromLngLat(72.8277, 24.5925) // Mount Abu's latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.two, // Repeating image
+// location = "Rann of Kutch, Gujarat",
+// time = "17 days ago",
+// point = Point.fromLngLat(69.8597, 23.7337) // Rann of Kutch's latitude and longitude
+// ),
+// MapItem(
+// image = R.drawable.three, // Repeating image
+// location = "Tawang Monastery, Arunachal Pradesh",
+// time = "18 days ago",
+// point = Point.fromLngLat(91.6274, 27.5860) // Tawang Monastery's latitude and longitude
+// ),
+// // Repeat the cycle of images as needed
+//)
+
+
+
+data class MapItem(
+ val image: Int,
+ val location: String,
+ val time: String,
+ val latitude: Double = 0.0,
+ val longitude: Double = 0.0,
+)
\ No newline at end of file
diff --git a/maps/src/main/java/com/example/mapbox_map/MapBoxMap.kt b/maps/src/main/java/com/example/mapbox_map/MapBoxMap.kt
new file mode 100644
index 0000000..c8b0771
--- /dev/null
+++ b/maps/src/main/java/com/example/mapbox_map/MapBoxMap.kt
@@ -0,0 +1,288 @@
+package com.example.mapbox_map
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.drawable.BitmapDrawable
+import android.graphics.drawable.Drawable
+import android.util.Log
+import androidx.annotation.DrawableRes
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.core.graphics.drawable.toBitmap
+import com.example.requestlocation.R
+import com.mapbox.android.gestures.StandardScaleGestureDetector
+import com.mapbox.geojson.Point
+import com.mapbox.maps.CameraOptions
+import com.mapbox.maps.MapView
+import com.mapbox.maps.Style
+import com.mapbox.maps.extension.style.atmosphere.generated.atmosphere
+import com.mapbox.maps.extension.style.expressions.dsl.generated.rgb
+import com.mapbox.maps.extension.style.expressions.dsl.generated.zoom
+import com.mapbox.maps.extension.style.layers.properties.generated.ProjectionName
+import com.mapbox.maps.extension.style.projection.generated.projection
+import com.mapbox.maps.extension.style.sources.generated.rasterDemSource
+import com.mapbox.maps.extension.style.style
+import com.mapbox.maps.extension.style.terrain.generated.terrain
+import com.mapbox.maps.plugin.animation.MapAnimationOptions
+import com.mapbox.maps.plugin.animation.flyTo
+import com.mapbox.maps.plugin.annotation.annotations
+import com.mapbox.maps.plugin.annotation.generated.PointAnnotationManager
+import com.mapbox.maps.plugin.annotation.generated.PointAnnotationOptions
+import com.mapbox.maps.plugin.annotation.generated.createPointAnnotationManager
+import com.mapbox.maps.plugin.gestures.OnScaleListener
+import com.mapbox.maps.plugin.gestures.gestures
+import com.mapbox.navigation.dropin.NavigationView
+
+@Composable
+fun MapBoxMap(
+ modifier: Modifier = Modifier,
+ onPointChange: (Point) -> Unit,
+ isClicked: MutableState = mutableStateOf(false),
+ isReset: MutableState = mutableStateOf(false),
+ points: List,
+ latitude: Double,
+ longitude: Double,
+ currentPoint: MutableState,
+) {
+
+ val context = LocalContext.current
+
+ val marker = remember(context) {
+ context.getDrawable(R.drawable.marker)!!.toBitmap()
+ }
+
+ var pointAnnotationManager: PointAnnotationManager? by remember {
+ mutableStateOf(null)
+ }
+
+
+
+ AndroidView(
+ factory = { context ->
+ val cameraOptions = CameraOptions.Builder()
+ .center(Point.fromLngLat(points[0].longitude, points[0].latitude))
+ .zoom(13.0)
+ .pitch(45.0)
+ .bearing(-17.6)
+ .build()
+ MapView(context).also { mapView ->
+ mapView.getMapboxMap().loadStyle(
+ style(Style.SATELLITE_STREETS) {
+ val zoom = zoom()
+ Log.i("Zoommmmmmmm", "${zoom.literalValue}")
+ +terrain("terrain-enable")
+ +projection(ProjectionName.MERCATOR)
+ +atmosphere {
+ color(rgb(220.0, 159.0, 159.0)) // Pink fog / lower atmosphere
+ highColor(rgb(220.0, 159.0, 159.0)) // Blue sky / upper atmosphere
+ horizonBlend(0.4) // Exaggerate atmosphere (default is .1)
+ }
+ +rasterDemSource("raster-dem") {
+ url("mapbox://mapbox.terrain-rgb")
+ }
+ +terrain("raster-dem") {
+ exaggeration(1.5)
+ }
+ }
+ )
+ isScalingOut(mapView) {
+ isClicked.value = false
+ }
+ mapView.getMapboxMap().flyTo(
+ cameraOptions,
+ MapAnimationOptions.mapAnimationOptions {
+ duration(5000L)
+ }
+ )
+
+
+// val annotationApi = mapView.annotations
+// pointAnnotationManager = annotationApi.createPointAnnotationManager()
+//
+// mapView.getMapboxMap().addOnMapClickListener { p ->
+// onPointChange(p)
+// true
+// }
+ }
+ },
+ update = { mapView ->
+ isScalingOut(mapView) {
+ isClicked.value = false
+ isReset.value = true
+ }
+ val cameraOptions = CameraOptions.Builder()
+ .center(Point.fromLngLat(longitude, latitude))
+ .zoom(currentPoint.value?.zoom ?: 3.0)
+ .build()
+ mapView.annotations.cleanup()
+ points.forEach { mapItem ->
+ addAnnotationToMap(
+ context = context,
+ mapView = mapView,
+ point = Point.fromLngLat(mapItem.longitude, mapItem.latitude),
+ icon = mapItem.image
+ )
+ }
+ if (isClicked.value) {
+ mapView.getMapboxMap().flyTo(
+ cameraOptions,
+ MapAnimationOptions.mapAnimationOptions {
+ duration(5000L)
+ }
+ )
+ }
+ if (isReset.value){
+ mapView.getMapboxMap().flyTo(
+ cameraOptions,
+ MapAnimationOptions.mapAnimationOptions {
+ duration(5000L)
+ }
+ )
+ }
+
+
+// if (point != null) {
+// pointAnnotationManager?.let {
+// it.deleteAll()
+// val pointAnnotationOptions = PointAnnotationOptions()
+// .withPoint(point)
+// .withIconImage(marker)
+//
+// it.create(pointAnnotationOptions)
+// mapView.getMapboxMap()
+// .flyTo(CameraOptions.Builder().zoom(16.0).center(point).build())
+// }
+// }
+// NoOpUpdate
+ },
+ modifier = modifier
+ )
+}
+
+fun addAnnotationToMap(
+ icon: Int,
+ context: Context,
+ mapView: MapView,
+ point: Point
+) {
+ bitmapFromDrawableRes(
+ context,
+ icon
+ )?.let {
+ val annotationApi = mapView.annotations
+ val pointAnnotationManager = annotationApi.createPointAnnotationManager()
+ val pointAnnotationOptions: PointAnnotationOptions = PointAnnotationOptions()
+ .withPoint(point)
+ .withIconImage(it)
+ pointAnnotationManager.create(pointAnnotationOptions)
+ }
+}
+
+private fun bitmapFromDrawableRes(context: Context, @DrawableRes resourceId: Int) =
+ convertDrawableToBitmap(AppCompatResources.getDrawable(context, resourceId))
+
+private fun convertDrawableToBitmap(sourceDrawable: Drawable?): Bitmap? {
+ if (sourceDrawable == null) {
+ return null
+ }
+ return if (sourceDrawable is BitmapDrawable) {
+ sourceDrawable.bitmap
+ } else {
+ val constantState = sourceDrawable.constantState ?: return null
+ val drawable = constantState.newDrawable().mutate()
+ val bitmap: Bitmap = Bitmap.createBitmap(
+ drawable.intrinsicWidth, drawable.intrinsicHeight,
+ Bitmap.Config.ARGB_8888
+ )
+ val canvas = Canvas(bitmap)
+ drawable.setBounds(0, 0, canvas.width, canvas.height)
+ drawable.draw(canvas)
+ bitmap
+ }
+}
+
+fun isScalingOut(
+ mapView: MapView,
+ onClick: () -> Unit = {}
+) {
+ mapView.gestures.addOnScaleListener(object : OnScaleListener {
+ override fun onScale(detector: StandardScaleGestureDetector) {
+ if (detector.isScalingOut) {
+ onClick()
+ }
+ }
+
+ override fun onScaleBegin(detector: StandardScaleGestureDetector) {
+ if (detector.isScalingOut) {
+ onClick()
+ }
+ }
+
+ override fun onScaleEnd(detector: StandardScaleGestureDetector) {
+ if (detector.isScalingOut) {
+ onClick()
+ }
+ }
+
+ })
+}
+
+
+@Composable
+fun MapBoxNavigation(
+ modifier: Modifier = Modifier,
+ onPointChange: (Point) -> Unit,
+ point: Point?,
+) {
+
+ val context = LocalContext.current
+
+ val marker = remember(context) {
+ context.getDrawable(R.drawable.marker)!!.toBitmap()
+ }
+
+ var pointAnnotationManager: PointAnnotationManager? by remember {
+ mutableStateOf(null)
+ }
+ val accessToken = stringResource(id = R.string.mapbox_access_token)
+
+
+
+
+
+ AndroidView(
+ factory = {
+ NavigationView(
+ context,
+ accessToken = accessToken,
+ ).also { navigationView ->
+
+ navigationView.api.routeReplayEnabled(true)
+ navigationView.api.startArrival()
+
+ }
+ },
+ update = { mapView ->
+
+ },
+ modifier = modifier
+ )
+}
+
+data class MapBoxPoint(
+ val latitude: Double,
+ val longitude: Double,
+ val zoom: Double = 15.0,
+ val pitch: Double = 10.0,
+ val bearing: Double = 1.0
+)
\ No newline at end of file
diff --git a/maps/src/main/java/com/example/mapbox_map/MyApp.kt b/maps/src/main/java/com/example/mapbox_map/MyApp.kt
new file mode 100644
index 0000000..c526791
--- /dev/null
+++ b/maps/src/main/java/com/example/mapbox_map/MyApp.kt
@@ -0,0 +1,21 @@
+package com.example.mapbox_map
+
+import android.app.Application
+import com.example.requestlocation.R
+import com.mapbox.navigation.base.options.NavigationOptions
+import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
+
+class MyApp : Application() {
+ override fun onCreate() {
+ super.onCreate()
+ if (!MapboxNavigationApp.isSetup()) {
+ MapboxNavigationApp.setup {
+ NavigationOptions.Builder(applicationContext = applicationContext)
+ .accessToken(R.string.mapbox_access_token.toString())
+ // additional options
+ .build()
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/maps/src/main/java/com/example/mapbox_map/PreviewMap.kt b/maps/src/main/java/com/example/mapbox_map/PreviewMap.kt
new file mode 100644
index 0000000..cf9bec6
--- /dev/null
+++ b/maps/src/main/java/com/example/mapbox_map/PreviewMap.kt
@@ -0,0 +1,156 @@
+package com.example.mapbox_map
+
+import android.util.Log
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.core.graphics.drawable.toBitmap
+import com.example.requestlocation.R
+import com.mapbox.geojson.Point
+import com.mapbox.maps.CameraOptions
+import com.mapbox.maps.MapView
+import com.mapbox.maps.Style
+import com.mapbox.maps.extension.style.atmosphere.generated.atmosphere
+import com.mapbox.maps.extension.style.expressions.dsl.generated.rgb
+import com.mapbox.maps.extension.style.expressions.dsl.generated.zoom
+import com.mapbox.maps.extension.style.layers.properties.generated.ProjectionName
+import com.mapbox.maps.extension.style.projection.generated.projection
+import com.mapbox.maps.extension.style.sources.generated.rasterDemSource
+import com.mapbox.maps.extension.style.style
+import com.mapbox.maps.extension.style.terrain.generated.terrain
+import com.mapbox.maps.plugin.animation.MapAnimationOptions
+import com.mapbox.maps.plugin.animation.flyTo
+import com.mapbox.maps.plugin.annotation.annotations
+import com.mapbox.maps.plugin.annotation.generated.PointAnnotationManager
+
+@Composable
+fun PreviewMap(
+ modifier: Modifier = Modifier,
+ onPointChange: (Point) -> Unit,
+ isClicked: MutableState = mutableStateOf(false),
+ isReset: MutableState = mutableStateOf(false),
+ points: List,
+ latitude: Double,
+ longitude: Double,
+ currentPoint: MutableState,
+) {
+
+ val context = LocalContext.current
+
+ val marker = remember(context) {
+ context.getDrawable(R.drawable.marker)!!.toBitmap()
+ }
+
+ var pointAnnotationManager: PointAnnotationManager? by remember {
+ mutableStateOf(null)
+ }
+
+
+
+ AndroidView(
+ factory = { context ->
+ val cameraOptions = CameraOptions.Builder()
+ .center(Point.fromLngLat(points[0].longitude, points[0].latitude))
+ .zoom(13.0)
+ .pitch(45.0)
+ .bearing(-17.6)
+ .build()
+ MapView(context).also { mapView ->
+ mapView.getMapboxMap().loadStyle(
+ style(Style.SATELLITE_STREETS) {
+ val zoom = zoom()
+ Log.i("Zoommmmmmmm", "${zoom.literalValue}")
+ +terrain("terrain-enable")
+ +projection(ProjectionName.MERCATOR)
+ +atmosphere {
+ color(rgb(220.0, 159.0, 159.0)) // Pink fog / lower atmosphere
+ highColor(rgb(220.0, 159.0, 159.0)) // Blue sky / upper atmosphere
+ horizonBlend(0.4) // Exaggerate atmosphere (default is .1)
+ }
+ +rasterDemSource("raster-dem") {
+ url("mapbox://mapbox.terrain-rgb")
+ }
+ +terrain("raster-dem") {
+ exaggeration(1.5)
+ }
+ }
+ )
+ isScalingOut(mapView) {
+ isClicked.value = false
+ }
+ mapView.getMapboxMap().flyTo(
+ cameraOptions,
+ MapAnimationOptions.mapAnimationOptions {
+ duration(5000L)
+ }
+ )
+
+
+// val annotationApi = mapView.annotations
+// pointAnnotationManager = annotationApi.createPointAnnotationManager()
+//
+// mapView.getMapboxMap().addOnMapClickListener { p ->
+// onPointChange(p)
+// true
+// }
+ }
+ },
+ update = { mapView ->
+ isScalingOut(mapView) {
+ isClicked.value = false
+ isReset.value = true
+ }
+ val cameraOptions = CameraOptions.Builder()
+ .center(Point.fromLngLat(longitude, latitude))
+ .zoom(currentPoint.value?.zoom ?: 3.0)
+ .build()
+ mapView.annotations.cleanup()
+ points.forEach { mapItem ->
+ addAnnotationToMap(
+ context = context,
+ mapView = mapView,
+ point = Point.fromLngLat(mapItem.longitude, mapItem.latitude),
+ icon = mapItem.image
+ )
+ }
+ if (isClicked.value) {
+ mapView.getMapboxMap().flyTo(
+ cameraOptions,
+ MapAnimationOptions.mapAnimationOptions {
+ duration(5000L)
+ }
+ )
+ }
+ if (isReset.value){
+ mapView.getMapboxMap().flyTo(
+ cameraOptions,
+ MapAnimationOptions.mapAnimationOptions {
+ duration(5000L)
+ }
+ )
+ }
+
+
+// if (point != null) {
+// pointAnnotationManager?.let {
+// it.deleteAll()
+// val pointAnnotationOptions = PointAnnotationOptions()
+// .withPoint(point)
+// .withIconImage(marker)
+//
+// it.create(pointAnnotationOptions)
+// mapView.getMapboxMap()
+// .flyTo(CameraOptions.Builder().zoom(16.0).center(point).build())
+// }
+// }
+// NoOpUpdate
+ },
+ modifier = modifier
+ )
+}
\ No newline at end of file
diff --git a/maps/src/main/java/com/example/mapbox_map/ui/LocationService.kt b/maps/src/main/java/com/example/mapbox_map/ui/LocationService.kt
new file mode 100644
index 0000000..ea5ef48
--- /dev/null
+++ b/maps/src/main/java/com/example/mapbox_map/ui/LocationService.kt
@@ -0,0 +1,69 @@
+package com.example.mapbox_map.ui
+
+import android.Manifest
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.pm.PackageManager
+import android.location.Location
+import android.location.LocationManager
+import androidx.core.app.ActivityCompat
+import com.google.android.gms.location.CurrentLocationRequest
+import com.google.android.gms.location.LocationServices
+import com.google.android.gms.location.Priority
+import kotlinx.coroutines.tasks.await
+
+class LocationService {
+
+ @SuppressLint("MissingPermission")
+ suspend fun getCurrentLocation(context: Context): Location {
+
+ if (!context.hasPermissions(
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ Manifest.permission.ACCESS_COARSE_LOCATION
+ )
+ ) {
+ throw throw LocationServiceException.MissingPermissionException()
+ }
+
+ val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
+ val isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
+ val isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
+
+ if (!isGpsEnabled) {
+ throw LocationServiceException.LocationDisabledException()
+ }
+ if (!isNetworkEnabled) {
+ throw LocationServiceException.NoNetworkEnabledException()
+ }
+
+ val locationProvider = LocationServices.getFusedLocationProviderClient(context)
+ val request = CurrentLocationRequest.Builder()
+ .setPriority(Priority.PRIORITY_HIGH_ACCURACY)
+ .build()
+
+
+ try {
+ val location = locationProvider.getCurrentLocation(request, null).await()
+
+ return location
+
+ } catch (e: Exception) {
+ throw LocationServiceException.UnknownException(e)
+ }
+
+ }
+
+ fun Context.hasPermissions(vararg permissions: String) =
+ permissions.all {
+ ActivityCompat.checkSelfPermission(this, it) == PackageManager.PERMISSION_GRANTED
+ }
+
+
+ sealed class LocationServiceException : Exception() {
+ class MissingPermissionException : LocationServiceException()
+ class LocationDisabledException : LocationServiceException()
+ class NoNetworkEnabledException : LocationServiceException()
+ class UnknownException(val exception: Exception) : LocationServiceException()
+ }
+
+}
\ No newline at end of file
diff --git a/maps/src/main/java/com/example/mapbox_map/ui/theme/Color.kt b/maps/src/main/java/com/example/mapbox_map/ui/theme/Color.kt
new file mode 100644
index 0000000..d5192f8
--- /dev/null
+++ b/maps/src/main/java/com/example/mapbox_map/ui/theme/Color.kt
@@ -0,0 +1,11 @@
+package com.example.mapbox_map.ui.theme
+
+import androidx.compose.ui.graphics.Color
+
+val Purple80 = Color(0xFFD0BCFF)
+val PurpleGrey80 = Color(0xFFCCC2DC)
+val Pink80 = Color(0xFFEFB8C8)
+
+val Purple40 = Color(0xFF6650a4)
+val PurpleGrey40 = Color(0xFF625b71)
+val Pink40 = Color(0xFF7D5260)
\ No newline at end of file
diff --git a/maps/src/main/java/com/example/mapbox_map/ui/theme/Theme.kt b/maps/src/main/java/com/example/mapbox_map/ui/theme/Theme.kt
new file mode 100644
index 0000000..2adf272
--- /dev/null
+++ b/maps/src/main/java/com/example/mapbox_map/ui/theme/Theme.kt
@@ -0,0 +1,70 @@
+package com.example.mapbox_map.ui.theme
+
+import android.app.Activity
+import android.os.Build
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.darkColorScheme
+import androidx.compose.material3.dynamicDarkColorScheme
+import androidx.compose.material3.dynamicLightColorScheme
+import androidx.compose.material3.lightColorScheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.SideEffect
+import androidx.compose.ui.graphics.toArgb
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.platform.LocalView
+import androidx.core.view.WindowCompat
+
+private val DarkColorScheme = darkColorScheme(
+ primary = Purple80,
+ secondary = PurpleGrey80,
+ tertiary = Pink80
+)
+
+private val LightColorScheme = lightColorScheme(
+ primary = Purple40,
+ secondary = PurpleGrey40,
+ tertiary = Pink40
+
+ /* Other default colors to override
+ background = Color(0xFFFFFBFE),
+ surface = Color(0xFFFFFBFE),
+ onPrimary = Color.White,
+ onSecondary = Color.White,
+ onTertiary = Color.White,
+ onBackground = Color(0xFF1C1B1F),
+ onSurface = Color(0xFF1C1B1F),
+ */
+)
+
+@Composable
+fun RequestLocationTheme(
+ darkTheme: Boolean = isSystemInDarkTheme(),
+ // Dynamic color is available on Android 12+
+ dynamicColor: Boolean = true,
+ content: @Composable () -> Unit
+) {
+ val colorScheme = when {
+ dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
+ val context = LocalContext.current
+ if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
+ }
+
+ darkTheme -> DarkColorScheme
+ else -> LightColorScheme
+ }
+ val view = LocalView.current
+ if (!view.isInEditMode) {
+ SideEffect {
+ val window = (view.context as Activity).window
+ window.statusBarColor = colorScheme.primary.toArgb()
+ WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
+ }
+ }
+
+ MaterialTheme(
+ colorScheme = colorScheme,
+ typography = Typography,
+ content = content
+ )
+}
\ No newline at end of file
diff --git a/maps/src/main/java/com/example/mapbox_map/ui/theme/Type.kt b/maps/src/main/java/com/example/mapbox_map/ui/theme/Type.kt
new file mode 100644
index 0000000..a1fb729
--- /dev/null
+++ b/maps/src/main/java/com/example/mapbox_map/ui/theme/Type.kt
@@ -0,0 +1,34 @@
+package com.example.mapbox_map.ui.theme
+
+import androidx.compose.material3.Typography
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.font.FontFamily
+import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.unit.sp
+
+// Set of Material typography styles to start with
+val Typography = Typography(
+ bodyLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ letterSpacing = 0.5.sp
+ )
+ /* Other default text styles to override
+ titleLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 22.sp,
+ lineHeight = 28.sp,
+ letterSpacing = 0.sp
+ ),
+ labelSmall = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Medium,
+ fontSize = 11.sp,
+ lineHeight = 16.sp,
+ letterSpacing = 0.5.sp
+ )
+ */
+)
\ No newline at end of file
diff --git a/maps/src/main/res/drawable-v24/ic_launcher_foreground.xml b/maps/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ b/maps/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/maps/src/main/res/drawable/app_icon.png b/maps/src/main/res/drawable/app_icon.png
new file mode 100644
index 0000000..e3d3ce3
Binary files /dev/null and b/maps/src/main/res/drawable/app_icon.png differ
diff --git a/maps/src/main/res/drawable/appicon.png b/maps/src/main/res/drawable/appicon.png
new file mode 100644
index 0000000..c8b2acf
Binary files /dev/null and b/maps/src/main/res/drawable/appicon.png differ
diff --git a/maps/src/main/res/drawable/appicons.jpg b/maps/src/main/res/drawable/appicons.jpg
new file mode 100644
index 0000000..05431c6
Binary files /dev/null and b/maps/src/main/res/drawable/appicons.jpg differ
diff --git a/maps/src/main/res/drawable/ic_appicon.png b/maps/src/main/res/drawable/ic_appicon.png
new file mode 100644
index 0000000..a6cca46
Binary files /dev/null and b/maps/src/main/res/drawable/ic_appicon.png differ
diff --git a/maps/src/main/res/drawable/ic_launcher_background.xml b/maps/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..07d5da9
--- /dev/null
+++ b/maps/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/maps/src/main/res/drawable/marker.xml b/maps/src/main/res/drawable/marker.xml
new file mode 100644
index 0000000..596040d
--- /dev/null
+++ b/maps/src/main/res/drawable/marker.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/maps/src/main/res/drawable/one.jpg b/maps/src/main/res/drawable/one.jpg
new file mode 100644
index 0000000..d6a2b46
Binary files /dev/null and b/maps/src/main/res/drawable/one.jpg differ
diff --git a/maps/src/main/res/drawable/three.jpg b/maps/src/main/res/drawable/three.jpg
new file mode 100644
index 0000000..48e758a
Binary files /dev/null and b/maps/src/main/res/drawable/three.jpg differ
diff --git a/maps/src/main/res/drawable/two.jpg b/maps/src/main/res/drawable/two.jpg
new file mode 100644
index 0000000..758fc4c
Binary files /dev/null and b/maps/src/main/res/drawable/two.jpg differ
diff --git a/maps/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/maps/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..6f3b755
--- /dev/null
+++ b/maps/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/maps/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/maps/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..6f3b755
--- /dev/null
+++ b/maps/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/maps/src/main/res/mipmap-hdpi/ic_launcher.webp b/maps/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 0000000..c209e78
Binary files /dev/null and b/maps/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/maps/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/maps/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..b2dfe3d
Binary files /dev/null and b/maps/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/maps/src/main/res/mipmap-mdpi/ic_launcher.webp b/maps/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 0000000..4f0f1d6
Binary files /dev/null and b/maps/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/maps/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/maps/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..62b611d
Binary files /dev/null and b/maps/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/maps/src/main/res/mipmap-xhdpi/ic_launcher.webp b/maps/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 0000000..948a307
Binary files /dev/null and b/maps/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/maps/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/maps/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..1b9a695
Binary files /dev/null and b/maps/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/maps/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/maps/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..28d4b77
Binary files /dev/null and b/maps/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/maps/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/maps/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..9287f50
Binary files /dev/null and b/maps/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/maps/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/maps/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..aa7d642
Binary files /dev/null and b/maps/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/maps/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/maps/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..9126ae3
Binary files /dev/null and b/maps/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/maps/src/main/res/values/colors.xml b/maps/src/main/res/values/colors.xml
new file mode 100644
index 0000000..f8c6127
--- /dev/null
+++ b/maps/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/maps/src/main/res/values/strings.xml b/maps/src/main/res/values/strings.xml
new file mode 100644
index 0000000..fc50dbd
--- /dev/null
+++ b/maps/src/main/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+ pk.eyJ1IjoidGhla2FhaWxhc2hzaGFybWEiLCJhIjoiY2xtNm9sbW00MnY4bTNlbzl2c2Y2Z3g3byJ9.HZmK-5aP8z6hVA8IIU0q6A
+ MapBoxMap
+
\ No newline at end of file
diff --git a/maps/src/main/res/values/themes.xml b/maps/src/main/res/values/themes.xml
new file mode 100644
index 0000000..3da3284
--- /dev/null
+++ b/maps/src/main/res/values/themes.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/maps/src/main/res/xml/backup_rules.xml b/maps/src/main/res/xml/backup_rules.xml
new file mode 100644
index 0000000..fa0f996
--- /dev/null
+++ b/maps/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,13 @@
+
+
+
+
\ No newline at end of file
diff --git a/maps/src/main/res/xml/data_extraction_rules.xml b/maps/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 0000000..9ee9997
--- /dev/null
+++ b/maps/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/maps/src/test/java/com/example/mapbox_map/ExampleUnitTest.kt b/maps/src/test/java/com/example/mapbox_map/ExampleUnitTest.kt
new file mode 100644
index 0000000..9774382
--- /dev/null
+++ b/maps/src/test/java/com/example/mapbox_map/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.example.mapbox_map
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..91c8d52
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,33 @@
+pluginManagement {
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ maven { url = uri("https://jitpack.io") }
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ maven { url = uri("https://jitpack.io") }
+ maven {
+ url 'https://api.mapbox.com/downloads/v2/releases/maven'
+ authentication {
+ basic(BasicAuthentication)
+ }
+ credentials {
+ // Do not change the username below.
+ // This should always be `mapbox` (not your username).
+ username = "mapbox"
+ // Use the secret token you stored in gradle.properties as the password
+ password = MAPBOX_DOWNLOADS_TOKEN
+ }
+ }
+ }
+}
+
+rootProject.name = "AI Travel Manager"
+include(":app")
+include(":maps")
diff --git a/settings.gradle.kts b/settings.gradle.kts
deleted file mode 100644
index bf051f2..0000000
--- a/settings.gradle.kts
+++ /dev/null
@@ -1,19 +0,0 @@
-pluginManagement {
- repositories {
- google()
- mavenCentral()
- gradlePluginPortal()
- maven { url = uri("https://jitpack.io") }
- }
-}
-dependencyResolutionManagement {
- repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
- repositories {
- google()
- mavenCentral()
- maven { url = uri("https://jitpack.io") }
- }
-}
-
-rootProject.name = "AI Travel Manager"
-include(":app")