Merge branch 'main' into l10n_main

Signed-off-by: Pranshul <pranshul.devmain@gmail.com>
This commit is contained in:
Pranshul authored and GitHub committed 2026-08-09 11:04:49 +05:30
commit f6a62bbeec
22 files changed
+155 -48

No files matched your search

+2
View File
@@ -64,6 +64,8 @@
- **China**
- **AccuWeather**
- **Meteo AM**
- **IPMA**
- **WeatherApi.com**
- _**And more to be added**_
# 🌐 Translate the app on [Crowdin](https://crowdin.com/project/weathermaster)
+14 -2
View File
@@ -32,6 +32,8 @@ val hasKeystore = keystoreFile.exists()
val versionNameString = "3.8.0"
val playStore = false
android {
namespace = "com.pranshulgg.weather_master_app"
compileSdk {
@@ -40,10 +42,14 @@ android {
android.buildFeatures.buildConfig = true
defaultConfig {
applicationId = "com.pranshulgg.weather_master_app"
applicationId = if (playStore) {
"com.pranshulgg.weather_master"
} else {
"com.pranshulgg.weather_master_app"
}
minSdk = 26
targetSdk = 36
versionCode = 57
versionCode = 58
versionName = versionNameString
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
@@ -77,6 +83,12 @@ android {
"APP_VERSION",
"\"v${versionNameString}\""
)
buildConfigField(
"boolean",
"IS_PLAYSTORE_BUILD",
playStore.toString()
)
}
signingConfigs {
@@ -165,16 +165,16 @@ fun getHeadline(
val tempMin = formatterTemperature(summaryData.temps.min)
val tempSentence = when {
tempMax >= 35 ->
summaryData.temps.max >= 35 ->
context.getString(R.string.summary_temp_template_extreme, "${tempMax}°", "${tempMin}°")
tempMax >= 25 ->
summaryData.temps.max >= 25 ->
context.getString(R.string.summary_temp_template_warm, "${tempMax}°", "${tempMin}°")
tempMax >= 15 ->
summaryData.temps.max >= 15 ->
context.getString(R.string.summary_temp_template_mild, "${tempMax}°", "${tempMin}°")
tempMax >= 5 ->
summaryData.temps.max >= 5 ->
context.getString(R.string.summary_temp_template_cool, "${tempMax}°", "${tempMin}°")
else ->
@@ -1,5 +1,6 @@
package com.pranshulgg.weather_master_app.feature.alerts
import android.util.Log
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
@@ -50,6 +51,10 @@ fun AlertsScreen(navController: NavController, locationId: String) {
}
if (!uiState.alerts.isNotEmpty()) {
return
}
LargeTopBarScaffold(
title = "Alerts",
navigationIcon = { NavigateUpBtn(navController) },
@@ -1,6 +1,7 @@
package com.pranshulgg.weather_master_app.feature.blocks.screens.humidity.components
import android.content.Context
import android.util.Log
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -32,6 +33,7 @@ import com.pranshulgg.weather_master_app.core.utils.formatters.to12HourTimeStrin
import com.pranshulgg.weather_master_app.core.utils.formatters.to24HourTimeString
import com.pranshulgg.weather_master_app.feature.shared.components.CardsHeader
import kotlin.collections.map
import kotlin.isNaN
import kotlin.math.max
import kotlin.math.roundToInt
@@ -90,8 +92,13 @@ fun DewPointHourlyCard(
val percentage = ((item.dewPoint!!.minus(min)).div((max - min))).times(
100
).roundToInt()
val barHeight = max((percentage.div(100.0)).times(140), 5.0)
).takeIf { !it.isNaN() } ?: 0.0
val barHeight = max(
(percentage.div(100.0)).times(140),
5.0
)
val barColor = when {
item.dewPoint < 0 -> Color(0xFF1565C0)
@@ -102,6 +109,15 @@ fun DewPointHourlyCard(
else -> Color(0xFFC62828)
}
// NEVER CRASH
val temperatureText = item.dewPoint
.takeIf { it.isFinite() }
?.let { formatter(it) }
?.takeIf { it.isFinite() }
?.roundToInt()
?.let { "$it°" }
?: "—"
if (index == 0) Gap(horizontal = 16.dp)
Column(
@@ -130,7 +146,7 @@ fun DewPointHourlyCard(
}
Gap(5.dp)
Text(
"${formatter(item.dewPoint)?.roundToInt()}°",
temperatureText,
color = MaterialTheme.colorScheme.primary,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold
@@ -69,7 +69,9 @@ fun HumidityHourlyCard(data: List<WeatherHourly>, zoneId: String) {
val item = data[index]
val barHeight = max((item.humidity!!.div(100.0)).times(140), 5.0)
val barHeight =
max((item.humidity!!.div(100.0)).times(140), 5.0).takeIf { !it.isNaN() }
?: 5.0
val barColor = when {
item.humidity < 20 -> Color(0xFFC62828)
@@ -1,6 +1,8 @@
package com.pranshulgg.weather_master_app.feature.editlocation.ui
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import com.pranshulgg.weather_master_app.R
import com.pranshulgg.weather_master_app.core.ui.components.TextAlertDialog
import com.pranshulgg.weather_master_app.feature.editlocation.EditLocationViewModel
import com.pranshulgg.weather_master_app.feature.locations.LocationsScreenViewModel
@@ -18,8 +20,8 @@ object EditLocationScreenDialogs {
show = uiState.isConfirmationDialogOpen,
onConfirm = onConfirm,
onDismiss = viewModel::hideConfirmationDialog,
title = "Delete Location",
message = "Are you sure you want to delete this location?"
title = stringResource(R.string.confirm_delete_location),
message = stringResource(R.string.alert_delete_location_secondary)
)
}
}
@@ -156,10 +156,14 @@ fun IntroScreen(navController: NavController) {
contentPadding = ButtonDefaults.contentPaddingFor(btnSize),
shapes = ButtonDefaults.shapes()
) {
Text("Enable Location", style = ButtonDefaults.textStyleFor(btnSize))
Text(
if (isLoading) "Loading..." else "Enable Location",
style = ButtonDefaults.textStyleFor(btnSize)
)
}
Gap(12.dp)
OutlinedButton(
enabled = !isLoading,
onClick = {
navController.navigate(NavRoutes.SEARCH)
},
@@ -1,6 +1,8 @@
package com.pranshulgg.weather_master_app.feature.locations.ui
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import com.pranshulgg.weather_master_app.R
import com.pranshulgg.weather_master_app.core.ui.components.TextAlertDialog
import com.pranshulgg.weather_master_app.feature.locations.LocationsScreenViewModel
import com.pranshulgg.weather_master_app.feature.shared.WeatherViewModel
@@ -21,7 +23,7 @@ fun LocationScreenConfirmationDialog(
viewModel.hideConfirmationDialog()
},
onDismiss = viewModel::hideConfirmationDialog,
title = "Delete Location",
message = "Are you sure you want to delete this location?"
title = stringResource(R.string.confirm_delete_location),
message = stringResource(R.string.alert_delete_location_secondary)
)
}
@@ -65,7 +65,8 @@ data class MainScreenUiState(
val isNewVersionAvailable: Boolean = false,
val lastestVersionUrl: String = "https://github.com/PranshulGG/WeatherMaster/releases/latest",
val isUnsupportedSourceDialogOpen: Boolean = false,
val isChangelogSheetOpen: Boolean = false
val isChangelogSheetOpen: Boolean = false,
val isGooglePlayStoreRelease: Boolean = BuildConfig.IS_PLAYSTORE_BUILD
)
@OptIn(ExperimentalMaterial3Api::class)
@@ -25,7 +25,9 @@ class MainScreenViewModel @Inject constructor(
init {
viewModelScope.launch {
checkForUpdates()
if (!_uiState.value.isGooglePlayStoreRelease) {
checkForUpdates()
}
}
}
@@ -1,31 +1,49 @@
package com.pranshulgg.weather_master_app.feature.settings
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.BasicAlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ListItem
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.pranshulgg.weather_master_app.R
import com.pranshulgg.weather_master_app.core.ui.components.DialogBasic
import com.pranshulgg.weather_master_app.core.ui.components.LargeTopBarScaffold
import com.pranshulgg.weather_master_app.core.ui.components.NavigateUpBtn
import com.pranshulgg.weather_master_app.core.ui.components.SettingSection
import com.pranshulgg.weather_master_app.core.ui.components.SettingTile
import com.pranshulgg.weather_master_app.core.ui.components.SettingsTileIcon
import com.pranshulgg.weather_master_app.core.ui.components.WeatherIconBox
import com.pranshulgg.weather_master_app.core.ui.navigation.NavRoutes
import com.pranshulgg.weather_master_app.core.utils.locale.getCurrentAppLocale
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SettingsScreen(navController: NavController) {
val uriHandler = LocalUriHandler.current
var isDonationDialogOpen by remember { mutableStateOf(false) }
LargeTopBarScaffold(
title = stringResource(R.string.settings),
navigationIcon = { NavigateUpBtn(navController) },
@@ -47,12 +65,12 @@ fun SettingsScreen(navController: NavController) {
description = stringResource(R.string.setting_appearance_secondary),
onClick = { navController.navigate(NavRoutes.APPEARANCE) }
),
// SettingTile.ActionTile(
// leading = { SettingsTileIcon(R.drawable.favorite_24px) },
// title = "Support",
// description = "If you enjoy the app, consider supporting its development",
// onClick = { uriHandler.openUri("https://github.com/sponsors/PranshulGG?frequency=one-time&sponsor=PranshulGG") }
// )
SettingTile.ActionTile(
leading = { SettingsTileIcon(R.drawable.favorite_24px) },
title = "Support",
description = "If you enjoy the app, consider supporting its development",
onClick = { isDonationDialogOpen = true }
)
)
)
@@ -101,4 +119,45 @@ fun SettingsScreen(navController: NavController) {
)
}
}
DialogBasic(
show = isDonationDialogOpen,
title = "Donate",
dismissText = stringResource(R.string.action_cancel),
showOnlyDismissAction = true,
onConfirm = {},
onDismiss = { isDonationDialogOpen = false },
) {
Column(
) {
DonateListItem(
"Ko-fi",
"Ko-fi.com/pranshulgg",
R.drawable.kofi_symbol
) { uriHandler.openUri("https://ko-fi.com/pranshulgg") }
DonateListItem(
"Liberapay",
"liberapay.com/PranshulGG",
R.drawable.liberapay_logo,
) { uriHandler.openUri("https://liberapay.com/PranshulGG") }
DonateListItem(
"Github sponsors",
"github.com/sponsors/PranshulGG",
R.drawable.gitub_logo_colored,
) { uriHandler.openUri("https://github.com/sponsors/PranshulGG?frequency=one-time&sponsor=PranshulGG") }
}
}
}
@Composable
private fun DonateListItem(headline: String, description: String, icon: Int, onClick: () -> Unit) {
ListItem(
colors = ListItemDefaults.colors(containerColor = Color.Transparent),
leadingContent = { WeatherIconBox(icon, size = 28.dp) },
headlineContent = { Text(headline) },
supportingContent = { Text(description) },
modifier = Modifier
.clickable(onClick = onClick)
.padding(horizontal = 14.dp)
)
}
@@ -44,20 +44,4 @@ object SharedDialogs {
}
// @Composable
// fun ChangelogDialog(
// show: Boolean,
// onDismiss: () -> Unit,
// version: String,
// ) {
// DialogBasic(
// show = show,
// onDismiss = onDismiss,
// title = "Change Log $version",
// dismissText = stringResource(R.string.action_ok),
// showOnlyDismissAction = true
// ) {
// ChangelogContent()
// }
// }
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

+2 -2
View File
@@ -277,11 +277,11 @@
<string name="settings_source_request_title">Onko sinulla säätietojen tarjoaja lisättäväksi? Voit toivoa sitä tästä</string>
<string name="action_request">Toivo tarjoajaa</string>
<string name="source_credits_label">%1$s ja muut</string>
<string name="weather_wind_direction_from">Tuuli:</string>
<string name="weather_wind_direction_from">Tuuli: %1$s</string>
<string name="day_length_hr">%1$s tuntia</string>
<string name="error_no_results">Tuloksia ei löytynyt</string>
<string name="summary_overview_template_same_condition">Luvassa %1$s päivällä ja yöllä.</string>
<string name="summary_overview_template_day_night_condition">Päivällä luvassa poutaa, yöksi %2$s.</string>
<string name="summary_overview_template_day_night_condition">Päivällä luvassa %1$s, yöllä %2$s.</string>
<string name="summary_rain_template_day_night">Päivällä on luvassa sadetta noin kello %1$s %2$s todennäköisyydellä. Yöllä on %3$s todennäköisyys sateeseen noin kello %4$s.</string>
<string name="summary_rain_template_day">Päivällä on luvassa sadetta noin kello %1$s %2$s todennäköisyydellä.</string>
<string name="summary_rain_template_night">Yöllä on %1$s todennäköisyys sateeseen noin kello %2$s.</string>
+1 -1
View File
@@ -183,7 +183,7 @@
<string name="setting_notification_permission_secondary">יישום זה שולח התראה ברקע כאשר יש עדכוני מזג אוויר</string>
<string name="setting_notification">התראה</string>
<string name="time_hours">%1$s שעות</string>
<string name="time_hour">שעה</string>
<string name="time_hour">%1$s שעה</string>
<string name="info_already_ignoring_battery_opt">מיטוב הסוללה כבר בהתעלמות</string>
<string name="setting_additional">הגדרות נוספות</string>
<string name="setting_update_interval">מרווח זמן בין עדכונים</string>
+1 -1
View File
@@ -95,7 +95,7 @@
<string name="action_delete">Apagar</string>
<string name="error_delete_default_location">Não é possível eliminar o local padrão</string>
<string name="setting_app_looks">Aparência da aplicação</string>
<string name="temp_feels_like">Sensação térmica</string>
<string name="temp_feels_like">Sensação térmica %1$s</string>
<string name="temp_max">Máx.: %1$s</string>
<string name="temp_min">Mín.: %1$s</string>
<string name="search_results_provided">Resultados da pesquisa fornecido por %1$s</string>
+4 -4
View File
@@ -11,10 +11,10 @@
<string name="weather_precipitation_hours">降雨時長</string>
<string name="time_now">現在</string>
<string name="day_today">今天</string>
<string name="weather_refresh_delay">請在 %1$d 分鐘後重新整理</string>
<string name="error_generic">發生錯誤。請再試一次</string>
<string name="weather_moon">月亮</string>
<string name="weather_sun">太陽</string>
<string name="weather_refresh_delay">請稍候 %1$d 分鐘 刷新後</string>
<string name="error_generic">發生錯誤。 請再試一次</string>
<string name="weather_moon">月相</string>
<string name="weather_sun">週日</string>
<string name="weather_humidity">濕度</string>
<string name="weather_pressure">氣壓</string>
<string name="weather_wind">風速</string>
+14
View File
@@ -395,6 +395,20 @@
<string name="weather_alerts">Alerts</string>
<string name="dew_point_scale_dry_comfortable">Dry and comfortable</string>
<string name="dew_point_scale_comfortable">Comfortable</string>
<string name="dew_point_scale_sticky">Sticky</string>
<string name="dew_point_scale_muggy">Muggy</string>
<string name="dew_point_scale_uncomfortable">Uncomfortable</string>
<string name="action_requires_restart">Requires restart</string>
<string name="location_latitude">Latitude</string>
<string name="location_longitude">Longitude</string>
<string name="settings_support">Support</string>
<string name="settings_support_secondary">If you enjoy the app, consider supporting its development</string>
<string name="location_your_device_location">Your device language</string>
<string name="label_system">System</string>
</resources>
<!--<string name=""></string>-->
@@ -1,4 +1,4 @@
<p><i>WeatherMaster</i> inspired by the Google Pixel weather app, but with more features</p>
<p><i>WeatherMaster</i>Inspired by the Google Pixel weather app, but with more features</p>
<br>
<p>Features both the Pixel Weather-inspired design and the original Froggy style, with summaries, multiple weather and search providers, personalization options, and more.</p>
<br>
@@ -17,5 +17,7 @@
<li><b>China</b></li>
<li><b>AccuWeather</b></li>
<li><b>Meteo AM</b></li>
<li><b>IPMA</b></li>
<li><b>WeatherApi.com</b></li>
<li><b>And more to be added</b></li>
</ul>