2025-04-13 00:51:32 +10:00
|
|
|
package moe.lava.banksia
|
|
|
|
|
|
2025-04-14 02:02:06 +10:00
|
|
|
import androidx.compose.foundation.layout.Box
|
2025-04-14 23:40:54 +10:00
|
|
|
import androidx.compose.foundation.layout.WindowInsets
|
|
|
|
|
import androidx.compose.foundation.layout.add
|
2025-04-13 01:27:49 +10:00
|
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
2025-04-14 23:40:54 +10:00
|
|
|
import androidx.compose.foundation.layout.safeContent
|
|
|
|
|
import androidx.compose.foundation.layout.safeDrawing
|
|
|
|
|
import androidx.compose.foundation.layout.windowInsetsPadding
|
2025-04-14 02:02:06 +10:00
|
|
|
import androidx.compose.material3.BottomSheetScaffold
|
|
|
|
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
2025-04-14 23:40:54 +10:00
|
|
|
import androidx.compose.material3.FloatingActionButton
|
|
|
|
|
import androidx.compose.material3.Icon
|
2025-04-14 13:35:26 +10:00
|
|
|
import androidx.compose.material3.MaterialTheme
|
2025-04-14 02:02:06 +10:00
|
|
|
import androidx.compose.material3.SheetValue
|
|
|
|
|
import androidx.compose.material3.rememberBottomSheetScaffoldState
|
|
|
|
|
import androidx.compose.material3.rememberStandardBottomSheetState
|
2025-04-14 13:35:26 +10:00
|
|
|
import androidx.compose.runtime.Composable
|
|
|
|
|
import androidx.compose.runtime.getValue
|
|
|
|
|
import androidx.compose.runtime.mutableStateOf
|
|
|
|
|
import androidx.compose.runtime.remember
|
2025-04-14 23:40:54 +10:00
|
|
|
import androidx.compose.runtime.rememberCoroutineScope
|
2025-04-14 13:35:26 +10:00
|
|
|
import androidx.compose.runtime.setValue
|
2025-04-14 23:40:54 +10:00
|
|
|
import androidx.compose.ui.Alignment
|
2025-04-13 00:51:32 +10:00
|
|
|
import androidx.compose.ui.Modifier
|
2025-04-14 23:40:54 +10:00
|
|
|
import androidx.compose.ui.platform.LocalDensity
|
2025-04-14 23:47:50 +10:00
|
|
|
import androidx.compose.ui.unit.dp
|
2025-04-14 23:40:54 +10:00
|
|
|
import dev.icerock.moko.geo.compose.BindLocationTrackerEffect
|
|
|
|
|
import dev.icerock.moko.geo.compose.LocationTrackerAccuracy
|
|
|
|
|
import dev.icerock.moko.geo.compose.rememberLocationTrackerFactory
|
|
|
|
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
|
|
|
|
import kotlinx.coroutines.launch
|
2025-04-14 21:07:05 +10:00
|
|
|
import moe.lava.banksia.api.ptv.PtvService
|
2025-04-13 01:27:49 +10:00
|
|
|
import moe.lava.banksia.native.maps.Maps
|
2025-04-14 23:40:54 +10:00
|
|
|
import moe.lava.banksia.native.maps.Point
|
|
|
|
|
import moe.lava.banksia.native.maps.getScreenHeight
|
|
|
|
|
import moe.lava.banksia.resources.Res
|
|
|
|
|
import moe.lava.banksia.resources.my_location_24
|
2025-04-14 13:35:26 +10:00
|
|
|
import moe.lava.banksia.ui.Searcher
|
2025-04-14 23:40:54 +10:00
|
|
|
import org.jetbrains.compose.resources.painterResource
|
2025-04-14 13:35:26 +10:00
|
|
|
import org.jetbrains.compose.ui.tooling.preview.Preview
|
2025-04-14 23:40:54 +10:00
|
|
|
import kotlin.math.roundToInt
|
2025-04-13 00:51:32 +10:00
|
|
|
|
2025-04-14 02:02:06 +10:00
|
|
|
@OptIn(ExperimentalMaterial3Api::class)
|
2025-04-13 00:51:32 +10:00
|
|
|
@Composable
|
|
|
|
|
@Preview
|
|
|
|
|
fun App() {
|
2025-04-14 02:02:06 +10:00
|
|
|
val scaffoldState = rememberBottomSheetScaffoldState(
|
|
|
|
|
bottomSheetState = rememberStandardBottomSheetState(
|
2025-04-14 23:47:50 +10:00
|
|
|
initialValue = SheetValue.PartiallyExpanded,
|
2025-04-14 02:02:06 +10:00
|
|
|
skipHiddenState = false
|
|
|
|
|
)
|
|
|
|
|
)
|
2025-04-14 13:35:26 +10:00
|
|
|
|
2025-04-14 23:40:54 +10:00
|
|
|
val locationFactory = rememberLocationTrackerFactory(LocationTrackerAccuracy.Best)
|
|
|
|
|
val locationTracker = remember { locationFactory.createLocationTracker() }
|
|
|
|
|
BindLocationTrackerEffect(locationTracker)
|
|
|
|
|
var lastLocation by remember { mutableStateOf(Point(-37.8136, 144.9631)) }
|
|
|
|
|
var newCameraPosition by remember { mutableStateOf<Point?>(Point(-37.8136, 144.9631)) }
|
2025-04-14 13:35:26 +10:00
|
|
|
var searchTextState by remember { mutableStateOf("") }
|
|
|
|
|
var searchExpandedState by remember { mutableStateOf(false) }
|
|
|
|
|
|
2025-04-14 23:40:54 +10:00
|
|
|
val sheetState = scaffoldState.bottomSheetState
|
|
|
|
|
val extInsets = if (
|
|
|
|
|
sheetState.currentValue != SheetValue.Hidden ||
|
|
|
|
|
sheetState.targetValue != SheetValue.Hidden
|
|
|
|
|
) {
|
2025-04-14 23:47:50 +10:00
|
|
|
val offset = runCatching { sheetState.requireOffset() }
|
|
|
|
|
val scaffoldOffset = offset.getOrDefault(0.0f).roundToInt()
|
2025-04-14 23:40:54 +10:00
|
|
|
(getScreenHeight() - scaffoldOffset - WindowInsets.safeDrawing.getBottom(LocalDensity.current)).coerceAtLeast(0)
|
|
|
|
|
} else 0
|
|
|
|
|
|
|
|
|
|
var scope = rememberCoroutineScope()
|
|
|
|
|
scope.launch {
|
|
|
|
|
val flow = locationTracker.getLocationsFlow()
|
|
|
|
|
locationTracker.startTracking()
|
|
|
|
|
flow.distinctUntilChanged().collect {
|
|
|
|
|
lastLocation = Point(it.latitude, it.longitude)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-13 00:51:32 +10:00
|
|
|
MaterialTheme {
|
2025-04-14 02:02:06 +10:00
|
|
|
BottomSheetScaffold(
|
|
|
|
|
scaffoldState = scaffoldState,
|
2025-04-14 23:47:50 +10:00
|
|
|
sheetPeekHeight = 250.dp,
|
2025-04-14 23:40:54 +10:00
|
|
|
modifier = Modifier.fillMaxSize(),
|
2025-04-14 02:02:06 +10:00
|
|
|
sheetContent = { Box(modifier = Modifier) },
|
|
|
|
|
) {
|
|
|
|
|
Maps(
|
|
|
|
|
modifier = Modifier.fillMaxSize(),
|
2025-04-14 23:40:54 +10:00
|
|
|
newCameraPosition = newCameraPosition,
|
|
|
|
|
cameraPositionUpdated = { newCameraPosition = null },
|
|
|
|
|
extInsets = extInsets,
|
2025-04-14 02:02:06 +10:00
|
|
|
)
|
2025-04-14 13:35:26 +10:00
|
|
|
Searcher(
|
2025-04-14 21:07:05 +10:00
|
|
|
ptvService = PtvService(),
|
2025-04-14 13:35:26 +10:00
|
|
|
expanded = searchExpandedState,
|
|
|
|
|
onExpandedChange = { searchExpandedState = it },
|
|
|
|
|
text = searchTextState,
|
|
|
|
|
onTextChange = { searchTextState = it },
|
2025-04-14 21:07:05 +10:00
|
|
|
onRouteChange = {}
|
2025-04-14 13:35:26 +10:00
|
|
|
)
|
2025-04-14 23:40:54 +10:00
|
|
|
|
|
|
|
|
Box(
|
|
|
|
|
Modifier.windowInsetsPadding(WindowInsets.safeContent.add(WindowInsets(bottom = extInsets))),
|
|
|
|
|
contentAlignment = Alignment.BottomEnd
|
|
|
|
|
) {
|
|
|
|
|
FloatingActionButton(
|
|
|
|
|
containerColor = MaterialTheme.colorScheme.surfaceContainer,
|
|
|
|
|
onClick = {
|
|
|
|
|
newCameraPosition = lastLocation
|
|
|
|
|
},
|
|
|
|
|
) {
|
|
|
|
|
Icon(painterResource(Res.drawable.my_location_24), "Move to current location")
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-04-13 00:51:32 +10:00
|
|
|
}
|
|
|
|
|
}
|
2025-04-14 21:53:07 +10:00
|
|
|
}
|