Fix quality!
This commit is contained in:
@@ -8,17 +8,11 @@
|
|||||||
package io.element.android.features.location.impl.common.ui
|
package io.element.android.features.location.impl.common.ui
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
sealed interface LocationConstraintsDialogState {
|
|
||||||
data object None : LocationConstraintsDialogState
|
|
||||||
data object PermissionRationale : LocationConstraintsDialogState
|
|
||||||
data object PermissionDenied : LocationConstraintsDialogState
|
|
||||||
data object LocationServiceDisabled : LocationConstraintsDialogState
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LocationConstraintsDialog(
|
fun LocationConstraintsDialog(
|
||||||
state: LocationConstraintsDialogState,
|
state: LocationConstraintsDialogState,
|
||||||
@@ -53,3 +47,11 @@ fun LocationConstraintsDialog(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
sealed interface LocationConstraintsDialogState {
|
||||||
|
data object None : LocationConstraintsDialogState
|
||||||
|
data object PermissionRationale : LocationConstraintsDialogState
|
||||||
|
data object PermissionDenied : LocationConstraintsDialogState
|
||||||
|
data object LocationServiceDisabled : LocationConstraintsDialogState
|
||||||
|
}
|
||||||
|
|||||||
@@ -60,15 +60,16 @@ import kotlin.math.roundToInt
|
|||||||
* - Updating camera position padding based on sheet height
|
* - Updating camera position padding based on sheet height
|
||||||
* - Rendering the MaplibreMap with proper ornament positioning
|
* - Rendering the MaplibreMap with proper ornament positioning
|
||||||
*
|
*
|
||||||
* @param cameraState The camera state for the map
|
|
||||||
* @param topBar The top app bar content
|
|
||||||
* @param sheetContent The content to display in the bottom sheet
|
|
||||||
* @param modifier Modifier for the root layout
|
* @param modifier Modifier for the root layout
|
||||||
* @param scaffoldState State for the bottom sheet scaffold
|
* @param scaffoldState State for the bottom sheet scaffold
|
||||||
|
* @param cameraState The camera state for the map
|
||||||
|
* @param mapOptions The options to configure the map
|
||||||
* @param sheetPeekHeight The height of the sheet when collapsed
|
* @param sheetPeekHeight The height of the sheet when collapsed
|
||||||
* @param sheetDragHandle Optional drag handle for the sheet
|
* @param sheetDragHandle Optional drag handle for the sheet
|
||||||
* @param sheetSwipeEnabled Whether the sheet can be swiped
|
* @param sheetSwipeEnabled Whether the sheet can be swiped
|
||||||
|
* @param topBar The top app bar content
|
||||||
* @param snackbarHost The snackbar host content
|
* @param snackbarHost The snackbar host content
|
||||||
|
* @param sheetContent The content to display in the bottom sheet
|
||||||
* @param mapContent The content inside the MaplibreMap (layers, location pucks, etc.)
|
* @param mapContent The content inside the MaplibreMap (layers, location pucks, etc.)
|
||||||
* @param overlayContent Content to overlay on top of the map (FAB, pin icons, etc.)
|
* @param overlayContent Content to overlay on top of the map (FAB, pin icons, etc.)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
package io.element.android.features.location.impl.common.ui
|
package io.element.android.features.location.impl.common.ui
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.platform.LocalInspectionMode
|
import androidx.compose.ui.platform.LocalInspectionMode
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -63,6 +64,7 @@ fun UserLocationPuck(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("MissingPermission")
|
||||||
@Composable
|
@Composable
|
||||||
fun rememberUserLocationState(hasLocationPermission: Boolean): UserLocationState {
|
fun rememberUserLocationState(hasLocationPermission: Boolean): UserLocationState {
|
||||||
val isPreview = LocalInspectionMode.current
|
val isPreview = LocalInspectionMode.current
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ class ShareLocationPresenter(
|
|||||||
dialogState = dialogState,
|
dialogState = dialogState,
|
||||||
trackUserLocation = trackUserPosition,
|
trackUserLocation = trackUserPosition,
|
||||||
hasLocationPermission = permissionsState.isAnyGranted,
|
hasLocationPermission = permissionsState.isAnyGranted,
|
||||||
canShareLiveLocation = false,
|
canShareLiveLocation = isLiveLocationSharingEnabled,
|
||||||
appName = appName,
|
appName = appName,
|
||||||
eventSink = ::handleEvent,
|
eventSink = ::handleEvent,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,11 +8,13 @@
|
|||||||
|
|
||||||
package io.element.android.features.location.impl.share
|
package io.element.android.features.location.impl.share
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.SheetValue
|
import androidx.compose.material3.SheetValue
|
||||||
import androidx.compose.material3.rememberBottomSheetScaffoldState
|
import androidx.compose.material3.rememberBottomSheetScaffoldState
|
||||||
@@ -20,9 +22,12 @@ import androidx.compose.material3.rememberStandardBottomSheetState
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -36,11 +41,14 @@ import io.element.android.features.location.impl.common.ui.LocationFloatingActio
|
|||||||
import io.element.android.features.location.impl.common.ui.MapBottomSheetScaffold
|
import io.element.android.features.location.impl.common.ui.MapBottomSheetScaffold
|
||||||
import io.element.android.features.location.impl.common.ui.UserLocationPuck
|
import io.element.android.features.location.impl.common.ui.UserLocationPuck
|
||||||
import io.element.android.features.location.impl.common.ui.rememberUserLocationState
|
import io.element.android.features.location.impl.common.ui.rememberUserLocationState
|
||||||
|
import io.element.android.libraries.androidutils.system.toast
|
||||||
import io.element.android.libraries.designsystem.components.LocationPin
|
import io.element.android.libraries.designsystem.components.LocationPin
|
||||||
import io.element.android.libraries.designsystem.components.PinVariant
|
import io.element.android.libraries.designsystem.components.PinVariant
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||||
|
import io.element.android.libraries.designsystem.components.dialogs.ListDialog
|
||||||
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
import io.element.android.libraries.designsystem.components.list.ListItemContent
|
||||||
|
import io.element.android.libraries.designsystem.components.list.RadioButtonListItem
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
import io.element.android.libraries.designsystem.theme.components.IconSource
|
import io.element.android.libraries.designsystem.theme.components.IconSource
|
||||||
@@ -62,6 +70,7 @@ fun ShareLocationView(
|
|||||||
navigateUp: () -> Unit,
|
navigateUp: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
when (val dialogState = state.dialogState) {
|
when (val dialogState = state.dialogState) {
|
||||||
ShareLocationState.Dialog.None -> Unit
|
ShareLocationState.Dialog.None -> Unit
|
||||||
is ShareLocationState.Dialog.Constraints -> LocationConstraintsDialog(
|
is ShareLocationState.Dialog.Constraints -> LocationConstraintsDialog(
|
||||||
@@ -75,6 +84,7 @@ fun ShareLocationView(
|
|||||||
ShareLocationState.Dialog.LiveLocationDuration -> LiveLocationDurationDialog(
|
ShareLocationState.Dialog.LiveLocationDuration -> LiveLocationDurationDialog(
|
||||||
onSelectDuration = { duration ->
|
onSelectDuration = { duration ->
|
||||||
state.eventSink(ShareLocationEvent.StartLiveLocationShare(duration))
|
state.eventSink(ShareLocationEvent.StartLiveLocationShare(duration))
|
||||||
|
context.toast("Not implemented yet!")
|
||||||
navigateUp()
|
navigateUp()
|
||||||
},
|
},
|
||||||
onDismiss = { state.eventSink(ShareLocationEvent.DismissDialog) },
|
onDismiss = { state.eventSink(ShareLocationEvent.DismissDialog) },
|
||||||
@@ -129,7 +139,7 @@ fun ShareLocationView(
|
|||||||
.padding(sheetPadding)
|
.padding(sheetPadding)
|
||||||
) {
|
) {
|
||||||
val variant = if (state.trackUserLocation) {
|
val variant = if (state.trackUserLocation) {
|
||||||
PinVariant.UserLocation(isLive = false, avatarData = state.currentUser.getAvatarData(AvatarSize.SelectedUser))
|
PinVariant.UserLocation(isLive = false, avatarData = state.currentUser.getAvatarData(AvatarSize.LocationPin))
|
||||||
} else {
|
} else {
|
||||||
PinVariant.PinnedLocation
|
PinVariant.PinnedLocation
|
||||||
}
|
}
|
||||||
@@ -243,7 +253,6 @@ private fun LiveLocationDurationDialog(
|
|||||||
onSelectDuration: (Duration) -> Unit,
|
onSelectDuration: (Duration) -> Unit,
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
) {
|
) {
|
||||||
/*
|
|
||||||
var selectedIndex by remember { mutableIntStateOf(0) }
|
var selectedIndex by remember { mutableIntStateOf(0) }
|
||||||
ListDialog(
|
ListDialog(
|
||||||
title = "Choose how long to share your live location.",
|
title = "Choose how long to share your live location.",
|
||||||
@@ -263,7 +272,6 @@ private fun LiveLocationDurationDialog(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PreviewsDayNight
|
@PreviewsDayNight
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ fun aShowLocationState(
|
|||||||
id = mode.senderId.value,
|
id = mode.senderId.value,
|
||||||
name = mode.senderName,
|
name = mode.senderName,
|
||||||
url = mode.senderAvatarUrl,
|
url = mode.senderAvatarUrl,
|
||||||
size = AvatarSize.UserListItem,
|
size = AvatarSize.LocationPin,
|
||||||
),
|
),
|
||||||
isLive = true,
|
isLive = true,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -49,8 +49,7 @@ data class TimelineItemLocationContent(
|
|||||||
senderId.value,
|
senderId.value,
|
||||||
name = senderProfile.getDisplayName(),
|
name = senderProfile.getDisplayName(),
|
||||||
url = senderProfile.getAvatarUrl(),
|
url = senderProfile.getAvatarUrl(),
|
||||||
// Size is irrelevant as the PinMarker will override anyway.
|
size = AvatarSize.LocationPin
|
||||||
size = AvatarSize.TimelineSender
|
|
||||||
)
|
)
|
||||||
|
|
||||||
sealed interface Mode {
|
sealed interface Mode {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
<string name="screen_room_attachment_source_camera_video">"Record video"</string>
|
<string name="screen_room_attachment_source_camera_video">"Record video"</string>
|
||||||
<string name="screen_room_attachment_source_files">"Attachment"</string>
|
<string name="screen_room_attachment_source_files">"Attachment"</string>
|
||||||
<string name="screen_room_attachment_source_gallery">"Photo & Video Library"</string>
|
<string name="screen_room_attachment_source_gallery">"Photo & Video Library"</string>
|
||||||
<string name="screen_room_attachment_source_location">"Location"</string>
|
<string name="screen_room_attachment_source_location">"Share location"</string>
|
||||||
<string name="screen_room_attachment_source_poll">"Poll"</string>
|
<string name="screen_room_attachment_source_poll">"Poll"</string>
|
||||||
<string name="screen_room_attachment_text_formatting">"Text Formatting"</string>
|
<string name="screen_room_attachment_text_formatting">"Text Formatting"</string>
|
||||||
<string name="screen_room_encrypted_history_banner">"Message history is currently unavailable."</string>
|
<string name="screen_room_encrypted_history_banner">"Message history is currently unavailable."</string>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import android.net.ConnectivityManager
|
|||||||
import android.net.Network
|
import android.net.Network
|
||||||
import android.net.NetworkCapabilities
|
import android.net.NetworkCapabilities
|
||||||
import android.net.NetworkRequest
|
import android.net.NetworkRequest
|
||||||
|
import android.os.Build
|
||||||
import dev.zacsweers.metro.AppScope
|
import dev.zacsweers.metro.AppScope
|
||||||
import dev.zacsweers.metro.ContributesBinding
|
import dev.zacsweers.metro.ContributesBinding
|
||||||
import dev.zacsweers.metro.SingleIn
|
import dev.zacsweers.metro.SingleIn
|
||||||
@@ -83,7 +84,9 @@ class DefaultNetworkMonitor(
|
|||||||
if (network.networkHandle == connectivityManager.activeNetwork?.networkHandle) {
|
if (network.networkHandle == connectivityManager.activeNetwork?.networkHandle) {
|
||||||
// If the network doesn't have the NET_CAPABILITY_VALIDATED capability, it means that the network is not able to reach the internet
|
// If the network doesn't have the NET_CAPABILITY_VALIDATED capability, it means that the network is not able to reach the internet
|
||||||
// (according to Google), which is a common case in air-gapped environments.
|
// (according to Google), which is a common case in air-gapped environments.
|
||||||
isInAirGappedEnvironment.value = !networkCapabilities.capabilities.contains(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
|
isInAirGappedEnvironment.value = !networkCapabilities.capabilities.contains(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import androidx.compose.foundation.layout.Column
|
|||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.compose.runtime.produceState
|
import androidx.compose.runtime.produceState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
@@ -60,6 +61,7 @@ private val STROKE_WIDTH = 1.dp
|
|||||||
/**
|
/**
|
||||||
* Variants of location pin markers.
|
* Variants of location pin markers.
|
||||||
*/
|
*/
|
||||||
|
@Immutable
|
||||||
sealed interface PinVariant {
|
sealed interface PinVariant {
|
||||||
data class UserLocation(
|
data class UserLocation(
|
||||||
val avatarData: AvatarData,
|
val avatarData: AvatarData,
|
||||||
|
|||||||
@@ -75,6 +75,6 @@ enum class AvatarSize(val dp: Dp) {
|
|||||||
SpaceMember(24.dp),
|
SpaceMember(24.dp),
|
||||||
LeaveSpaceRoom(32.dp),
|
LeaveSpaceRoom(32.dp),
|
||||||
SelectParentSpace(32.dp),
|
SelectParentSpace(32.dp),
|
||||||
|
|
||||||
AccountItem(32.dp),
|
AccountItem(32.dp),
|
||||||
|
LocationPin(32.dp)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user