add reload capabi lities among other things

This commit is contained in:
Henry Hiles 2023-04-06 18:36:39 -04:00
parent 49f7f4bd9a
commit ff7710143b
17 changed files with 189 additions and 139 deletions

View file

@ -12,23 +12,6 @@ import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.create import retrofit2.create
//@Module
//@InstallIn(SingletonComponent::class)
//object AppModule {
// @Provides
// @Singleton
// fun provideWeatherApi(): WeatherApi {
// return Retrofit.Builder().baseUrl("https://api.open-meteo.com")
// .addConverterFactory(MoshiConverterFactory.create()).build().create()
// }
//
// @Provides
// @Singleton
// fun provideFusedLocationProviderClient(app: Application): FusedLocationProviderClient {
// return LocationServices.getFusedLocationProviderClient(app)
// }
//}
val appModule = module { val appModule = module {
fun provideWeatherApi(): WeatherApi { fun provideWeatherApi(): WeatherApi {
return Retrofit.Builder().baseUrl("https://api.open-meteo.com") return Retrofit.Builder().baseUrl("https://api.open-meteo.com")

View file

@ -4,15 +4,6 @@ import com.henryhiles.qweather.domain.location.LocationTracker
import org.koin.core.module.dsl.singleOf import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module import org.koin.dsl.module
//@Module
//@InstallIn(SingletonComponent::class)
//abstract class LocationModule {
// @Binds
// @Singleton
// abstract fun bindLocationTracker(defaultLocationTracker: DefaultLocationTracker): LocationTracker
//}
val locationModule = module { val locationModule = module {
singleOf(::LocationTracker) singleOf(::LocationTracker)
} }

View file

@ -4,14 +4,6 @@ import com.henryhiles.qweather.domain.repository.WeatherRepository
import org.koin.core.module.dsl.singleOf import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module import org.koin.dsl.module
//@Module
//@InstallIn(SingletonComponent::class)
//abstract class RepositoryModule {
// @Binds
// @Singleton
// abstract fun bindWeatherRepository(weatherRepository: WeatherRepository): WeatherRepository
//}
val repositoryModule = module { val repositoryModule = module {
singleOf(::WeatherRepository) singleOf(::WeatherRepository)
} }

View file

@ -0,0 +1,9 @@
package com.henryhiles.qweather.domain.util
import androidx.compose.runtime.Composable
import cafe.adriel.voyager.navigator.tab.Tab
interface NavigationTab : Tab {
@Composable
fun Actions()
}

View file

@ -1,4 +1,4 @@
package com.henryhiles.qweather.presentation.components package com.henryhiles.qweather.presentation.components.navigation
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack

View file

@ -0,0 +1,53 @@
package com.henryhiles.qweather.presentation.components.navigation
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.DateRange
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import cafe.adriel.voyager.navigator.tab.TabNavigator
import com.henryhiles.qweather.R
import com.henryhiles.qweather.presentation.tabs.SettingsTab
import com.henryhiles.qweather.presentation.tabs.TodayTab
import com.henryhiles.qweather.presentation.tabs.WeekTab
@Composable
fun BottomBar(navigator: TabNavigator) {
NavigationBar {
NavigationBarItem(
selected = navigator.current == TodayTab,
onClick = { navigator.current = TodayTab },
label = { Text(text = stringResource(id = R.string.tab_today)) },
icon = {
Icon(
imageVector = Icons.Default.Home,
contentDescription = stringResource(id = R.string.tab_today)
)
})
NavigationBarItem(
selected = navigator.current == WeekTab,
onClick = { navigator.current = WeekTab },
label = { Text(text = "Weekly") },
icon = {
Icon(
imageVector = Icons.Default.DateRange,
contentDescription = "Weekly"
)
})
NavigationBarItem(
selected = navigator.current == SettingsTab,
onClick = { navigator.current = SettingsTab },
label = { Text(text = "Settings") },
icon = {
Icon(
imageVector = Icons.Default.Settings,
contentDescription = "Settings"
)
})
}
}

View file

@ -1,4 +1,4 @@
package com.henryhiles.qweather.presentation.components package com.henryhiles.qweather.presentation.components.navigation
import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.RowScope
import androidx.compose.material3.* import androidx.compose.material3.*
@ -7,12 +7,13 @@ import androidx.compose.runtime.Composable
@Composable @Composable
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
fun LargeToolbar( fun LargeToolbar(
title: String, title: @Composable () -> Unit,
actions: @Composable RowScope.() -> Unit = {}, actions: @Composable RowScope.() -> Unit = {},
backButton: Boolean = false
) { ) {
LargeTopAppBar( LargeTopAppBar(
title = { Text(text = title) }, title = title,
navigationIcon = { BackButton() }, navigationIcon = { if (backButton) BackButton() },
actions = actions, actions = actions,
) )
} }

View file

@ -1,4 +1,4 @@
package com.henryhiles.qweather.presentation.components package com.henryhiles.qweather.presentation.components.navigation
import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.RowScope
import androidx.compose.material3.* import androidx.compose.material3.*
@ -7,12 +7,13 @@ import androidx.compose.runtime.Composable
@Composable @Composable
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
fun SmallToolbar( fun SmallToolbar(
title: String, title: @Composable () -> Unit,
actions: @Composable RowScope.() -> Unit = {}, actions: @Composable RowScope.() -> Unit = {},
backButton: Boolean = true
) { ) {
TopAppBar( TopAppBar(
title = { Text(text = title) }, title = title,
navigationIcon = { BackButton() }, navigationIcon = { if (backButton) BackButton() },
actions = actions, actions = actions,
) )
} }

View file

@ -7,6 +7,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -17,7 +18,7 @@ import java.time.format.DateTimeFormatter
@Composable @Composable
fun WeatherDay(dailyWeatherData: DailyWeatherData) { fun WeatherDay(dailyWeatherData: DailyWeatherData) {
val formattedDate = remember { val formattedDate by remember {
derivedStateOf { derivedStateOf {
dailyWeatherData.date.format( dailyWeatherData.date.format(
DateTimeFormatter.ofPattern("E d") DateTimeFormatter.ofPattern("E d")
@ -45,7 +46,7 @@ fun WeatherDay(dailyWeatherData: DailyWeatherData) {
Spacer(modifier = Modifier.width(16.dp)) Spacer(modifier = Modifier.width(16.dp))
Column { Column {
Text( Text(
text = formattedDate.value text = formattedDate
) )
Text(text = "Feels like ${dailyWeatherData.apparentTemperatureMax}°C") Text(text = "Feels like ${dailyWeatherData.apparentTemperatureMax}°C")
} }

View file

@ -0,0 +1,25 @@
package com.henryhiles.qweather.presentation.screen
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import cafe.adriel.voyager.core.screen.Screen
import com.henryhiles.qweather.presentation.components.navigation.LargeToolbar
class AboutScreen : Screen {
@Composable
override fun Content() {
Scaffold(topBar = { LargeToolbar(title = { Text(text = "About") }, backButton = true) }) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(it)
) {
}
}
}
}

View file

@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
@ -13,7 +14,7 @@ import androidx.compose.ui.res.stringResource
import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.koin.getScreenModel import cafe.adriel.voyager.koin.getScreenModel
import com.henryhiles.qweather.R import com.henryhiles.qweather.R
import com.henryhiles.qweather.presentation.components.LargeToolbar import com.henryhiles.qweather.presentation.components.navigation.SmallToolbar
import com.henryhiles.qweather.presentation.components.settings.SettingsItemChoice import com.henryhiles.qweather.presentation.components.settings.SettingsItemChoice
import com.henryhiles.qweather.presentation.components.settings.SettingsSwitch import com.henryhiles.qweather.presentation.components.settings.SettingsSwitch
import com.henryhiles.qweather.presentation.screenmodel.AppearancePreferencesScreenModel import com.henryhiles.qweather.presentation.screenmodel.AppearancePreferencesScreenModel
@ -24,12 +25,16 @@ class AppearanceSettingsScreen : Screen {
override fun Content() = Screen() override fun Content() = Screen()
@Composable @Composable
private fun Screen( private fun Screen() {
screenModel: AppearancePreferencesScreenModel = getScreenModel() val screenModel: AppearancePreferencesScreenModel = getScreenModel()
) {
val ctx = LocalContext.current val ctx = LocalContext.current
Scaffold(topBar = { Toolbar() }) { padding -> Scaffold(topBar = {
SmallToolbar(
title = { Text(text = stringResource(R.string.settings_appearance)) },
backButton = true
)
}) { padding ->
Column( Column(
modifier = Modifier modifier = Modifier
.padding(padding) .padding(padding)
@ -52,13 +57,4 @@ class AppearanceSettingsScreen : Screen {
} }
} }
} }
@Composable
private fun Toolbar(
) {
LargeToolbar(
title = stringResource(R.string.settings_appearance),
)
}
} }

View file

@ -2,60 +2,33 @@ package com.henryhiles.qweather.presentation.screen
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material3.Scaffold
import androidx.compose.material.icons.filled.DateRange import androidx.compose.material3.Text
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.navigator.CurrentScreen import cafe.adriel.voyager.navigator.CurrentScreen
import cafe.adriel.voyager.navigator.tab.TabNavigator import cafe.adriel.voyager.navigator.tab.TabNavigator
import com.henryhiles.qweather.R import com.henryhiles.qweather.domain.util.NavigationTab
import com.henryhiles.qweather.presentation.tabs.SettingsTab import com.henryhiles.qweather.presentation.components.navigation.BottomBar
import com.henryhiles.qweather.presentation.components.navigation.SmallToolbar
import com.henryhiles.qweather.presentation.tabs.TodayTab import com.henryhiles.qweather.presentation.tabs.TodayTab
import com.henryhiles.qweather.presentation.tabs.WeekTab
class MainScreen : Screen { class MainScreen : Screen {
@Composable @Composable
override fun Content() { override fun Content() {
TabNavigator(tab = TodayTab) { navigator -> TabNavigator(tab = TodayTab) {
Scaffold( Scaffold(
topBar = {
SmallToolbar(
title = { Text(text = "QWeather") },
actions = {
(it.current as? NavigationTab)?.Actions()
}
)
},
bottomBar = { bottomBar = {
NavigationBar { BottomBar(navigator = it)
NavigationBarItem(
selected = navigator.current == TodayTab,
onClick = { navigator.current = TodayTab },
label = { Text(text = stringResource(id = R.string.tab_today)) },
icon = {
Icon(
imageVector = Icons.Default.Home,
contentDescription = stringResource(id = R.string.tab_today)
)
})
NavigationBarItem(
selected = navigator.current == WeekTab,
onClick = { navigator.current = WeekTab },
label = { Text(text = "Weekly") },
icon = {
Icon(
imageVector = Icons.Default.DateRange,
contentDescription = "Weekly"
)
})
NavigationBarItem(
selected = navigator.current == SettingsTab,
onClick = { navigator.current = SettingsTab },
label = { Text(text = "Settings") },
icon = {
Icon(
imageVector = Icons.Default.Settings,
contentDescription = "Settings"
)
})
}
} }
) { padding -> ) { padding ->
Box(modifier = Modifier.padding(padding)) { Box(modifier = Modifier.padding(padding)) {

View file

@ -1,5 +1,6 @@
package com.henryhiles.qweather.presentation.screenmodel package com.henryhiles.qweather.presentation.screenmodel
import android.location.Location
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
@ -23,11 +24,12 @@ class DailyWeatherScreenModel constructor(
) : ScreenModel { ) : ScreenModel {
var state by mutableStateOf(DailyWeatherState()) var state by mutableStateOf(DailyWeatherState())
private set private set
private var currentLocation: Location? = null
fun loadWeatherInfo() { fun loadWeatherInfo() {
coroutineScope.launch { coroutineScope.launch {
state = state.copy(isLoading = true, error = null) state = state.copy(isLoading = true, error = null)
val currentLocation = locationTracker.getCurrentLocation() currentLocation = locationTracker.getCurrentLocation()
currentLocation?.let { location -> currentLocation?.let { location ->
state = when (val result = state = when (val result =
repository.getDailyWeatherData(location.latitude, location.longitude)) { repository.getDailyWeatherData(location.latitude, location.longitude)) {
@ -38,7 +40,6 @@ class DailyWeatherScreenModel constructor(
error = null error = null
) )
} }
is Resource.Error -> { is Resource.Error -> {
state.copy( state.copy(
dailyWeatherData = null, dailyWeatherData = null,

View file

@ -1,26 +1,26 @@
package com.henryhiles.qweather.presentation.tabs package com.henryhiles.qweather.presentation.tabs
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Settings import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.icons.outlined.Palette import androidx.compose.material.icons.outlined.Palette
import androidx.compose.material3.Scaffold import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import cafe.adriel.voyager.navigator.tab.Tab import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.currentOrThrow
import cafe.adriel.voyager.navigator.tab.TabOptions import cafe.adriel.voyager.navigator.tab.TabOptions
import com.henryhiles.qweather.R import com.henryhiles.qweather.R
import com.henryhiles.qweather.presentation.components.SmallToolbar import com.henryhiles.qweather.domain.util.NavigationTab
import com.henryhiles.qweather.presentation.components.settings.SettingsCategory import com.henryhiles.qweather.presentation.components.settings.SettingsCategory
import com.henryhiles.qweather.presentation.screen.AboutScreen
import com.henryhiles.qweather.presentation.screen.AppearanceSettingsScreen import com.henryhiles.qweather.presentation.screen.AppearanceSettingsScreen
object SettingsTab : Tab { object SettingsTab : NavigationTab {
override val options: TabOptions override val options: TabOptions
@Composable @Composable
get() { get() {
@ -38,26 +38,25 @@ object SettingsTab : Tab {
@Composable @Composable
override fun Content() { override fun Content() {
Scaffold( Column {
topBar = { SettingsCategory(
SmallToolbar( icon = Icons.Outlined.Palette,
title = stringResource(R.string.tab_settings), text = stringResource(R.string.settings_appearance),
) subtext = stringResource(R.string.settings_appearance_description),
}, destination = ::AppearanceSettingsScreen
) { )
Column( }
modifier = Modifier }
.padding(it)
.verticalScroll(rememberScrollState())
) {
SettingsCategory( @Composable
icon = Icons.Outlined.Palette, override fun Actions() {
text = stringResource(R.string.settings_appearance), val navigator = LocalNavigator.currentOrThrow.parent
subtext = stringResource(R.string.settings_appearance_description),
destination = ::AppearanceSettingsScreen IconButton(onClick = { navigator?.push(AboutScreen()) }) {
) Icon(
} imageVector = Icons.Outlined.Info,
contentDescription = stringResource(R.string.action_open_about)
)
} }
} }
} }

View file

@ -5,10 +5,8 @@ import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Home import androidx.compose.material.icons.filled.Home
import androidx.compose.material3.AlertDialog import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.*
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -18,16 +16,16 @@ import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.koin.getScreenModel import cafe.adriel.voyager.koin.getScreenModel
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions import cafe.adriel.voyager.navigator.tab.TabOptions
import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.rememberPermissionState import com.google.accompanist.permissions.rememberPermissionState
import com.henryhiles.qweather.R import com.henryhiles.qweather.R
import com.henryhiles.qweather.domain.util.NavigationTab
import com.henryhiles.qweather.presentation.components.weather.WeatherCard import com.henryhiles.qweather.presentation.components.weather.WeatherCard
import com.henryhiles.qweather.presentation.components.weather.WeatherForecast import com.henryhiles.qweather.presentation.components.weather.WeatherForecast
import com.henryhiles.qweather.presentation.screenmodel.HourlyWeatherScreenModel import com.henryhiles.qweather.presentation.screenmodel.HourlyWeatherScreenModel
object TodayTab : Tab { object TodayTab : NavigationTab {
override val options: TabOptions override val options: TabOptions
@Composable @Composable
get() { get() {
@ -43,7 +41,7 @@ object TodayTab : Tab {
} }
} }
@OptIn(ExperimentalMaterial3Api::class, ExperimentalPermissionsApi::class) @OptIn(ExperimentalPermissionsApi::class)
@Composable @Composable
override fun Content() { override fun Content() {
val weatherViewModel = getScreenModel<HourlyWeatherScreenModel>() val weatherViewModel = getScreenModel<HourlyWeatherScreenModel>()
@ -92,4 +90,16 @@ object TodayTab : Tab {
} }
} }
} }
@Composable
override fun Actions() {
val viewModel: HourlyWeatherScreenModel = getScreenModel()
IconButton(onClick = { viewModel.loadWeatherInfo() }) {
Icon(
imageVector = Icons.Filled.Refresh,
contentDescription = stringResource(R.string.action_reload)
)
}
}
} }

View file

@ -7,6 +7,7 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.foundation.text.selection.SelectionContainer
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.DateRange import androidx.compose.material.icons.filled.DateRange
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
@ -16,15 +17,15 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import cafe.adriel.voyager.koin.getScreenModel import cafe.adriel.voyager.koin.getScreenModel
import cafe.adriel.voyager.navigator.tab.Tab
import cafe.adriel.voyager.navigator.tab.TabOptions import cafe.adriel.voyager.navigator.tab.TabOptions
import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.rememberPermissionState import com.google.accompanist.permissions.rememberPermissionState
import com.henryhiles.qweather.R import com.henryhiles.qweather.R
import com.henryhiles.qweather.domain.util.NavigationTab
import com.henryhiles.qweather.presentation.components.weather.WeatherDay import com.henryhiles.qweather.presentation.components.weather.WeatherDay
import com.henryhiles.qweather.presentation.screenmodel.DailyWeatherScreenModel import com.henryhiles.qweather.presentation.screenmodel.DailyWeatherScreenModel
object WeekTab : Tab { object WeekTab : NavigationTab {
override val options: TabOptions override val options: TabOptions
@Composable @Composable
get() { get() {
@ -92,4 +93,16 @@ object WeekTab : Tab {
} }
} }
} }
@Composable
override fun Actions() {
val viewModel: DailyWeatherScreenModel = getScreenModel()
IconButton(onClick = { viewModel.loadWeatherInfo() }) {
Icon(
imageVector = Icons.Filled.Refresh,
contentDescription = stringResource(R.string.action_reload)
)
}
}
} }

View file

@ -6,6 +6,8 @@
<string name="action_back">Back</string> <string name="action_back">Back</string>
<string name="action_confirm">Confirm</string> <string name="action_confirm">Confirm</string>
<string name="action_open_about">About</string>
<string name="action_reload">Reload</string>
<string name="appearance_theme">Theme</string> <string name="appearance_theme">Theme</string>
<string name="appearance_monet">Dynamic Theme</string> <string name="appearance_monet">Dynamic Theme</string>