diff options
Diffstat (limited to 'android/lib/ui/component/src')
4 files changed, 128 insertions, 65 deletions
diff --git a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/RelayListItem.kt b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/RelayListItem.kt index 8132a9ece7..f88b7b92b4 100644 --- a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/RelayListItem.kt +++ b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/RelayListItem.kt @@ -1,8 +1,11 @@ package net.mullvad.mullvadvpn.lib.ui.component.relaylist +import android.content.Context import net.mullvad.mullvadvpn.lib.model.CustomListId import net.mullvad.mullvadvpn.lib.model.CustomListName +import net.mullvad.mullvadvpn.lib.model.Hop import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.lib.resource.R enum class RelayListItemContentType { CUSTOM_LIST_HEADER, @@ -13,6 +16,10 @@ enum class RelayListItemContentType { LOCATION_ITEM, LOCATIONS_EMPTY_TEXT, EMPTY_RELAY_LIST, + RECENT_LIST_ITEM, + RECENT_LIST_HEADER, + RECENT_LIST_FOOTER, + SECTION_DIVIDER, } enum class RelayListItemState { @@ -24,46 +31,51 @@ sealed interface RelayListItem { val key: Any val contentType: RelayListItemContentType - data object CustomListHeader : RelayListItem { - override val key = "custom_list_header" - override val contentType = RelayListItemContentType.CUSTOM_LIST_HEADER - } - sealed interface SelectableItem : RelayListItem { - val item: RelayItem + val hop: Hop val depth: Int val isSelected: Boolean val expanded: Boolean + val canExpand: Boolean val state: RelayListItemState? val itemPosition: ItemPosition } + data object CustomListHeader : RelayListItem { + override val key = "custom_list_header" + override val contentType = RelayListItemContentType.CUSTOM_LIST_HEADER + } + data class CustomListItem( - override val item: RelayItem.CustomList, + override val hop: Hop.Single<RelayItem.CustomList>, override val isSelected: Boolean = false, override val expanded: Boolean = false, override val state: RelayListItemState? = null, override val itemPosition: ItemPosition = ItemPosition.Single, ) : SelectableItem { + val item = hop.relay override val key = item.id override val depth: Int = 0 override val contentType = RelayListItemContentType.CUSTOM_LIST_ITEM + override val canExpand: Boolean = item.hasChildren } data class CustomListEntryItem( val parentId: CustomListId, val parentName: CustomListName, - override val item: RelayItem.Location, + override val hop: Hop.Single<RelayItem.Location>, override val expanded: Boolean, override val depth: Int = 0, override val state: RelayListItemState? = null, override val itemPosition: ItemPosition, ) : SelectableItem { + val item = hop.relay override val key = parentId to item.id // Can't be displayed as selected override val isSelected: Boolean = false override val contentType = RelayListItemContentType.CUSTOM_LIST_ENTRY_ITEM + override val canExpand: Boolean = item.hasChildren } data class CustomListFooter(val hasCustomList: Boolean) : RelayListItem { @@ -77,15 +89,40 @@ sealed interface RelayListItem { } data class GeoLocationItem( - override val item: RelayItem.Location, + override val hop: Hop.Single<RelayItem.Location>, override val isSelected: Boolean = false, override val depth: Int = 0, override val expanded: Boolean = false, override val state: RelayListItemState? = null, override val itemPosition: ItemPosition, ) : SelectableItem { + val item = hop.relay override val key = item.id override val contentType = RelayListItemContentType.LOCATION_ITEM + override val canExpand: Boolean = item.hasChildren + } + + data object RecentsListHeader : RelayListItem { + override val key = "recents_list_header" + override val contentType = RelayListItemContentType.RECENT_LIST_HEADER + } + + data class RecentListItem( + override val hop: Hop, + override val isSelected: Boolean = false, + override val expanded: Boolean = false, + override val state: RelayListItemState? = null, + override val itemPosition: ItemPosition = ItemPosition.Single, + ) : SelectableItem { + override val key = "recents$hop" + override val depth: Int = 0 + override val contentType = RelayListItemContentType.RECENT_LIST_ITEM + override val canExpand: Boolean = false + } + + data object RecentsListFooter : RelayListItem { + override val key = "recents_list_footer" + override val contentType = RelayListItemContentType.RECENT_LIST_FOOTER } data class LocationsEmptyText(val searchTerm: String) : RelayListItem { @@ -97,6 +134,11 @@ sealed interface RelayListItem { override val key = "empty_relay_list" override val contentType = RelayListItemContentType.EMPTY_RELAY_LIST } + + class SectionDivider : RelayListItem { + override val key: String = "section_divider_${this.hashCode()}" + override val contentType = RelayListItemContentType.SECTION_DIVIDER + } } data class CheckableRelayListItem( @@ -130,3 +172,9 @@ sealed interface ItemPosition { else -> false } } + +fun Hop.displayName(context: Context): String = + when (this) { + is Hop.Multi -> context.getString(R.string.x_via_x, exit.name, entry.name) + is Hop.Single<*> -> relay.name + } diff --git a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/RelayListItemPreviewData.kt b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/RelayListItemPreviewData.kt index 5776601168..58ae2f2e82 100644 --- a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/RelayListItemPreviewData.kt +++ b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/RelayListItemPreviewData.kt @@ -3,6 +3,7 @@ package net.mullvad.mullvadvpn.lib.ui.component.relaylist import net.mullvad.mullvadvpn.lib.model.CustomList import net.mullvad.mullvadvpn.lib.model.CustomListId import net.mullvad.mullvadvpn.lib.model.CustomListName +import net.mullvad.mullvadvpn.lib.model.Hop import net.mullvad.mullvadvpn.lib.model.RelayItem object RelayListItemPreviewData { @@ -16,23 +17,25 @@ object RelayListItemPreviewData { // Add custom list items if (includeCustomLists) { RelayListItem.CustomListItem( - item = - RelayItem.CustomList( - customList = - CustomList( - id = CustomListId("custom_list_id"), - name = CustomListName.fromString("Custom List"), - locations = emptyList(), - ), - locations = - listOf( - generateRelayItemCountry( - name = "Country", - cityNames = listOf("City"), - relaysPerCity = 2, - active = true, - ) - ), + hop = + Hop.Single( + RelayItem.CustomList( + customList = + CustomList( + id = CustomListId("custom_list_id"), + name = CustomListName.fromString("Custom List"), + locations = emptyList(), + ), + locations = + listOf( + generateRelayItemCountry( + name = "Country", + cityNames = listOf("City"), + relaysPerCity = 2, + active = true, + ) + ), + ) ), isSelected = false, state = null, @@ -63,7 +66,7 @@ object RelayListItemPreviewData { addAll( listOf( RelayListItem.GeoLocationItem( - item = locations[0], + hop = Hop.Single(locations[0]), isSelected = false, depth = 0, expanded = true, @@ -71,7 +74,7 @@ object RelayListItemPreviewData { itemPosition = ItemPosition.Middle, ), RelayListItem.GeoLocationItem( - item = locations[0].cities[0], + hop = Hop.Single(locations[0].cities[0]), isSelected = true, depth = 1, expanded = false, @@ -79,7 +82,7 @@ object RelayListItemPreviewData { itemPosition = ItemPosition.Middle, ), RelayListItem.GeoLocationItem( - item = locations[0].cities[1], + hop = Hop.Single(locations[0].cities[1]), isSelected = false, depth = 1, expanded = true, @@ -87,7 +90,7 @@ object RelayListItemPreviewData { itemPosition = ItemPosition.Middle, ), RelayListItem.GeoLocationItem( - item = locations[0].cities[1].relays[0], + hop = Hop.Single(locations[0].cities[1].relays[0]), isSelected = false, depth = 2, expanded = false, @@ -95,7 +98,7 @@ object RelayListItemPreviewData { itemPosition = ItemPosition.Middle, ), RelayListItem.GeoLocationItem( - item = locations[0].cities[1].relays[1], + hop = Hop.Single(locations[0].cities[1].relays[1]), isSelected = false, depth = 2, expanded = false, @@ -103,7 +106,7 @@ object RelayListItemPreviewData { itemPosition = ItemPosition.Middle, ), RelayListItem.GeoLocationItem( - item = locations[1], + hop = Hop.Single(locations[1]), isSelected = false, depth = 0, expanded = false, diff --git a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/SelectableRelayListItem.kt b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/SelectableRelayListItem.kt index 83b24ff137..289eb5aa9f 100644 --- a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/SelectableRelayListItem.kt +++ b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/SelectableRelayListItem.kt @@ -26,6 +26,7 @@ import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow @@ -72,7 +73,7 @@ fun SelectableRelayListItem( modifier = modifier, shape = relayListItem.itemPosition.toShape(), selected = relayListItem.isSelected, - enabled = relayListItem.item.active, + enabled = relayListItem.hop.isActive, content = { Row( modifier = @@ -84,7 +85,7 @@ fun SelectableRelayListItem( ) { val iconTint = when { - !relayListItem.item.active -> MaterialTheme.colorScheme.error + !relayListItem.hop.isActive -> MaterialTheme.colorScheme.error relayListItem.isSelected -> MaterialTheme.colorScheme.tertiary else -> Color.Transparent } @@ -94,14 +95,14 @@ fun SelectableRelayListItem( contentDescription = null, tint = iconTint, ) - } else if (!relayListItem.item.active) { + } else if (!relayListItem.hop.isActive) { InactiveRelayIndicator(iconTint) } Name( - name = relayListItem.item.name, + name = relayListItem.hop.displayName(LocalContext.current), state = relayListItem.state, - active = relayListItem.item.active, + active = relayListItem.hop.isActive, ) } }, @@ -111,7 +112,7 @@ fun SelectableRelayListItem( else ({}), onLongClick = onLongClick, trailingContent = - if (relayListItem.item.hasChildren) { + if (relayListItem.canExpand) { { ExpandChevron( isExpanded = relayListItem.expanded, diff --git a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/SelectableRelayListItemPreviewParameterProvider.kt b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/SelectableRelayListItemPreviewParameterProvider.kt index 732c03bbc4..812f4de60e 100644 --- a/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/SelectableRelayListItemPreviewParameterProvider.kt +++ b/android/lib/ui/component/src/main/kotlin/net/mullvad/mullvadvpn/lib/ui/component/relaylist/SelectableRelayListItemPreviewParameterProvider.kt @@ -1,6 +1,7 @@ package net.mullvad.mullvadvpn.lib.ui.component.relaylist import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import net.mullvad.mullvadvpn.lib.model.Hop class SelectableRelayListItemPreviewParameterProvider : PreviewParameterProvider<List<RelayListItem.SelectableItem>> { @@ -8,55 +9,65 @@ class SelectableRelayListItemPreviewParameterProvider : sequenceOf( listOf( RelayListItem.GeoLocationItem( - item = - generateRelayItemCountry( - name = "Relay country Active", - cityNames = listOf("Relay city 1", "Relay city 2"), - relaysPerCity = 2, + hop = + Hop.Single( + generateRelayItemCountry( + name = "Relay country Active", + cityNames = listOf("Relay city 1", "Relay city 2"), + relaysPerCity = 2, + ) ), isSelected = true, expanded = false, itemPosition = ItemPosition.Single, ), RelayListItem.GeoLocationItem( - item = - generateRelayItemCountry( - name = "Not Enabled Relay country", - cityNames = listOf("Not Enabled city"), - relaysPerCity = 1, - active = false, + hop = + Hop.Single( + generateRelayItemCountry( + name = "Not Enabled Relay country", + cityNames = listOf("Not Enabled city"), + relaysPerCity = 1, + active = false, + ) ), isSelected = false, itemPosition = ItemPosition.Single, ), RelayListItem.GeoLocationItem( - item = - generateRelayItemCountry( - name = "Relay country Expanded", - cityNames = listOf("Normal city"), - relaysPerCity = 2, + hop = + Hop.Single( + generateRelayItemCountry( + name = "Relay country Expanded", + cityNames = listOf("Normal city"), + relaysPerCity = 2, + ) ), isSelected = true, expanded = true, itemPosition = ItemPosition.Single, ), RelayListItem.GeoLocationItem( - item = - generateRelayItemCountry( - name = "Country and city Expanded", - cityNames = listOf("Expanded city A", "Expanded city B"), - relaysPerCity = 2, + hop = + Hop.Single( + generateRelayItemCountry( + name = "Country and city Expanded", + cityNames = listOf("Expanded city A", "Expanded city B"), + relaysPerCity = 2, + ) ), isSelected = false, itemPosition = ItemPosition.Single, ), RelayListItem.GeoLocationItem( - item = - generateRelayItemCountry( - name = "Country selected but inactive", - cityNames = listOf("Expanded city A", "Expanded city B"), - relaysPerCity = 2, - active = false, + hop = + Hop.Single( + generateRelayItemCountry( + name = "Country selected but inactive", + cityNames = listOf("Expanded city A", "Expanded city B"), + relaysPerCity = 2, + active = false, + ) ), isSelected = true, itemPosition = ItemPosition.Single, |
