Skip to content

Commit 4434dc5

Browse files
committed
refactor: Update MapUtils, MapUiState, and GmApp
1 parent db5e0d4 commit 4434dc5

File tree

5 files changed

+88
-105
lines changed

5 files changed

+88
-105
lines changed

app/src/main/kotlin/com/espressodev/gptmap/GmApp.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.WindowInsets
66
import androidx.compose.foundation.layout.fillMaxSize
77
import androidx.compose.foundation.layout.padding
88
import androidx.compose.material.BottomNavigation
9+
import androidx.compose.material3.BottomAppBar
910
import androidx.compose.material3.Icon
1011
import androidx.compose.material3.MaterialTheme
1112
import androidx.compose.material3.NavigationBarItem
@@ -15,6 +16,7 @@ import androidx.compose.material3.Snackbar
1516
import androidx.compose.material3.SnackbarHost
1617
import androidx.compose.material3.SnackbarHostState
1718
import androidx.compose.material3.Surface
19+
import androidx.compose.material3.Text
1820
import androidx.compose.runtime.Composable
1921
import androidx.compose.runtime.ReadOnlyComposable
2022
import androidx.compose.runtime.remember
@@ -86,9 +88,10 @@ fun GmBottomNavigation(
8688
modifier: Modifier = Modifier,
8789
) {
8890
if (currentTopLevelDestination == null) return
89-
BottomNavigation(
91+
BottomAppBar(
9092
modifier = modifier,
91-
backgroundColor = MaterialTheme.colorScheme.surfaceVariant
93+
containerColor = MaterialTheme.colorScheme.surfaceVariant,
94+
contentColor = MaterialTheme.colorScheme.onSurfaceVariant
9295
) {
9396
destinations.forEach { destination ->
9497
val selected = currentDestination.isTopLevelDestinationInHierarchy(destination)
@@ -108,6 +111,9 @@ fun GmBottomNavigation(
108111
tint = MaterialTheme.colorScheme.primary
109112
)
110113
},
114+
label = {
115+
Text(text = stringResource(id = destination.contentDesc))
116+
}
111117
)
112118
}
113119
}

feature/map/src/main/kotlin/com/espressodev/gptmap/feature/map/MapScreen.kt

