Feat: Added batter status widget.

Signed-off-by: HeCodes2Much <wayne6324@gmail.com>
This commit is contained in:
HeCodes2Much
2024-06-08 22:03:39 +01:00
parent ef05e338c6
commit 316b755ead
11 changed files with 346 additions and 151 deletions

View File

@@ -24,16 +24,6 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
manifestPlaceholders["internetPermission"] = "android.permission.INTERNET"
val weatherFile = project.rootProject.file("weather.properties")
val properties = Properties()
properties.load(weatherFile.inputStream())
val apiKey = properties.getProperty("WEATHER_API_KEY") ?: ""
buildConfigField(
type = "String",
name = "API_KEY",
value = "\"$apiKey\""
)
}
buildTypes {
@@ -82,14 +72,26 @@ android {
productFlavors {
create("withInternet") {
dimension = "internet"
manifestPlaceholders["hasInternetPermission"] = true
manifestPlaceholders["internetPermission"] = "android.permission.INTERNET"
val weatherFile = project.rootProject.file("weather.properties")
val properties = Properties()
properties.load(weatherFile.inputStream())
val apiKey = properties.getProperty("WEATHER_API_KEY") ?: ""
buildConfigField(
type = "String",
name = "API_KEY",
value = "\"$apiKey\""
)
}
create("withoutInternet") {
dimension = "internet"
manifestPlaceholders["hasInternetPermission"] = false
manifestPlaceholders["internetPermission"] = "REMOVE"
buildConfigField(
type = "String",
name = "API_KEY",
value = "\"REMOVE\""
)
}
}

View File

@@ -13,6 +13,7 @@ import android.text.style.StyleSpan
import android.view.View
import android.widget.Toast
import androidx.core.text.getSpans
import java.util.Locale
/**
* Returns [Spannable] where the term is
@@ -101,4 +102,8 @@ fun String.showLongToast(context: Context) {
fun String.showShortToast(context: Context) {
Toast.makeText(context, this, Toast.LENGTH_SHORT).show()
}
fun String.capitalizeEachWord(): String {
return this.split(" ").joinToString(" ") { it.replaceFirstChar { str -> if (str.isLowerCase()) str.titlecase(Locale.getDefault()) else str.toString() } }
}

View File

@@ -257,13 +257,11 @@ class AppHelper @Inject constructor() {
): WeatherResponse {
// Check if cached data is available and not expired
val cachedWeatherData = context.getWeatherDataFromCache()
if (cachedWeatherData != null && System.currentTimeMillis() - cachedWeatherData.timestamp < TimeUnit.MINUTES.toMillis(
5
)
) {
if (cachedWeatherData?.let { System.currentTimeMillis() - it.timestamp < TimeUnit.MINUTES.toMillis(15) } == true) {
return cachedWeatherData.weatherResponse
}
// Fetch weather data from the network
val apiKey = BuildConfig.API_KEY
val units = "metric"
@@ -306,8 +304,8 @@ class AppHelper @Inject constructor() {
// Function to retrieve weather data from cache
private fun Context.getWeatherDataFromCache(): CachedWeatherData? {
val sharedPreferences = getSharedPreferences("WeatherCache", Context.MODE_PRIVATE)
val timestamp = sharedPreferences.getLong("timestamp", -1)
val sharedPreferences = getSharedPreferences(Constants.WEATHER_PREFS, Context.MODE_PRIVATE)
val timestamp = sharedPreferences.getLong("cachedDataTimestamp", -1)
val weatherResponseJson = sharedPreferences.getString("weatherResponse", null)
if (timestamp != -1L && weatherResponseJson != null) {
val weatherResponse = Gson().fromJson(weatherResponseJson, WeatherResponse::class.java)

View File

@@ -28,5 +28,7 @@ data class Weather(
)
data class Sys(
val country: String
val country: String,
val sunrise: Int,
val sunset: Int
)

View File

@@ -1,22 +1,30 @@
package com.github.droidworksstudio.launcher.ui.widgets
import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.drawable.GradientDrawable
import android.os.BatteryManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.github.droidworksstudio.common.capitalizeEachWord
import com.github.droidworksstudio.common.hasInternetPermission
import com.github.droidworksstudio.common.hideKeyboard
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.databinding.FragmentWidgetsBinding
@@ -27,7 +35,10 @@ import com.github.droidworksstudio.launcher.listener.ScrollEventListener
import com.github.droidworksstudio.launcher.utils.Constants
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import javax.inject.Inject
@AndroidEntryPoint
@@ -52,7 +63,6 @@ class WidgetFragment : Fragment(),
): View {
// Inflate the layout for this fragment
_binding = FragmentWidgetsBinding.inflate(inflater, container, false)
_binding = binding
return binding.root
}
@@ -65,6 +75,7 @@ class WidgetFragment : Fragment(),
initializeInjectedDependencies()
setupWeatherWidget()
setupBatteryWidget()
observeSwipeTouchListener()
observeClickListener()
}
@@ -72,7 +83,7 @@ class WidgetFragment : Fragment(),
private fun initializeInjectedDependencies() {
context = requireContext()
binding.nestScrollView.hideKeyboard()
//
binding.nestScrollView.scrollEventListener = this
}
@@ -81,29 +92,35 @@ class WidgetFragment : Fragment(),
context.getSharedPreferences(Constants.WEATHER_PREFS, Context.MODE_PRIVATE)
val latitude = sharedPreferences.getFloat(Constants.LATITUDE, 0f)
val longitude = sharedPreferences.getFloat(Constants.LONGITUDE, 0f)
val timestamp = convertTimestampToReadableDate(sharedPreferences.getLong("cachedDataTimestamp", 0))
lifecycleScope.launch {
try {
if (!context.hasInternetPermission()) return@launch
binding.weatherRoot.visibility = View.VISIBLE
val weatherResponse = appHelper.fetchWeatherData(context, latitude, longitude)
Log.d("weatherResponse", "$weatherResponse")
val temperatureScale = if (preferenceHelper.weatherUnits == Constants.Units.Metric) getString(R.string.weather_c) else getString(
R.string.weather_f
val temperatureScale = if (preferenceHelper.weatherUnits == Constants.Units.Metric) getString(R.string.widget_c) else getString(
R.string.widget_f
)
val speedScale = if (preferenceHelper.weatherUnits == Constants.Units.Metric) getString(R.string.weather_mps) else getString(R.string.weather_mph)
val speedScale = if (preferenceHelper.weatherUnits == Constants.Units.Metric) getString(R.string.widget_weather_mps) else getString(R.string.widget_weather_mph)
binding.weatherCity.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherTemperature.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherDescription.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherWind.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherHumidity.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherPressure.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherRefresh.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherLastRun.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherRefresh.typeface = ResourcesCompat.getFont(requireActivity(), R.font.weather)
binding.weatherCity.text = getString(R.string.widget_weather_location, weatherResponse.name, weatherResponse.sys.country)
binding.weatherTemperature.text = getString(R.string.widget_weather_temp, weatherResponse.main.temp, temperatureScale)
binding.weatherDescription.text = getString(R.string.widget_weather_description, weatherResponse.weather[0].description)
binding.weatherDescription.text = getString(R.string.widget_weather_description, weatherResponse.weather[0].description).capitalizeEachWord()
binding.weatherWind.text = getString(R.string.widget_weather_wind, weatherResponse.wind.speed, speedScale)
binding.weatherHumidity.text = getString(R.string.widget_weather_humidity, weatherResponse.main.humidity)
binding.weatherPressure.text = getString(R.string.widget_weather_pressure, weatherResponse.main.pressure)
binding.weatherLastRun.text = timestamp
binding.weatherRefresh.text = getString(R.string.widget_weather_refresh, getString(R.string.refresh_icon))
val weatherIcon = createWeatherIcon(context, setWeatherIcon(context, weatherResponse.weather[0].id))
binding.weatherIcon.setImageBitmap(weatherIcon)
@@ -112,10 +129,7 @@ class WidgetFragment : Fragment(),
if (weatherWidgetDrawable is GradientDrawable) {
weatherWidgetDrawable.setColor(preferenceHelper.widgetBackgroundColor)
}
binding.weatherButtonRefresh.setColorFilter(preferenceHelper.widgetTextColor)
} catch (e: Exception) {
binding.weatherRoot.visibility = View.GONE
Log.e("Weather", "Failed to fetch weather data: ${e.message}")
}
}
@@ -138,10 +152,10 @@ class WidgetFragment : Fragment(),
}
private fun setWeatherIcon(context: Context, id: Int): String {
var icon = ""
val icon: String
val idDivided = id / 100
val hourOfDay = Calendar.getInstance().get(Calendar.HOUR_OF_DAY)
if (idDivided * 100 == 800) {
val hourOfDay = Calendar.getInstance().get(Calendar.HOUR_OF_DAY)
icon = if (hourOfDay in 7..19) {
context.getString(R.string.weather_sunny)
} else {
@@ -161,6 +175,70 @@ class WidgetFragment : Fragment(),
return icon
}
private fun convertTimestampToReadableDate(timestamp: Long): String {
val date = Date(timestamp)
val format = SimpleDateFormat("hh:mm aa", Locale.getDefault())
return format.format(date)
}
private fun setupBatteryWidget() {
try {
binding.batteryLevel.setTextColor(preferenceHelper.widgetTextColor)
binding.chargingStatus.setTextColor(preferenceHelper.widgetTextColor)
binding.batteryHealth.setTextColor(preferenceHelper.widgetTextColor)
binding.batteryVoltage.setTextColor(preferenceHelper.widgetTextColor)
binding.batteryTemperature.setTextColor(preferenceHelper.widgetTextColor)
val weatherBatteryDrawable = binding.batteryRoot.background
if (weatherBatteryDrawable is GradientDrawable) {
weatherBatteryDrawable.setColor(preferenceHelper.widgetBackgroundColor)
}
} catch (e: Exception) {
Log.e("Battery", "Failed to fetch battery data: ${e.message}")
}
binding.batteryRoot.visibility = View.VISIBLE
}
private val batteryReceiver = object : BroadcastReceiver() {
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
override fun onReceive(context: Context?, intent: Intent?) {
if (intent?.action == Intent.ACTION_BATTERY_CHANGED) {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
val scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
val isCharging = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1)
val health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN)
val count = intent.getIntExtra(BatteryManager.EXTRA_CYCLE_COUNT, 0)
val voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0)
val temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0)
val voltageScale = getString(R.string.widget_mv)
val temperatureScale = getString(R.string.widget_c)
val batteryPct = (level / scale.toFloat() * 100).toInt()
val chargingStatusText = when (isCharging) {
BatteryManager.BATTERY_PLUGGED_AC, BatteryManager.BATTERY_PLUGGED_USB, BatteryManager.BATTERY_PLUGGED_WIRELESS -> "Charging"
else -> "Not Charging"
}
val healthStatus = when (health) {
BatteryManager.BATTERY_HEALTH_GOOD -> "Good"
BatteryManager.BATTERY_HEALTH_OVERHEAT -> "Overheat"
BatteryManager.BATTERY_HEALTH_DEAD -> "Dead"
BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE -> "Over Voltage"
BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE -> "Unspecified Failure"
BatteryManager.BATTERY_HEALTH_COLD -> "Cold"
else -> "Unknown"
}
binding.batteryLevel.text = getString(R.string.widgets_battery_level, batteryPct)
binding.batteryCount.text = getString(R.string.widgets_battery_count, count)
binding.chargingStatus.text = getString(R.string.widgets_battery_status, chargingStatusText)
binding.batteryHealth.text = getString(R.string.widgets_battery_health, healthStatus)
binding.batteryVoltage.text = getString(R.string.widgets_battery_voltage, voltage, voltageScale)
binding.batteryTemperature.text = getString(R.string.widgets_battery_temperature, temperature, temperatureScale)
}
}
}
@SuppressLint("ClickableViewAccessibility")
private fun observeSwipeTouchListener() {
@@ -183,9 +261,20 @@ class WidgetFragment : Fragment(),
}
private fun observeClickListener() {
binding.weatherButtonRefresh.setOnClickListener {
binding.weatherRefresh.setOnClickListener {
setupWeatherWidget()
}
}
override fun onResume() {
super.onResume()
context.registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
setupWeatherWidget()
}
override fun onPause() {
super.onPause()
context.unregisterReceiver(batteryReceiver)
}
}

View File

@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#ffffff" />
<corners android:radius="8dp" />
<corners android:radius="10dp" />
<padding
android:left="16dp"
android:top="16dp"
android:right="16dp"
android:bottom="16dp" />
android:left="14dp"
android:top="10dp"
android:right="14dp"
android:bottom="10dp" />
</shape>

View File

@@ -19,132 +19,227 @@
android:id="@+id/nestScrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:clipChildren="false"
android:clipToPadding="false"
android:fadingEdgeLength="48dp"
android:fillViewport="true"
android:overScrollMode="never"
android:requiresFadingEdge="vertical"
android:scrollbars="none">
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="SpeakableTextPresentCheck">
<RelativeLayout
android:id="@+id/weather_root"
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginVertical="50dp"
android:background="@drawable/widget_background">
android:orientation="vertical">
<LinearLayout
<RelativeLayout
android:id="@+id/weather_root"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_alignParentStart="true"
android:layout_marginBottom="16dp"
android:id="@+id/topHeader"
android:layout_height="wrap_content">
<TextView
android:id="@+id/weather_city"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2"
android:ellipsize="end"
android:gravity="center"
android:lines="1"
android:textSize="18sp"
tools:text="Kayamkulam, IN" />
<ImageButton
android:id="@+id/weather_button_refresh"
android:layout_width="48dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@android:color/transparent"
android:contentDescription="@string/widget_weather_refresh"
android:src="@drawable/icon_refresh" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_below="@id/topHeader"
android:gravity="center_vertical"
android:paddingEnd="8dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingStart="8dp">
<ImageView
android:id="@+id/weather_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_marginEnd="18dp"
android:layout_weight="0.3"
android:contentDescription="@string/widget_weather_description" />
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="5dp"
android:background="@drawable/widget_background"
android:orientation="vertical"
android:visibility="gone">
<LinearLayout
android:layout_width="wrap_content"
android:id="@+id/topHeaderWeather"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.7"
android:orientation="vertical">
android:layout_alignParentStart="true"
android:orientation="horizontal">
<TextView
android:id="@+id/weather_temperature"
android:id="@+id/weather_city"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:layout_weight="3"
android:ellipsize="end"
android:textAlignment="viewStart"
android:gravity="start"
android:lines="1"
android:text="@string/widget_weather_temp"
android:textSize="30sp" />
android:textSize="16sp"
tools:text="London, GB" />
<TextView
android:id="@+id/weather_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/weather_lastRun"
android:layout_width="115dp"
android:layout_height="match_parent"
android:layout_marginEnd="2dp"
android:layout_weight="2"
android:ellipsize="end"
android:gravity="center_vertical|end"
android:lines="1"
android:paddingTop="2dp"
android:text="@string/widget_weather_description"
android:textSize="16sp" />
android:textSize="11sp"
tools:text="lastRun" />
<TextView
android:id="@+id/weather_wind"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/weather_refresh"
android:layout_width="42dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:ellipsize="end"
android:paddingTop="2dp"
android:text="@string/widget_weather_wind"
android:lines="1" />
android:gravity="end"
android:lines="1"
android:textSize="18sp"
tools:text="refresh" />
<TextView
android:id="@+id/weather_humidity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:paddingTop="2dp"
android:text="@string/widget_weather_humidity"
android:lines="1" />
<TextView
android:id="@+id/weather_pressure"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="2dp"
android:ellipsize="end"
android:text="@string/widget_weather_pressure"
android:lines="1" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/topHeaderWeather"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="8dp"
android:paddingLeft="8dp"
android:paddingEnd="8dp"
android:paddingRight="8dp">
<ImageView
android:id="@+id/weather_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_marginEnd="12dp"
android:layout_weight="0.3"
android:contentDescription="@string/widget_weather_description" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.7"
android:orientation="vertical">
<TextView
android:id="@+id/weather_temperature"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:paddingTop="2dp"
android:text="@string/widget_weather_temp"
android:textSize="20sp" />
<TextView
android:id="@+id/weather_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:paddingTop="2dp"
android:text="@string/widget_weather_description"
android:textSize="14sp" />
<TextView
android:id="@+id/weather_wind"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:paddingTop="2dp"
android:text="@string/widget_weather_wind"
android:textSize="14sp" />
<TextView
android:id="@+id/weather_humidity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:paddingTop="2dp"
android:text="@string/widget_weather_humidity"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:id="@+id/battery_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="5dp"
android:background="@drawable/widget_background"
android:orientation="vertical"
android:visibility="gone">
<LinearLayout
android:id="@+id/topHeaderBattery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:orientation="vertical"
tools:ignore="UselessParent">
<TextView
android:id="@+id/battery_level"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:paddingTop="2dp"
android:text="@string/widgets_battery_level"
android:textSize="14sp" />
<TextView
android:id="@+id/battery_count"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:paddingTop="2dp"
android:text="@string/widgets_battery_count"
android:textSize="14sp" />
<TextView
android:id="@+id/charging_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:paddingTop="2dp"
android:text="@string/widgets_battery_status"
android:textSize="14sp" />
<TextView
android:id="@+id/battery_health"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:paddingTop="2dp"
android:text="@string/widgets_battery_health"
android:textSize="14sp" />
<TextView
android:id="@+id/battery_voltage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:paddingTop="2dp"
android:text="@string/widgets_battery_voltage"
android:textSize="14sp" />
<TextView
android:id="@+id/battery_temperature"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:paddingTop="2dp"
android:text="@string/widgets_battery_temperature"
android:textSize="14sp" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</com.github.droidworksstudio.launcher.view.GestureNestedScrollView>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/widget_frame"
android:padding="8dp"/>

View File

@@ -1,17 +1,18 @@
<resources>
<string name="battery_level" translatable="false">%s%%</string>
<string name="widget_mv" translatable="false">mV</string>
<string name="widget_c" translatable="false">°C</string>
<string name="widget_f" translatable="false">°F</string>
<string name="widget_weather_refresh" translatable="false">%1$s</string>
<string name="widget_weather_location" translatable="false">%1$s, %2$s</string>
<string name="widget_weather_temp" translatable="false">%1$.2f %2$s</string>
<string name="widget_weather_temp" translatable="false">%1$.0f %2$s</string>
<string name="widget_weather_description" translatable="false">%1$s</string>
<string name="weather_mps" translatable="false">m/s</string>
<string name="weather_mph" translatable="false">mil/h</string>
<string name="weather_mm" translatable="false">mm</string>
<string name="weather_c" translatable="false">°C</string>
<string name="weather_f" translatable="false">°F</string>
<string name="widget_weather_mps" translatable="false">m/s</string>
<string name="widget_weather_mph" translatable="false">mil/h</string>
<string name="widget_weather_feels_like" translatable="false">Feels Like : %s%</string>
<string name="widget_weather_wind" translatable="false">Wind : %1$.2f %2$s</string>

View File

@@ -13,7 +13,7 @@
<!-- Strings used for fragments header labels -->
<string name="favorite_fragment_name">Favorite Apps</string>
<string name="hidden_fragment_name">Hidden Apps</string>
<string name="search">Search</string>
<string name="bottom_dialog_app_rename">Rename</string>
@@ -595,4 +595,13 @@
<string name="search_bing">Bing</string>
<string name="search_brave">Brave</string>
<string name="search_swisscow">SwissCows</string>
<string name="widgets_battery_level">Battery Level : %d %%</string>
<string name="widgets_battery_count">Battery Charge Count : %1$d</string>
<string name="widgets_battery_status">Charging Status : %1$s</string>
<string name="widgets_battery_health">Battery Health : %1$s</string>
<string name="widgets_battery_voltage">Battery Voltage : %1$d %2$s</string>
<string name="widgets_battery_temperature">Battery Temperature : %1$d %2$s</string>
</resources>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="refresh_icon" translatable="false">&#xF04C;</string>
<string name="humidity_icon" translatable="false">&#xf07a;</string>
<string name="pressure_icon" translatable="false">&#xf079;</string>
<string name="speed_icon" translatable="false">&#xf050;</string>
@@ -14,6 +16,4 @@
<string name="weather_snowy" translatable="false">&#xf01b;</string>
<string name="weather_thunder" translatable="false">&#xf01e;</string>
<string name="weather_drizzle" translatable="false">&#xf01a;</string>
<string name="rain" translatable="false">&#xf019;</string>
<string name="snow" translatable="false">&#xf01b;</string>
</resources>