mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 12:07:28 +00:00
+21
-7
@@ -37,6 +37,7 @@ import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.Dp
|
||||
@@ -44,9 +45,11 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.max
|
||||
import io.element.android.features.location.api.internal.rememberTileStyleUrl
|
||||
import io.element.android.features.location.impl.common.MapDefaults
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.core.data.tryOrNull
|
||||
import io.element.android.libraries.designsystem.text.toDp
|
||||
import io.element.android.libraries.designsystem.theme.components.BottomSheetScaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import org.maplibre.compose.camera.CameraState
|
||||
import org.maplibre.compose.camera.rememberCameraState
|
||||
import org.maplibre.compose.map.MapOptions
|
||||
@@ -63,6 +66,7 @@ import kotlin.math.roundToInt
|
||||
* - Updating camera position padding based on sheet height
|
||||
* - Rendering the MaplibreMap with proper ornament positioning
|
||||
*
|
||||
* @param customMapStyleUrl Optional custom style URL for the map
|
||||
* @param modifier Modifier for the root layout
|
||||
* @param scaffoldState State for the bottom sheet scaffold
|
||||
* @param cameraState The camera state for the map
|
||||
@@ -79,6 +83,7 @@ import kotlin.math.roundToInt
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun MapBottomSheetScaffold(
|
||||
customMapStyleUrl: AsyncData<String?>,
|
||||
modifier: Modifier = Modifier,
|
||||
scaffoldState: BottomSheetScaffoldState = rememberBottomSheetScaffoldState(
|
||||
bottomSheetState = rememberStandardBottomSheetState(initialValue = SheetValue.PartiallyExpanded)
|
||||
@@ -130,13 +135,22 @@ fun MapBottomSheetScaffold(
|
||||
val ornamentOptions = mapOptions.ornamentOptions.copy(padding = sheetPadding)
|
||||
val mapOptions = mapOptions.copy(ornamentOptions = ornamentOptions)
|
||||
Box {
|
||||
MaplibreMap(
|
||||
options = mapOptions,
|
||||
baseStyle = BaseStyle.Uri(rememberTileStyleUrl()),
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
cameraState = cameraState,
|
||||
content = mapContent,
|
||||
)
|
||||
when (customMapStyleUrl) {
|
||||
is AsyncData.Success -> {
|
||||
MaplibreMap(
|
||||
options = mapOptions,
|
||||
baseStyle = BaseStyle.Uri(rememberTileStyleUrl(customMapStyleUrl.data)),
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
cameraState = cameraState,
|
||||
content = mapContent,
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
|
||||
}
|
||||
}
|
||||
}
|
||||
overlayContent(sheetPadding)
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -14,6 +14,7 @@ import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.produceState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
@@ -35,6 +36,7 @@ import io.element.android.features.location.impl.common.toDialogState
|
||||
import io.element.android.features.location.impl.live.LiveLocationStore
|
||||
import io.element.android.features.messages.api.MessageComposerContext
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.architecture.runUpdatingState
|
||||
import io.element.android.libraries.core.extensions.flatMap
|
||||
@@ -86,6 +88,10 @@ class ShareLocationPresenter(
|
||||
}
|
||||
val startLiveLocationAction = remember { mutableStateOf<AsyncAction<Unit>>(AsyncAction.Uninitialized) }
|
||||
val currentUser by client.userProfile.collectAsState()
|
||||
val customMapStyleUrl by produceState(AsyncData.Loading()) {
|
||||
// Ignore errors
|
||||
value = AsyncData.Success(client.getMapStyleUrl().getOrNull())
|
||||
}
|
||||
val sendLiveLocationPermissions by room.permissionsAsState(SendLiveLocationPermissions.DEFAULT) { perms ->
|
||||
perms.sendLiveLocationPermissions()
|
||||
}
|
||||
@@ -161,6 +167,7 @@ class ShareLocationPresenter(
|
||||
}
|
||||
|
||||
return ShareLocationState(
|
||||
customMapStyleUrl = customMapStyleUrl,
|
||||
currentUser = currentUser,
|
||||
dialogState = dialogState,
|
||||
trackUserLocation = trackUserPosition,
|
||||
|
||||
+2
@@ -10,10 +10,12 @@ package io.element.android.features.location.impl.share
|
||||
|
||||
import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
data class ShareLocationState(
|
||||
val customMapStyleUrl: AsyncData<String?>,
|
||||
val currentUser: MatrixUser,
|
||||
val dialogState: Dialog,
|
||||
val trackUserLocation: Boolean,
|
||||
|
||||
+6
@@ -11,6 +11,7 @@ package io.element.android.features.location.impl.share
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState
|
||||
import io.element.android.libraries.architecture.AsyncAction
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
@@ -76,10 +77,14 @@ class ShareLocationStateProvider : PreviewParameterProvider<ShareLocationState>
|
||||
hasLocationPermission = true,
|
||||
canShareLiveLocation = true,
|
||||
),
|
||||
aShareLocationState(
|
||||
customMapStyleUrl = AsyncData.Loading(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun aShareLocationState(
|
||||
customMapStyleUrl: AsyncData<String?> = AsyncData.Success(null),
|
||||
currentUser: MatrixUser = MatrixUser(UserId("@user:matrix.org")),
|
||||
dialogState: ShareLocationState.Dialog = ShareLocationState.Dialog.None,
|
||||
trackUserPosition: Boolean = false,
|
||||
@@ -90,6 +95,7 @@ fun aShareLocationState(
|
||||
eventSink: (ShareLocationEvent) -> Unit = {},
|
||||
): ShareLocationState {
|
||||
return ShareLocationState(
|
||||
customMapStyleUrl = customMapStyleUrl,
|
||||
currentUser = currentUser,
|
||||
dialogState = dialogState,
|
||||
trackUserLocation = trackUserPosition,
|
||||
|
||||
+1
@@ -117,6 +117,7 @@ fun ShareLocationView(
|
||||
}
|
||||
|
||||
MapBottomSheetScaffold(
|
||||
customMapStyleUrl = state.customMapStyleUrl,
|
||||
cameraState = cameraState,
|
||||
modifier = modifier,
|
||||
scaffoldState = scaffoldState,
|
||||
|
||||
+9
@@ -33,6 +33,7 @@ import io.element.android.features.location.impl.common.permissions.PermissionsP
|
||||
import io.element.android.features.location.impl.common.permissions.PermissionsState
|
||||
import io.element.android.features.location.impl.common.toDialogState
|
||||
import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.coroutine.mapState
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
@@ -40,6 +41,7 @@ import io.element.android.libraries.dateformatter.api.DateFormatter
|
||||
import io.element.android.libraries.dateformatter.api.DateFormatterMode
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.matrix.api.MatrixClient
|
||||
import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
import io.element.android.libraries.matrix.api.room.getBestName
|
||||
import io.element.android.libraries.matrix.api.room.joinedRoomMembers
|
||||
@@ -58,6 +60,7 @@ class ShowLocationPresenter(
|
||||
private val buildMeta: BuildMeta,
|
||||
private val dateFormatter: DateFormatter,
|
||||
private val stringProvider: StringProvider,
|
||||
private val client: MatrixClient,
|
||||
private val joinedRoom: JoinedRoom,
|
||||
private val liveLocationShareManager: ActiveLiveLocationShareManager,
|
||||
) : Presenter<ShowLocationState> {
|
||||
@@ -78,6 +81,11 @@ class ShowLocationPresenter(
|
||||
mutableStateOf(LocationConstraintsDialogState.None)
|
||||
}
|
||||
|
||||
val customMapStyleUrl by produceState(AsyncData.Loading()) {
|
||||
// Ignore errors
|
||||
value = AsyncData.Success(client.getMapStyleUrl().getOrNull())
|
||||
}
|
||||
|
||||
LaunchedEffect(permissionsState.permissions) {
|
||||
if (permissionsState.isAnyGranted) {
|
||||
dialogState = LocationConstraintsDialogState.None
|
||||
@@ -188,6 +196,7 @@ class ShowLocationPresenter(
|
||||
}
|
||||
|
||||
return ShowLocationState(
|
||||
customMapStyleUrl = customMapStyleUrl,
|
||||
dialogState = dialogState,
|
||||
locationShares = locationShares,
|
||||
focusedLocation = focusedLocation,
|
||||
|
||||
+2
@@ -11,6 +11,7 @@ package io.element.android.features.location.impl.show
|
||||
import io.element.android.features.location.api.Location
|
||||
import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState
|
||||
import io.element.android.features.location.impl.common.ui.LocationMarkerData
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.designsystem.components.PinVariant
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
@@ -18,6 +19,7 @@ import io.element.android.libraries.matrix.api.room.location.AssetType
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
data class ShowLocationState(
|
||||
val customMapStyleUrl: AsyncData<String?>,
|
||||
val isLive: Boolean,
|
||||
val dialogState: LocationConstraintsDialogState,
|
||||
val locationShares: ImmutableList<LocationShareItem>,
|
||||
|
||||
+6
@@ -11,6 +11,7 @@ package io.element.android.features.location.impl.show
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import io.element.android.features.location.api.Location
|
||||
import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState
|
||||
import io.element.android.libraries.architecture.AsyncData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.preview.USER_NAME_ALICE
|
||||
@@ -41,12 +42,16 @@ class ShowLocationStateProvider : PreviewParameterProvider<ShowLocationState> {
|
||||
hasLocationPermission = true,
|
||||
isTrackMyLocation = true,
|
||||
),
|
||||
aShowLocationState(
|
||||
customMapStyleUrl = AsyncData.Loading(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private const val APP_NAME = "ApplicationName"
|
||||
|
||||
fun aShowLocationState(
|
||||
customMapStyleUrl: AsyncData<String?> = AsyncData.Success(null),
|
||||
isLive: Boolean = false,
|
||||
constraintsDialogState: LocationConstraintsDialogState = LocationConstraintsDialogState.None,
|
||||
locationShares: List<LocationShareItem> = listOf(aLocationShareItem(isLive = isLive)),
|
||||
@@ -57,6 +62,7 @@ fun aShowLocationState(
|
||||
eventSink: (ShowLocationEvent) -> Unit = {},
|
||||
): ShowLocationState {
|
||||
return ShowLocationState(
|
||||
customMapStyleUrl = customMapStyleUrl,
|
||||
dialogState = constraintsDialogState,
|
||||
locationShares = locationShares.toImmutableList(),
|
||||
focusedLocation = focusedLocation,
|
||||
|
||||
+1
@@ -100,6 +100,7 @@ fun ShowLocationView(
|
||||
}
|
||||
}
|
||||
MapBottomSheetScaffold(
|
||||
customMapStyleUrl = state.customMapStyleUrl,
|
||||
sheetDragHandle = if (state.isSheetDraggable) {
|
||||
{ BottomSheetDefaults.DragHandle() }
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user