Lines changed: 65 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import androidx.compose.animation.core.animateFloatAsState
99
import androidx.compose.animation.core.tween
1010
import androidx.compose.foundation.ExperimentalFoundationApi
1111
import androidx.compose.foundation.Image
12-
import androidx.compose.foundation.isSystemInDarkTheme
1312
import androidx.compose.foundation.layout.Arrangement
1413
import androidx.compose.foundation.layout.Box
1514
import androidx.compose.foundation.layout.BoxScope
@@ -32,7 +31,6 @@ import androidx.compose.material3.Surface
3231
import androidx.compose.material3.Text
3332
import androidx.compose.runtime.Composable
3433
import androidx.compose.runtime.LaunchedEffect
35-
import androidx.compose.runtime.derivedStateOf
3634
import androidx.compose.runtime.getValue
3735
import androidx.compose.runtime.mutableStateOf
3836
import androidx.compose.runtime.remember
@@ -82,12 +80,9 @@ import com.espressodev.gptmap.feature.map.MapBottomSheetState.DETAIL_CARD
8280
import com.espressodev.gptmap.feature.map.MapBottomSheetState.SMALL_INFORMATION_CARD
8381
import com.google.android.gms.maps.CameraUpdateFactory
8482
import com.google.android.gms.maps.model.CameraPosition
85-
import com.google.android.gms.maps.model.LatLng
8683
import com.google.android.gms.maps.model.MapStyleOptions
87-
import com.google.maps.android.compose.CameraPositionState
8884
import com.google.maps.android.compose.GoogleMap
8985
import com.google.maps.android.compose.MapProperties
90-
import com.google.maps.android.compose.MapUiSettings
9186
import com.google.maps.android.compose.rememberCameraPositionState
9287
import kotlin.math.absoluteValue
9388
import com.espressodev.gptmap.core.designsystem.R.drawable as AppDrawable
@@ -105,9 +100,7 @@ fun MapRoute(
105100
viewModel: MapViewModel = hiltViewModel(),
106101
) {
107102
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
108-
Scaffold(
109-
modifier = modifier
110-
) {
103+
Scaffold(modifier = modifier) {
111104
MapScreen(
112105
uiState = uiState,
113106
onEvent = { event ->
@@ -118,18 +111,10 @@ fun MapRoute(
118111
}
119112
)
120113
},
121-
onAvatarClick = navigateToProfile
114+
onAvatarClick = navigateToProfile,
115+
navigateToScreenshot = navigateToScreenshot
122116
)
123117
}
124-
SaveScreenshot(
125-
onSuccess = {
126-
navigateToScreenshot()
127-
viewModel.reset()
128-
},
129-
onConfirm = {
130-
viewModel.onEvent(MapUiEvent.OnScreenshotProcessStarted)
131-
}
132-
)
133118

134119
LaunchedEffect(favouriteId) {
135120
if (favouriteId != "default")
@@ -142,17 +127,9 @@ private fun MapScreen(
142127
uiState: MapUiState,
143128
onEvent: (MapUiEvent) -> Unit,
144129
onAvatarClick: () -> Unit,
130+
navigateToScreenshot: () -> Unit,
145131
modifier: Modifier = Modifier,
146132
) {
147-
val latLng by remember(uiState.location) {
148-
derivedStateOf {
149-
uiState.getCoordinates().let { LatLng(it.first, it.second) }
150-
}
151-
}
152-
val cameraPositionState = rememberCameraPositionState {
153-
position = CameraPosition.fromLatLngZoom(latLng, 13f)
154-
}
155-
AnimateCameraPosition(uiState.getCoordinates(), cameraPositionState)
156133
DisplayImageGallery(
157134
imageGalleryState = uiState.imageGalleryState,
158135
location = uiState.location,
@@ -171,24 +148,23 @@ private fun MapScreen(
171148
.align(Alignment.TopCenter)
172149
)
173150
}
174-
GmDraggableButton(icon = StreetView, initialAlignment = Alignment.CenterStart)
151+
SaveScreenshot(
152+
onSuccess = {
153+
navigateToScreenshot()
154+
onEvent(MapUiEvent.OnScreenshotProcessFinished)
155+
},
156+
onConfirm = { onEvent(MapUiEvent.OnScreenshotProcessStarted) },
157+
)
175158
LoadingDialog(uiState.componentLoadingState)
176159
MapSection(
177160
isPinVisible = uiState.isLocationPinVisible,
178-
cameraPositionState = cameraPositionState
161+
uiState = uiState,
162+
onEvent = onEvent
179163
)
180-
DisplayBottomSheet(uiState.bottomSheetState, uiState.location, cameraPositionState, onEvent)
181-
}
182-
}
183-
184-
@Composable
185-
private fun AnimateCameraPosition(
186-
latLng: Pair<Double, Double>,
187-
cameraPositionState: CameraPositionState
188-
) {
189-
LaunchedEffect(latLng) {
190-
cameraPositionState.animate(
191-
CameraUpdateFactory.newLatLng(LatLng(latLng.first, latLng.second))
164+
DisplayBottomSheet(
165+
bottomSheetState = uiState.bottomSheetState,
166+
location = uiState.location,
167+
onEvent = onEvent
192168
)
193169
}
194170
}
@@ -212,7 +188,6 @@ private fun DisplayImageGallery(
212188
private fun BoxScope.DisplayBottomSheet(
213189
bottomSheetState: MapBottomSheetState,
214190
location: Location,
215-
cameraPositionState: CameraPositionState,
216191
onEvent: (MapUiEvent) -> Unit
217192
) {
218193
when (bottomSheetState) {
@@ -221,16 +196,11 @@ private fun BoxScope.DisplayBottomSheet(
221196
content = location.content,
222197
onExploreWithAiClick = { onEvent(MapUiEvent.OnExploreWithAiClick) },
223198
onBackClick = { onEvent(MapUiEvent.OnBackClick) },
224-
onStreetViewClick = { onEvent(MapUiEvent.OnStreetViewClick(cameraPositionState.toLatitudeLongitude())) }
225199
)
226200
}
227201

228202
DETAIL_CARD -> {
229-
DetailSheet(
230-
location,
231-
onEvent = onEvent,
232-
onStreetViewClick = { onEvent(MapUiEvent.OnStreetViewClick(cameraPositionState.toLatitudeLongitude())) }
233-
)
203+
DetailSheet(location = location, onEvent = onEvent)
234204
}
235205

236206
BOTTOM_SHEET_HIDDEN -> {}
@@ -296,62 +266,68 @@ private fun MapSearchBar(
296266
}
297267

298268
@Composable
299-
private fun MapSection(isPinVisible: Boolean, cameraPositionState: CameraPositionState) {
300-
val context = LocalContext.current
301-
val isSystemInDarkTheme = isSystemInDarkTheme()
269+
private fun MapSection(uiState: MapUiState, isPinVisible: Boolean, onEvent: (MapUiEvent) -> Unit) {
302270
var isMapLoaded by remember { mutableStateOf(value = false) }
271+
val context = LocalContext.current
272+
val latLng = uiState.getCoordinates()
303273
val mapProperties = remember {
304-
if (isSystemInDarkTheme) {
305-
MapProperties(
306-
mapStyleOptions = MapStyleOptions.loadRawResourceStyle(
307-
context,
308-
AppRaw.dark_map_style
309-
)
274+
MapProperties(
275+
mapStyleOptions = MapStyleOptions.loadRawResourceStyle(
276+
context,
277+
AppRaw.map_style
310278
)
311-
} else {
312-
MapProperties()
313-
}
279+
)
314280
}
315281

316-
Box(modifier = Modifier.fillMaxSize()) {
317-
MapContent(
318-
isPinVisible = isPinVisible,
319-
cameraPositionState = cameraPositionState,
320-
mapProperties = mapProperties
321-
) {
322-
isMapLoaded = true
323-
}
282+
val cameraPositionState = rememberCameraPositionState {
283+
position = CameraPosition.fromLatLngZoom(latLng, 14f)
324284
}
325285

326286
if (!isMapLoaded) {
327287
LottieAnimationPlaceholder(AppRaw.transistor_earth)
328288
}
329-
}
330289

331-
@Composable
332-
private fun BoxScope.MapContent(
333-
isPinVisible: Boolean,
334-
cameraPositionState: CameraPositionState,
335-
mapProperties: MapProperties,
336-
onMapLoaded: () -> Unit
337-
) {
338-
LocationPin(isPinVisible = isPinVisible, isCameraMoving = cameraPositionState.isMoving)
339-
GoogleMap(
340-
modifier = Modifier.fillMaxSize(),
341-
cameraPositionState = cameraPositionState,
342-
uiSettings = MapUiSettings(zoomControlsEnabled = false),
343-
properties = mapProperties,
344-
onMapLoaded = onMapLoaded
345-
)
290+
LaunchedEffect(uiState.getCoordinates()) {
291+
cameraPositionState.animate(CameraUpdateFactory.newLatLng(latLng))
292+
}
293+
294+
Box(modifier = Modifier.fillMaxSize()) {
295+
AnimatedVisibility(
296+
visible = uiState.isStreetViewButtonVisible,
297+
modifier = Modifier.zIndex(1f)
298+
) {
299+
GmDraggableButton(
300+
icon = StreetView,
301+
initialAlignment = Alignment.CenterStart,
302+
onClick = {
303+
onEvent(MapUiEvent.OnStreetViewClick(cameraPositionState.toLatitudeLongitude()))
304+
}
305+
)
306+
}
307+
LocationPin(isPinVisible = isPinVisible, isCameraMoving = cameraPositionState.isMoving)
308+
GoogleMap(
309+
modifier = Modifier.fillMaxSize(),
310+
cameraPositionState = cameraPositionState,
311+
properties = mapProperties,
312+
onMapLoaded = { isMapLoaded = true }
313+
)
314+
}
346315
}
347316

348317
@Composable
349-
private fun BoxScope.LoadingDialog(loadingState: ComponentLoadingState) {
318+
private fun BoxScope.LoadingDialog(
319+
loadingState: ComponentLoadingState,
320+
modifier: Modifier = Modifier
321+
) {
350322
AnimatedVisibility(
351323
visible = loadingState != ComponentLoadingState.NOTHING,
352-
modifier = Modifier
324+
modifier = modifier
353325
.zIndex(1f)
354-
.align(Alignment.Center)
326+
.align(Alignment.TopCenter)
327+
.statusBarsPadding()
328+
.fillMaxWidth()
329+
.padding(top = 64.dp)
330+
.padding(horizontal = 32.dp)
355331
) {
356332
val textId: Int =
357333
when (loadingState) {
@@ -371,8 +347,8 @@ private fun BoxScope.LoadingDialog(loadingState: ComponentLoadingState) {
371347
Text(
372348
text = stringResource(textId),
373349
textAlign = TextAlign.Center,
374-
style = MaterialTheme.typography.titleSmall,
375-
fontWeight = FontWeight.Medium
350+
style = MaterialTheme.typography.titleMedium,
351+
fontWeight = FontWeight.Medium,
376352
)
377353
}
378354
}
@@ -429,7 +405,6 @@ fun BoxScope.SmallInformationCard(
429405
content: Content,
430406
onExploreWithAiClick: () -> Unit,
431407
onBackClick: () -> Unit,
432-
onStreetViewClick: () -> Unit,
433408
modifier: Modifier = Modifier
434409
) {
435410
BackHandler(onBack = onBackClick)
@@ -444,11 +419,6 @@ fun BoxScope.SmallInformationCard(
444419
contentDesc = AppText.back_arrow,
445420
onClick = onBackClick,
446421
)
447-
SquareButton(
448-
icon = IconType.Bitmap(AppDrawable.street_view),
449-
contentDesc = AppText.search,
450-
onClick = onStreetViewClick,
451-
)
452422

453423
Surface(
454424
shape = RoundedCornerShape(16.dp),

feature/map/src/main/kotlin/com/espressodev/gptmap/feature/map/MapUiState.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.espressodev.gptmap.feature.map
22

33
import com.espressodev.gptmap.core.model.Location
4+
import com.google.android.gms.maps.model.LatLng
45

56
enum class MapBottomSheetState {
67
SMALL_INFORMATION_CARD, DETAIL_CARD, BOTTOM_SHEET_HIDDEN
@@ -21,11 +22,12 @@ data class MapUiState(
2122
val searchBarState: Boolean = true,
2223
val isFavouriteButtonPlaying: Boolean = false,
2324
val isLocationPinVisible: Boolean = true,
25+
val isStreetViewButtonVisible: Boolean = true,
2426
val takeScreenshotState: Boolean = false,
2527
val imageGalleryState: Pair<Int, Boolean> = Pair(0, false)
2628
) {
27-
fun getCoordinates(): Pair<Double, Double> =
28-
location.content.coordinates.let { Pair(it.latitude, it.longitude) }
29+
fun getCoordinates(): LatLng =
30+
location.content.coordinates.let { LatLng(it.latitude, it.longitude) }
2931
}
3032

3133
sealed class MapUiEvent {
@@ -38,6 +40,7 @@ sealed class MapUiEvent {
3840
data object OnBackClick: MapUiEvent()
3941
data object OnExploreWithAiClick: MapUiEvent()
4042
data object OnScreenshotProcessStarted: MapUiEvent()
43+
data object OnScreenshotProcessFinished: MapUiEvent()
4144
data object OnTakeScreenshotClick: MapUiEvent()
4245
data class OnStreetViewClick(val latLng: Pair<Double, Double>) : MapUiEvent()
4346
}

feature/map/src/main/kotlin/com/espressodev/gptmap/feature/map/MapUtils.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ enum class Status {
8181

8282
enum class Source(var value: String) {
8383
DEFAULT("default"),
84-
OUTDOOR("outdoor");
84+
OUTDOOR("outdoor")
8585
}
8686

8787
fun CameraPositionState.toLatitudeLongitude(): Pair<Double, Double> =

0 commit comments

Comments
 (0)