Finalize location item UI

This commit is contained in:
MM20 2024-05-06 23:35:31 +02:00
parent 787f64b85f
commit f6028a3f39
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
3 changed files with 226 additions and 19 deletions

View File

@ -18,6 +18,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@ -29,18 +30,24 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material.icons.automirrored.rounded.NavigateNext import androidx.compose.material.icons.automirrored.rounded.NavigateNext
import androidx.compose.material.icons.automirrored.rounded.OpenInNew
import androidx.compose.material.icons.rounded.BugReport import androidx.compose.material.icons.rounded.BugReport
import androidx.compose.material.icons.rounded.Edit
import androidx.compose.material.icons.rounded.Language import androidx.compose.material.icons.rounded.Language
import androidx.compose.material.icons.rounded.Map
import androidx.compose.material.icons.rounded.Navigation import androidx.compose.material.icons.rounded.Navigation
import androidx.compose.material.icons.rounded.Phone import androidx.compose.material.icons.rounded.Phone
import androidx.compose.material.icons.rounded.Star import androidx.compose.material.icons.rounded.Star
import androidx.compose.material.icons.rounded.StarOutline import androidx.compose.material.icons.rounded.StarOutline
import androidx.compose.material.icons.rounded.Visibility
import androidx.compose.material.icons.rounded.VisibilityOff
import androidx.compose.material.icons.rounded.WifiOff
import androidx.compose.material3.AssistChip import androidx.compose.material3.AssistChip
import androidx.compose.material3.AssistChipDefaults import androidx.compose.material3.AssistChipDefaults
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedCard import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarResult
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
@ -62,10 +69,13 @@ import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.roundToIntRect import androidx.compose.ui.unit.roundToIntRect
import androidx.compose.ui.unit.times import androidx.compose.ui.unit.times
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import de.mm20.launcher2.i18n.R import de.mm20.launcher2.i18n.R
import de.mm20.launcher2.ktx.tryStartActivity import de.mm20.launcher2.ktx.tryStartActivity
import de.mm20.launcher2.search.Location import de.mm20.launcher2.search.Location
import de.mm20.launcher2.search.LocationCategory
import de.mm20.launcher2.search.OpeningHours import de.mm20.launcher2.search.OpeningHours
import de.mm20.launcher2.search.OpeningSchedule import de.mm20.launcher2.search.OpeningSchedule
import de.mm20.launcher2.ui.component.DefaultToolbarAction import de.mm20.launcher2.ui.component.DefaultToolbarAction
@ -77,10 +87,13 @@ import de.mm20.launcher2.ui.ktx.metersToLocalizedString
import de.mm20.launcher2.ui.ktx.toPixels import de.mm20.launcher2.ui.ktx.toPixels
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
import de.mm20.launcher2.ui.launcher.search.listItemViewModel import de.mm20.launcher2.ui.launcher.search.listItemViewModel
import de.mm20.launcher2.ui.launcher.sheets.LocalBottomSheetManager
import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled import de.mm20.launcher2.ui.locals.LocalFavoritesEnabled
import de.mm20.launcher2.ui.locals.LocalGridSettings import de.mm20.launcher2.ui.locals.LocalGridSettings
import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
import de.mm20.launcher2.ui.modifier.scale import de.mm20.launcher2.ui.modifier.scale
import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.launch
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle import java.time.format.FormatStyle
@ -170,7 +183,7 @@ fun LocationItem(
if (category != null || formattedDistance != null) { if (category != null || formattedDistance != null) {
Text( Text(
when { when {
category != null && formattedDistance != null -> "${category}${formattedDistance}" category != null && formattedDistance != null -> "${stringResource(category.labelRes)}${formattedDistance}"
category != null -> category.toString() category != null -> category.toString()
formattedDistance != null -> formattedDistance formattedDistance != null -> formattedDistance
else -> "" else -> ""
@ -268,7 +281,7 @@ fun LocationItem(
if (category != null || formattedDistance != null) { if (category != null || formattedDistance != null) {
Text( Text(
when { when {
category != null && formattedDistance != null -> "${category}${formattedDistance}" category != null && formattedDistance != null -> "${stringResource(category.labelRes)}${formattedDistance}"
category != null -> category.toString() category != null -> category.toString()
formattedDistance != null -> formattedDistance formattedDistance != null -> formattedDistance
else -> "" else -> ""
@ -291,7 +304,8 @@ fun LocationItem(
//TODO: add rating to location //TODO: add rating to location
if (showMap && false) { if (showMap && false) {
RatingBar(0.66f) RatingBar(0.66f)
} else { }
if (!showMap) {
Compass( Compass(
targetHeading = targetHeading, targetHeading = targetHeading,
modifier = Modifier modifier = Modifier
@ -540,16 +554,23 @@ fun LocationItem(
toolbarActions.add(favAction) toolbarActions.add(favAction)
} }
if (!showMap) { toolbarActions += DefaultToolbarAction(
toolbarActions += DefaultToolbarAction( label = stringResource(id = R.string.menu_map),
label = stringResource(id = R.string.menu_map), icon = Icons.AutoMirrored.Rounded.OpenInNew,
icon = Icons.Rounded.Map ) {
) { viewModel.launch(context)
viewModel.launch(context)
}
} }
val sheetManager = LocalBottomSheetManager.current
val lifecycleOwner = LocalLifecycleOwner.current
val snackbarHostState = LocalSnackbarHostState.current
toolbarActions.add(DefaultToolbarAction(
label = stringResource(de.mm20.launcher2.ui.R.string.menu_customize),
icon = Icons.Rounded.Edit,
action = { sheetManager.showCustomizeSearchableModal(location) }
))
location.fixMeUrl?.let { location.fixMeUrl?.let {
@ -565,6 +586,41 @@ fun LocationItem(
} }
} }
val isHidden by viewModel.isHidden.collectAsState(false)
val hideAction = if (isHidden) {
DefaultToolbarAction(
label = stringResource(R.string.menu_unhide),
icon = Icons.Rounded.Visibility,
action = {
viewModel.unhide()
onBack()
}
)
} else {
DefaultToolbarAction(
label = stringResource(R.string.menu_hide),
icon = Icons.Rounded.VisibilityOff,
action = {
viewModel.hide()
onBack()
lifecycleOwner.lifecycleScope.launch {
val result = snackbarHostState.showSnackbar(
message = context.getString(
R.string.msg_item_hidden,
location.labelOverride ?: location.label
),
actionLabel = context.getString(R.string.action_undo),
duration = SnackbarDuration.Short,
)
if (result == SnackbarResult.ActionPerformed) {
viewModel.unhide()
}
}
})
}
toolbarActions.add(hideAction)
Toolbar( Toolbar(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
leftActions = listOf(DefaultToolbarAction( leftActions = listOf(DefaultToolbarAction(
@ -682,3 +738,80 @@ private fun OpeningSchedule.getNextOpeningHours(): OpeningHours {
now.dayOfWeek < it.dayOfWeek || now.dayOfWeek == it.dayOfWeek && now.toLocalTime() < it.startTime now.dayOfWeek < it.dayOfWeek || now.dayOfWeek == it.dayOfWeek && now.toLocalTime() < it.startTime
} ?: sortedSchedule.first() } ?: sortedSchedule.first()
} }
private val LocationCategory.labelRes
get() = when(this) {
LocationCategory.ART -> R.string.poi_category_art
LocationCategory.BANK -> R.string.poi_category_bank
LocationCategory.BAR -> R.string.poi_category_bar
LocationCategory.BEAUTY -> R.string.poi_category_beauty
LocationCategory.BICYCLE -> R.string.poi_category_bicycle
LocationCategory.RESTAURANT -> R.string.poi_category_restaurant
LocationCategory.FAST_FOOD -> R.string.poi_category_fast_food
LocationCategory.CAFE -> R.string.poi_category_coffee_shop
LocationCategory.HOTEL -> R.string.poi_category_hotel
LocationCategory.SUPERMARKET -> R.string.poi_category_supermarket
LocationCategory.OTHER -> R.string.poi_category_other
LocationCategory.SCHOOL -> R.string.poi_category_school
LocationCategory.PARKING -> R.string.poi_category_parking
LocationCategory.FUEL -> R.string.poi_category_fuel
LocationCategory.TOILETS -> R.string.poi_category_toilets
LocationCategory.PHARMACY -> R.string.poi_category_pharmacy
LocationCategory.HOSPITAL -> R.string.poi_category_hospital
LocationCategory.POST_OFFICE -> R.string.poi_category_post_office
LocationCategory.PUB -> R.string.poi_category_pub
LocationCategory.GRAVE_YARD -> R.string.poi_category_grave_yard
LocationCategory.DOCTORS -> R.string.poi_category_doctors
LocationCategory.POLICE -> R.string.poi_category_police
LocationCategory.DENTIST -> R.string.poi_category_dentist
LocationCategory.LIBRARY -> R.string.poi_category_library
LocationCategory.COLLEGE -> R.string.poi_category_college
LocationCategory.ICE_CREAM -> R.string.poi_category_ice_cream
LocationCategory.THEATER -> R.string.poi_category_theater
LocationCategory.PUBLIC_BUILDING -> R.string.poi_category_public_building
LocationCategory.CINEMA -> R.string.poi_category_cinema
LocationCategory.NIGHTCLUB -> R.string.poi_category_nightclub
LocationCategory.BIERGARTEN -> R.string.poi_category_biergarten
LocationCategory.CLINIC -> R.string.poi_category_clinic
LocationCategory.UNIVERSITY -> R.string.poi_category_university
LocationCategory.DEPARTMENT_STORE -> R.string.poi_category_department_store
LocationCategory.CLOTHES -> R.string.poi_category_clothes
LocationCategory.CONVENIENCE -> R.string.poi_category_convenience
LocationCategory.HAIRDRESSER -> R.string.poi_category_hairdresser
LocationCategory.CAR_REPAIR -> R.string.poi_category_car_repair
LocationCategory.BOOKS -> R.string.poi_category_books
LocationCategory.BAKERY -> R.string.poi_category_bakery
LocationCategory.CAR -> R.string.poi_category_car
LocationCategory.MOBILE_PHONE -> R.string.poi_category_mobile_phone
LocationCategory.FURNITURE -> R.string.poi_category_furniture
LocationCategory.ALCOHOL -> R.string.poi_category_alcohol
LocationCategory.FLORIST -> R.string.poi_category_florist
LocationCategory.HARDWARE -> R.string.poi_category_hardware
LocationCategory.ELECTRONICS -> R.string.poi_category_electronics
LocationCategory.SHOES -> R.string.poi_category_shoes
LocationCategory.MALL -> R.string.poi_category_mall
LocationCategory.OPTICIAN -> R.string.poi_category_optician
LocationCategory.JEWELRY -> R.string.poi_category_jewelry
LocationCategory.GIFT -> R.string.poi_category_gift
LocationCategory.LAUNDRY -> R.string.poi_category_laundry
LocationCategory.COMPUTER -> R.string.poi_category_computer
LocationCategory.TOBACCO -> R.string.poi_category_tobacco
LocationCategory.WINE -> R.string.poi_category_wine
LocationCategory.PHOTO -> R.string.poi_category_photo
LocationCategory.COFFEE_SHOP -> R.string.poi_category_coffee_shop
LocationCategory.SOCCER -> R.string.poi_category_soccer
LocationCategory.BASKETBALL -> R.string.poi_category_basketball
LocationCategory.TENNIS -> R.string.poi_category_tennis
LocationCategory.FITNESS -> R.string.poi_category_fitness
LocationCategory.TRAM_STOP -> R.string.poi_category_tram_stop
LocationCategory.RAILWAY_STATION -> R.string.poi_category_railway_station
LocationCategory.BUS_STATION -> R.string.poi_category_bus_station
LocationCategory.ATM -> R.string.poi_category_atm
LocationCategory.KIOSK -> R.string.poi_category_kiosk
LocationCategory.BUS_STOP -> R.string.poi_category_bus_stop
LocationCategory.MUSEUM -> R.string.poi_category_museum
LocationCategory.PARCEL_LOCKER -> R.string.poi_category_parcel_locker
LocationCategory.CHEMIST -> R.string.poi_category_chemist
LocationCategory.TRAVEL_AGENCY -> R.string.poi_category_travel_agency
LocationCategory.FITNESS_CENTER -> R.string.poi_category_fitness_center
}

View File

@ -80,7 +80,7 @@ interface Location : SavableSearchable {
LocationCategory.LIBRARY, LocationCategory.BOOKS -> R.drawable.ic_location_library to R.color.brown LocationCategory.LIBRARY, LocationCategory.BOOKS -> R.drawable.ic_location_library to R.color.brown
LocationCategory.COLLEGE, LocationCategory.UNIVERSITY -> R.drawable.ic_location_college to R.color.purple LocationCategory.COLLEGE, LocationCategory.UNIVERSITY -> R.drawable.ic_location_college to R.color.purple
LocationCategory.ICE_CREAM -> R.drawable.ic_location_ice_cream to R.color.pink LocationCategory.ICE_CREAM -> R.drawable.ic_location_ice_cream to R.color.pink
LocationCategory.THEATRE -> R.drawable.ic_location_theatre to R.color.purple LocationCategory.THEATER -> R.drawable.ic_location_theatre to R.color.purple
LocationCategory.PUBLIC_BUILDING -> R.drawable.ic_location_public_building to R.color.bluegrey LocationCategory.PUBLIC_BUILDING -> R.drawable.ic_location_public_building to R.color.bluegrey
LocationCategory.CINEMA -> R.drawable.ic_location_cinema to R.color.purple LocationCategory.CINEMA -> R.drawable.ic_location_cinema to R.color.purple
LocationCategory.NIGHTCLUB -> R.drawable.ic_location_nightclub to R.color.purple LocationCategory.NIGHTCLUB -> R.drawable.ic_location_nightclub to R.color.purple
@ -111,9 +111,9 @@ interface Location : SavableSearchable {
LocationCategory.SOCCER -> R.drawable.ic_location_soccer to R.color.green LocationCategory.SOCCER -> R.drawable.ic_location_soccer to R.color.green
LocationCategory.BASKETBALL -> R.drawable.ic_location_basketball to R.color.orange LocationCategory.BASKETBALL -> R.drawable.ic_location_basketball to R.color.orange
LocationCategory.TENNIS -> R.drawable.ic_location_tennis to R.color.orange LocationCategory.TENNIS -> R.drawable.ic_location_tennis to R.color.orange
LocationCategory.FITNESS, LocationCategory.FITNESS_CENTRE -> R.drawable.ic_location_fitness to R.color.orange LocationCategory.FITNESS, LocationCategory.FITNESS_CENTER -> R.drawable.ic_location_fitness to R.color.orange
LocationCategory.TRAM_STOP -> R.drawable.ic_location_tram_stop to R.color.blue LocationCategory.TRAM_STOP -> R.drawable.ic_location_tram_stop to R.color.blue
LocationCategory.RAILWAY_STOP -> R.drawable.ic_location_railway_stop to R.color.lightblue LocationCategory.RAILWAY_STATION -> R.drawable.ic_location_railway_stop to R.color.lightblue
LocationCategory.BUS_STATION, LocationCategory.BUS_STOP -> R.drawable.ic_location_bus_station to R.color.blue LocationCategory.BUS_STATION, LocationCategory.BUS_STOP -> R.drawable.ic_location_bus_station to R.color.blue
LocationCategory.ATM -> R.drawable.ic_location_atm to R.color.green LocationCategory.ATM -> R.drawable.ic_location_atm to R.color.green
LocationCategory.ART -> R.drawable.ic_location_art to R.color.deeporange LocationCategory.ART -> R.drawable.ic_location_art to R.color.deeporange
@ -175,7 +175,7 @@ enum class LocationCategory {
LIBRARY, LIBRARY,
COLLEGE, COLLEGE,
ICE_CREAM, ICE_CREAM,
THEATRE, THEATER,
PUBLIC_BUILDING, PUBLIC_BUILDING,
CINEMA, CINEMA,
NIGHTCLUB, NIGHTCLUB,
@ -215,7 +215,7 @@ enum class LocationCategory {
TENNIS, TENNIS,
FITNESS, FITNESS,
TRAM_STOP, TRAM_STOP,
RAILWAY_STOP, RAILWAY_STATION,
BUS_STATION, BUS_STATION,
ATM, ATM,
ART, ART,
@ -225,7 +225,7 @@ enum class LocationCategory {
PARCEL_LOCKER, PARCEL_LOCKER,
CHEMIST, CHEMIST,
TRAVEL_AGENCY, TRAVEL_AGENCY,
FITNESS_CENTRE FITNESS_CENTER
} }
data class OpeningHours( data class OpeningHours(

View File

@ -930,4 +930,78 @@
<string name="preference_customize_filter_bar">Customize filter bar</string> <string name="preference_customize_filter_bar">Customize filter bar</string>
<string name="preference_customize_filter_bar_summary">Customize which items are included in the filter bar</string> <string name="preference_customize_filter_bar_summary">Customize which items are included in the filter bar</string>
<string name="filter_settings_network_warning">The current filter enables online results by default. Your search queries might unintentionally be sent to external web services. For privacy reasons, this is not recommended.</string> <string name="filter_settings_network_warning">The current filter enables online results by default. Your search queries might unintentionally be sent to external web services. For privacy reasons, this is not recommended.</string>
<string name="poi_category_restaurant">Restaurant</string>
<string name="poi_category_fast_food">Fast food</string>
<string name="poi_category_bar">Bar</string>
<string name="poi_category_cafe">Cafe</string>
<string name="poi_category_hotel">Hotel</string>
<string name="poi_category_supermarket">Supermarket</string>
<string name="poi_category_other">Place of interest</string>
<string name="poi_category_school">School</string>
<string name="poi_category_parking">Parking</string>
<string name="poi_category_fuel">Gas station</string>
<string name="poi_category_toilets">Restroom</string>
<string name="poi_category_pharmacy">Pharmacy</string>
<string name="poi_category_hospital">Hospital</string>
<string name="poi_category_post_office">Post office</string>
<string name="poi_category_pub">Pub</string>
<string name="poi_category_grave_yard">Graveyard</string>
<string name="poi_category_doctors">Doctors</string>
<string name="poi_category_police">Police</string>
<string name="poi_category_dentist">Dentist</string>
<string name="poi_category_library">Library</string>
<string name="poi_category_college">College</string>
<string name="poi_category_ice_cream">Ice cream parlor</string>
<string name="poi_category_theater">Theater</string>
<string name="poi_category_public_building">Public building</string>
<string name="poi_category_cinema">Cinema</string>
<string name="poi_category_nightclub">Nightclub</string>
<string name="poi_category_biergarten">Biergarten</string>
<string name="poi_category_clinic">Clinic</string>
<string name="poi_category_university">University</string>
<string name="poi_category_department_store">Department store</string>
<string name="poi_category_clothes">Apparel store</string>
<string name="poi_category_convenience">Convenience store</string>
<string name="poi_category_hairdresser">Hairdresser</string>
<string name="poi_category_car_repair">Car repair</string>
<string name="poi_category_beauty">Beauty salon</string>
<string name="poi_category_books">Bookstore</string>
<string name="poi_category_bakery">Bakery</string>
<string name="poi_category_car">Car service</string>
<string name="poi_category_mobile_phone">Cell phone store</string>
<string name="poi_category_furniture">Furniture store</string>
<string name="poi_category_alcohol">Liquor store</string>
<string name="poi_category_florist">Flower shop</string>
<string name="poi_category_hardware">Hardware store</string>
<string name="poi_category_electronics">Electronics store</string>
<string name="poi_category_shoes">Shoe store</string>
<string name="poi_category_mall">Mall</string>
<string name="poi_category_optician">Optometrist</string>
<string name="poi_category_jewelry">Jewelry store</string>
<string name="poi_category_gift">Gift shop</string>
<string name="poi_category_bicycle">Bicycle store</string>
<string name="poi_category_laundry">Laundry</string>
<string name="poi_category_computer">Computer store</string>
<string name="poi_category_tobacco">Tobacco store</string>
<string name="poi_category_wine">Wine store</string>
<string name="poi_category_photo">Photo shop</string>
<string name="poi_category_coffee_shop">Coffee Shop</string>
<string name="poi_category_bank">Bank</string>
<string name="poi_category_soccer">Soccer</string>
<string name="poi_category_basketball">Basketball</string>
<string name="poi_category_tennis">Tennis</string>
<string name="poi_category_fitness">Fitness</string>
<string name="poi_category_tram_stop">Tram stop</string>
<string name="poi_category_railway_station">Railway station</string>
<string name="poi_category_bus_station">Bus station</string>
<string name="poi_category_atm">ATM</string>
<string name="poi_category_art">Art store</string>
<string name="poi_category_kiosk">Kiosk</string>
<string name="poi_category_bus_stop">Bus stop</string>
<string name="poi_category_museum">Museum</string>
<string name="poi_category_parcel_locker">Parcel locker</string>
<string name="poi_category_chemist">Drug store</string>
<string name="poi_category_travel_agency">Travel agency</string>
<string name="poi_category_fitness_center">Fitness center</string>
</resources> </resources>