update widget

This commit is contained in:
Tommaso Berlose 2021-05-03 23:01:54 +02:00
parent 1bd18ac486
commit 40644f3657
28 changed files with 3101 additions and 1331 deletions

Binary file not shown.

View File

@ -65,14 +65,14 @@ dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.13.1' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
// UI // UI
implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'com.google.android.material:material:1.3.0-beta01' implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.browser:browser:1.3.0' implementation 'androidx.browser:browser:1.3.0'
implementation 'net.idik:slimadapter:2.1.2' implementation 'net.idik:slimadapter:2.1.2'
implementation 'com.google.android:flexbox:2.0.1' implementation 'com.google.android:flexbox:2.0.1'
@ -80,17 +80,17 @@ dependencies {
// Lifecycle // Lifecycle
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation "androidx.work:work-runtime-ktx:2.4.0" implementation "androidx.work:work-runtime-ktx:2.5.0"
// EventBus // EventBus
implementation 'org.greenrobot:eventbus:3.2.0' implementation 'org.greenrobot:eventbus:3.2.0'
// Navigation // Navigation
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.2' implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.2' implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
// Other // Other
implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.multidex:multidex:2.0.1'
@ -99,24 +99,24 @@ dependencies {
implementation 'com.github.warkiz.widget:indicatorseekbar:2.1.2' implementation 'com.github.warkiz.widget:indicatorseekbar:2.1.2'
//Glide //Glide
implementation 'com.github.bumptech.glide:glide:4.11.0' implementation 'com.github.bumptech.glide:glide:4.12.0'
kapt 'com.github.bumptech.glide:compiler:4.11.0' kapt 'com.github.bumptech.glide:compiler:4.11.0'
// Fitness // Fitness
implementation 'com.google.android.gms:play-services-fitness:20.0.0' implementation 'com.google.android.gms:play-services-fitness:20.0.0'
implementation 'com.google.android.gms:play-services-auth:18.1.0' implementation 'com.google.android.gms:play-services-auth:19.0.0'
//Weather //Weather
implementation 'com.github.KwabenBerko:OpenWeatherMap-Android-Library:2.0.2' implementation 'com.github.KwabenBerko:OpenWeatherMap-Android-Library:2.0.2'
implementation 'com.google.android.gms:play-services-location:17.1.0' implementation 'com.google.android.gms:play-services-location:18.0.0'
// Billing // Billing
implementation 'com.android.billingclient:billing:3.0.2' implementation 'com.android.billingclient:billing:3.0.3'
implementation 'com.android.billingclient:billing-ktx:3.0.2' implementation 'com.android.billingclient:billing-ktx:3.0.3'
// KTX // KTX
implementation "androidx.core:core-ktx:1.3.2" implementation "androidx.core:core-ktx:1.3.2"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
implementation "androidx.palette:palette-ktx:1.0.0" implementation "androidx.palette:palette-ktx:1.0.0"
implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.core:core-ktx:1.3.2'
@ -128,14 +128,14 @@ dependencies {
implementation "com.github.haroldadmin:NetworkResponseAdapter:4.0.1" implementation "com.github.haroldadmin:NetworkResponseAdapter:4.0.1"
//Coroutines //Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
// Add the Firebase SDK for Crashlytics. // Add the Firebase SDK for Crashlytics.
implementation 'com.google.firebase:firebase-crashlytics:17.3.0' implementation 'com.google.firebase:firebase-crashlytics:17.4.1'
// Preferences // Preferences
implementation 'com.chibatching.kotpref:kotpref:2.11.0' implementation 'com.chibatching.kotpref:kotpref:2.13.1'
implementation 'com.chibatching.kotpref:livedata-support:2.10.0' implementation 'com.chibatching.kotpref:livedata-support:2.13.1'
implementation 'androidx.preference:preference-ktx:1.1.1' implementation 'androidx.preference:preference-ktx:1.1.1'
// Permissions // Permissions

View File

@ -8,9 +8,7 @@ import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.navigation.Navigation
import com.google.android.gms.auth.api.signin.GoogleSignIn import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInOptions import com.google.android.gms.auth.api.signin.GoogleSignInOptions
@ -119,7 +117,7 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
binding.actionChangeNotificationTimer.setOnClickListener { binding.actionChangeNotificationTimer.setOnClickListener {
val dialog = BottomSheetMenu<Int>(context, header = context.getString(R.string.glance_notification_hide_timeout_title)).setSelectedValue(Preferences.hideNotificationAfter) val dialog = BottomSheetMenu<Int>(context, header = context.getString(R.string.glance_notification_hide_timeout_title)).setSelectedValue(Preferences.hideNotificationAfter)
Constants.GlanceNotificationTimer.values().forEachIndexed { index, timeout -> Constants.GlanceNotificationTimer.values().forEachIndexed { index, timeout ->
dialog.addItem(stringArray[index], timeout.value) dialog.addItem(stringArray[index], timeout.rawValue)
} }
dialog.addOnSelectItemListener { value -> dialog.addOnSelectItemListener { value ->
Preferences.hideNotificationAfter = value Preferences.hideNotificationAfter = value

View File

@ -2,7 +2,6 @@ package com.tommasoberlose.anotherwidget.components
import android.content.Context import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView import android.widget.ImageView
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
@ -28,13 +27,13 @@ class IconPackSelector(context: Context, private val header: String? = null) : B
// Menu // Menu
for (item in Constants.WeatherIconPack.values()) { for (item in Constants.WeatherIconPack.values()) {
val itemBinding = IconPackMenuItemBinding.inflate(LayoutInflater.from(context)) val itemBinding = IconPackMenuItemBinding.inflate(LayoutInflater.from(context))
itemBinding.label.text = context.getString(R.string.settings_weather_icon_pack_default).format(item.value + 1) itemBinding.label.text = context.getString(R.string.settings_weather_icon_pack_default).format(item.rawValue + 1)
itemBinding.root.isSelected = item.value == Preferences.weatherIconPack itemBinding.root.isSelected = item.rawValue == Preferences.weatherIconPack
itemBinding.icon1.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "01d", item.value))) itemBinding.icon1.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "01d", item.rawValue)))
itemBinding.icon2.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "01n", item.value))) itemBinding.icon2.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "01n", item.rawValue)))
itemBinding.icon3.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "10d", item.value))) itemBinding.icon3.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "10d", item.rawValue)))
itemBinding.icon4.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "09n", item.value))) itemBinding.icon4.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "09n", item.rawValue)))
listOf<ImageView>(itemBinding.icon1, itemBinding.icon2, itemBinding.icon3, itemBinding.icon4).forEach { listOf<ImageView>(itemBinding.icon1, itemBinding.icon2, itemBinding.icon3, itemBinding.icon4).forEach {
if (item == Constants.WeatherIconPack.MINIMAL) { if (item == Constants.WeatherIconPack.MINIMAL) {
@ -45,7 +44,7 @@ class IconPackSelector(context: Context, private val header: String? = null) : B
} }
itemBinding.root.setOnClickListener { itemBinding.root.setOnClickListener {
Preferences.weatherIconPack = item.value Preferences.weatherIconPack = item.rawValue
this.dismiss() this.dismiss()
} }
binding.menu.addView(itemBinding.root) binding.menu.addView(itemBinding.root)

View File

@ -1,7 +1,5 @@
package com.tommasoberlose.anotherwidget.global package com.tommasoberlose.anotherwidget.global
import java.text.SimpleDateFormat
object Constants { object Constants {
const val RESULT_CODE_CUSTOM_LOCATION = 45 const val RESULT_CODE_CUSTOM_LOCATION = 45
const val RESULT_APP_NAME = "RESULT_APP_NAME" const val RESULT_APP_NAME = "RESULT_APP_NAME"
@ -11,14 +9,14 @@ object Constants {
const val CUSTOM_FONT_DOWNLOADED = 2 const val CUSTOM_FONT_DOWNLOADED = 2
const val CUSTOM_FONT_DOWNLOAD_NEW = 3 const val CUSTOM_FONT_DOWNLOAD_NEW = 3
enum class ClockBottomMargin(val value: Int) { enum class ClockBottomMargin(val rawValue: Int) {
NONE(0), NONE(0),
SMALL(1), SMALL(1),
MEDIUM(2), MEDIUM(2),
LARGE(3) LARGE(3)
} }
enum class SecondRowTopMargin(val value: Int) { enum class SecondRowTopMargin(val rawValue: Int) {
NONE(0), NONE(0),
SMALL(1), SMALL(1),
MEDIUM(2), MEDIUM(2),
@ -41,13 +39,13 @@ object Constants {
} }
} }
enum class WidgetUpdateFrequency(val value: Int) { enum class WidgetUpdateFrequency(val rawValue: Int) {
LOW(0), LOW(0),
DEFAULT(1), DEFAULT(1),
HIGH(2) HIGH(2)
} }
enum class WeatherProvider(val value: Int) { enum class WeatherProvider(val rawValue: Int) {
OPEN_WEATHER(0), OPEN_WEATHER(0),
WEATHER_BIT(1), WEATHER_BIT(1),
WEATHER_API(2), WEATHER_API(2),
@ -57,12 +55,12 @@ object Constants {
YR(6); YR(6);
companion object { companion object {
private val map = WeatherProvider.values().associateBy(WeatherProvider::value) private val map = WeatherProvider.values().associateBy(WeatherProvider::rawValue)
fun fromInt(type: Int) = map[type] fun fromInt(type: Int) = map[type]
} }
} }
enum class GlanceNotificationTimer(val value: Int) { enum class GlanceNotificationTimer(val rawValue: Int) {
HALF_MINUTE(0), HALF_MINUTE(0),
ONE_MINUTE(1), ONE_MINUTE(1),
FIVE_MINUTES(2), FIVE_MINUTES(2),
@ -71,15 +69,21 @@ object Constants {
WHEN_DISMISSED(5); WHEN_DISMISSED(5);
companion object { companion object {
private val map = values().associateBy(GlanceNotificationTimer::value) private val map = values().associateBy(GlanceNotificationTimer::rawValue)
fun fromInt(type: Int) = map[type] fun fromInt(type: Int) = map[type]
} }
} }
enum class WeatherIconPack(val value: Int) { enum class WeatherIconPack(val rawValue: Int) {
DEFAULT(0), DEFAULT(0),
MINIMAL(1), MINIMAL(1),
COOL(2), COOL(2),
GOOGLE_NEWS(3) GOOGLE_NEWS(3)
} }
enum class WidgetAlign(val rawValue: Int) {
LEFT(0),
RIGHT(1),
CENTER(2)
}
} }

View File

@ -1,13 +1,11 @@
package com.tommasoberlose.anotherwidget.global package com.tommasoberlose.anotherwidget.global
import android.os.Build
import androidx.appcompat.app.AppCompatDelegate.* import androidx.appcompat.app.AppCompatDelegate.*
import androidx.core.os.ConfigurationCompat import androidx.core.os.ConfigurationCompat
import com.chibatching.kotpref.KotprefModel import com.chibatching.kotpref.KotprefModel
import com.tommasoberlose.anotherwidget.helpers.IntentHelper import com.tommasoberlose.anotherwidget.helpers.IntentHelper
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.utils.isMetric import com.tommasoberlose.anotherwidget.utils.isMetric
import java.util.*
object Preferences : KotprefModel() { object Preferences : KotprefModel() {
override val commitAllPropertiesByDefault: Boolean = true override val commitAllPropertiesByDefault: Boolean = true
@ -48,14 +46,14 @@ object Preferences : KotprefModel() {
var weatherProviderApiWeatherApi by stringPref(default = "") var weatherProviderApiWeatherApi by stringPref(default = "")
var weatherProviderApiWeatherBit by stringPref(default = "") var weatherProviderApiWeatherBit by stringPref(default = "")
var weatherProviderApiAccuweather by stringPref(default = "") var weatherProviderApiAccuweather by stringPref(default = "")
var weatherProvider by intPref(default = if (ConfigurationCompat.getLocales(context.resources.configuration)[0].isMetric()) Constants.WeatherProvider.YR.value else Constants.WeatherProvider.WEATHER_GOV.value) var weatherProvider by intPref(default = if (ConfigurationCompat.getLocales(context.resources.configuration)[0].isMetric()) Constants.WeatherProvider.YR.rawValue else Constants.WeatherProvider.WEATHER_GOV.rawValue)
var weatherProviderError by stringPref(default = "") var weatherProviderError by stringPref(default = "")
var weatherProviderLocationError by stringPref(default = "") var weatherProviderLocationError by stringPref(default = "")
var eventAppName by stringPref(key = "PREF_EVENT_APP_NAME", default = "") var eventAppName by stringPref(key = "PREF_EVENT_APP_NAME", default = "")
var eventAppPackage by stringPref(key = "PREF_EVENT_APP_PACKAGE", default = "") var eventAppPackage by stringPref(key = "PREF_EVENT_APP_PACKAGE", default = "")
var openEventDetails by booleanPref(default = true) var openEventDetails by booleanPref(default = true)
var widgetUpdateFrequency by intPref(default = Constants.WidgetUpdateFrequency.DEFAULT.value) var widgetUpdateFrequency by intPref(default = Constants.WidgetUpdateFrequency.DEFAULT.rawValue)
var textGlobalColor by stringPref(key = "PREF_TEXT_COLOR", default = "#FFFFFF") var textGlobalColor by stringPref(key = "PREF_TEXT_COLOR", default = "#FFFFFF")
var textGlobalAlpha by stringPref(default = "FF") var textGlobalAlpha by stringPref(default = "FF")
@ -84,14 +82,14 @@ object Preferences : KotprefModel() {
var showAMPMIndicator by booleanPref(default = true) var showAMPMIndicator by booleanPref(default = true)
var weatherIconPack by intPref(default = Constants.WeatherIconPack.DEFAULT.value) var weatherIconPack by intPref(default = Constants.WeatherIconPack.DEFAULT.rawValue)
// Global // Global
var textMainSize by floatPref(key = "PREF_TEXT_MAIN_SIZE", default = 26f) var textMainSize by floatPref(key = "PREF_TEXT_MAIN_SIZE", default = 26f)
var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 18f) var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 18f)
var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 90f) var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 90f)
var clockBottomMargin by intPref(default = Constants.ClockBottomMargin.MEDIUM.value) var clockBottomMargin by intPref(default = Constants.ClockBottomMargin.MEDIUM.rawValue)
var secondRowTopMargin by intPref(default = Constants.SecondRowTopMargin.NONE.value) var secondRowTopMargin by intPref(default = Constants.SecondRowTopMargin.NONE.rawValue)
var showClock by booleanPref(key = "PREF_SHOW_CLOCK", default = false) var showClock by booleanPref(key = "PREF_SHOW_CLOCK", default = false)
var clockAppName by stringPref(key = "PREF_CLOCK_APP_NAME", default = "") var clockAppName by stringPref(key = "PREF_CLOCK_APP_NAME", default = "")
var clockAppPackage by stringPref(key = "PREF_CLOCK_APP_PACKAGE", default = "") var clockAppPackage by stringPref(key = "PREF_CLOCK_APP_PACKAGE", default = "")
@ -111,6 +109,8 @@ object Preferences : KotprefModel() {
var showDividers by booleanPref(default = true) var showDividers by booleanPref(default = true)
var widgetAlign by intPref(default = Constants.WidgetAlign.CENTER.rawValue)
// Settings // Settings
var showWallpaper by booleanPref(default = true) var showWallpaper by booleanPref(default = true)
var showPreview by booleanPref(default = true) var showPreview by booleanPref(default = true)
@ -127,7 +127,7 @@ object Preferences : KotprefModel() {
var showDailySteps by booleanPref(default = false) var showDailySteps by booleanPref(default = false)
var showGreetings by booleanPref(default = false) var showGreetings by booleanPref(default = false)
var showNotifications by booleanPref(default = false) var showNotifications by booleanPref(default = false)
var hideNotificationAfter by intPref(default = Constants.GlanceNotificationTimer.ONE_MINUTE.value) var hideNotificationAfter by intPref(default = Constants.GlanceNotificationTimer.ONE_MINUTE.rawValue)
var lastNotificationId by intPref(default = -1) var lastNotificationId by intPref(default = -1)
var lastNotificationTitle by stringPref(default = "") var lastNotificationTitle by stringPref(default = "")

View File

@ -96,13 +96,13 @@ object SettingsStringHelper {
difference <= 0 -> { difference <= 0 -> {
return "" return ""
} }
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.HIGH.value && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> { TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.HIGH.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> {
return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 5), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString() return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 5), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
} }
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.DEFAULT.value && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> { TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.DEFAULT.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> {
return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 15), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString() return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 15), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
} }
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.LOW.value -> { TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.LOW.rawValue -> {
return context.getString(R.string.soon) return context.getString(R.string.soon)
} }
TimeUnit.MILLISECONDS.toHours(difference) < 1 -> { TimeUnit.MILLISECONDS.toHours(difference) < 1 -> {

View File

@ -2,23 +2,15 @@ package com.tommasoberlose.anotherwidget.helpers
import android.Manifest import android.Manifest
import android.content.Context import android.content.Context
import android.os.Build
import android.util.Log
import com.chibatching.kotpref.Kotpref import com.chibatching.kotpref.Kotpref
import com.google.android.gms.location.LocationServices
import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
import com.tommasoberlose.anotherwidget.services.LocationService import com.tommasoberlose.anotherwidget.services.LocationService
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.isDarkTheme import com.tommasoberlose.anotherwidget.utils.isDarkTheme
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
/** /**
@ -122,97 +114,97 @@ object WeatherHelper {
return when (icon) { return when (icon) {
"01d" -> { "01d" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.clear_day_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.clear_day_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.clear_day_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.clear_day_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.clear_day_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.clear_day_4
else -> if (context.isDarkTheme()) R.drawable.clear_day_5 else R.drawable.clear_day_5_light else -> if (context.isDarkTheme()) R.drawable.clear_day_5 else R.drawable.clear_day_5_light
} }
} }
"02d" -> { "02d" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.partly_cloudy_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.partly_cloudy_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.partly_cloudy_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.partly_cloudy_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.partly_cloudy_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.partly_cloudy_4
else -> if (context.isDarkTheme()) R.drawable.partly_cloudy_5 else R.drawable.partly_cloudy_5_light else -> if (context.isDarkTheme()) R.drawable.partly_cloudy_5 else R.drawable.partly_cloudy_5_light
} }
} }
"03d" -> { "03d" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.mostly_cloudy_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.mostly_cloudy_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.mostly_cloudy_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.mostly_cloudy_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.mostly_cloudy_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.mostly_cloudy_4
else -> if (context.isDarkTheme()) R.drawable.mostly_cloudy_5 else R.drawable.mostly_cloudy_5_light else -> if (context.isDarkTheme()) R.drawable.mostly_cloudy_5 else R.drawable.mostly_cloudy_5_light
} }
} }
"04d" -> { "04d" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.cloudy_weather_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.cloudy_weather_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.cloudy_weather_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.cloudy_weather_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.cloudy_weather_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.cloudy_weather_4
else -> if (context.isDarkTheme()) R.drawable.cloudy_weather_5 else R.drawable.cloudy_weather_5_light else -> if (context.isDarkTheme()) R.drawable.cloudy_weather_5 else R.drawable.cloudy_weather_5_light
} }
} }
"09d" -> { "09d" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.storm_weather_day_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.storm_weather_day_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.storm_weather_day_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.storm_weather_day_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.storm_weather_day_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.storm_weather_day_4
else -> if (context.isDarkTheme()) R.drawable.storm_weather_day_5 else R.drawable.storm_weather_day_5_light else -> if (context.isDarkTheme()) R.drawable.storm_weather_day_5 else R.drawable.storm_weather_day_5_light
} }
} }
"10d" -> { "10d" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.rainy_day_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.rainy_day_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rainy_day_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.rainy_day_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rainy_day_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.rainy_day_4
else -> if (context.isDarkTheme()) R.drawable.rainy_day_5 else R.drawable.rainy_day_5_light else -> if (context.isDarkTheme()) R.drawable.rainy_day_5 else R.drawable.rainy_day_5_light
} }
} }
"11d" -> { "11d" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.thunder_day_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.thunder_day_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.thunder_day_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.thunder_day_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.thunder_day_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.thunder_day_4
else -> if (context.isDarkTheme()) R.drawable.thunder_day_5 else R.drawable.thunder_day_5_light else -> if (context.isDarkTheme()) R.drawable.thunder_day_5 else R.drawable.thunder_day_5_light
} }
} }
"13d" -> { "13d" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.snow_day_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.snow_day_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.snow_day_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.snow_day_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.snow_day_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.snow_day_4
else -> if (context.isDarkTheme()) R.drawable.snow_day_5 else R.drawable.snow_day_5_light else -> if (context.isDarkTheme()) R.drawable.snow_day_5 else R.drawable.snow_day_5_light
} }
} }
"50d" -> { "50d" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_day_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.haze_day_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_day_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.haze_day_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_day_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.haze_day_4
else -> if (context.isDarkTheme()) R.drawable.haze_day_5 else R.drawable.haze_day_5_light else -> if (context.isDarkTheme()) R.drawable.haze_day_5 else R.drawable.haze_day_5_light
} }
} }
"80d" -> { "80d" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.windy_day_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.windy_day_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.windy_day_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.windy_day_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.windy_day_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.windy_day_4
else -> if (context.isDarkTheme()) R.drawable.windy_day_5 else R.drawable.windy_day_5_light else -> if (context.isDarkTheme()) R.drawable.windy_day_5 else R.drawable.windy_day_5_light
} }
} }
"81d" -> { "81d" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.rain_snow_day_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.rain_snow_day_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rain_snow_day_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.rain_snow_day_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rain_snow_day_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.rain_snow_day_4
else -> if (context.isDarkTheme()) R.drawable.rain_snow_day_5 else R.drawable.rain_snow_day_5_light else -> if (context.isDarkTheme()) R.drawable.rain_snow_day_5 else R.drawable.rain_snow_day_5_light
} }
} }
"82d" -> { "82d" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_weather_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.haze_weather_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_weather_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.haze_weather_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_weather_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.haze_weather_4
else -> if (context.isDarkTheme()) R.drawable.haze_weather_5 else R.drawable.haze_weather_5_light else -> if (context.isDarkTheme()) R.drawable.haze_weather_5 else R.drawable.haze_weather_5_light
} }
} }
@ -221,97 +213,97 @@ object WeatherHelper {
"01n" -> { "01n" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.clear_night_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.clear_night_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.clear_night_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.clear_night_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.clear_night_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.clear_night_4
else -> if (context.isDarkTheme()) R.drawable.clear_night_5 else R.drawable.clear_night_5_light else -> if (context.isDarkTheme()) R.drawable.clear_night_5 else R.drawable.clear_night_5_light
} }
} }
"02n" -> { "02n" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.partly_cloudy_night_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.partly_cloudy_night_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.partly_cloudy_night_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.partly_cloudy_night_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.partly_cloudy_night_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.partly_cloudy_night_4
else -> if (context.isDarkTheme()) R.drawable.partly_cloudy_night_5 else R.drawable.partly_cloudy_night_5_light else -> if (context.isDarkTheme()) R.drawable.partly_cloudy_night_5 else R.drawable.partly_cloudy_night_5_light
} }
} }
"03n" -> { "03n" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.mostly_cloudy_night_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.mostly_cloudy_night_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.mostly_cloudy_night_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.mostly_cloudy_night_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.mostly_cloudy_night_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.mostly_cloudy_night_4
else -> if (context.isDarkTheme()) R.drawable.mostly_cloudy_night_5 else R.drawable.mostly_cloudy_night_5_light else -> if (context.isDarkTheme()) R.drawable.mostly_cloudy_night_5 else R.drawable.mostly_cloudy_night_5_light
} }
} }
"04n" -> { "04n" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.cloudy_weather_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.cloudy_weather_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.cloudy_weather_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.cloudy_weather_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.cloudy_weather_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.cloudy_weather_4
else -> if (context.isDarkTheme()) R.drawable.cloudy_weather_5 else R.drawable.cloudy_weather_5_light else -> if (context.isDarkTheme()) R.drawable.cloudy_weather_5 else R.drawable.cloudy_weather_5_light
} }
} }
"09n" -> { "09n" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.storm_weather_night_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.storm_weather_night_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.storm_weather_night_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.storm_weather_night_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.storm_weather_night_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.storm_weather_night_4
else -> if (context.isDarkTheme()) R.drawable.storm_weather_night_5 else R.drawable.storm_weather_night_5_light else -> if (context.isDarkTheme()) R.drawable.storm_weather_night_5 else R.drawable.storm_weather_night_5_light
} }
} }
"10n" -> { "10n" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.rainy_night_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.rainy_night_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rainy_night_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.rainy_night_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rainy_night_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.rainy_night_4
else -> if (context.isDarkTheme()) R.drawable.rainy_night_5 else R.drawable.rainy_night_5_light else -> if (context.isDarkTheme()) R.drawable.rainy_night_5 else R.drawable.rainy_night_5_light
} }
} }
"11n" -> { "11n" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.thunder_night_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.thunder_night_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.thunder_night_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.thunder_night_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.thunder_night_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.thunder_night_4
else -> if (context.isDarkTheme()) R.drawable.thunder_night_5 else R.drawable.thunder_night_5_light else -> if (context.isDarkTheme()) R.drawable.thunder_night_5 else R.drawable.thunder_night_5_light
} }
} }
"13n" -> { "13n" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.snow_night_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.snow_night_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.snow_night_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.snow_night_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.snow_night_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.snow_night_4
else -> if (context.isDarkTheme()) R.drawable.snow_night_5 else R.drawable.snow_night_5_light else -> if (context.isDarkTheme()) R.drawable.snow_night_5 else R.drawable.snow_night_5_light
} }
} }
"50n" -> { "50n" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_night_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.haze_night_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_night_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.haze_night_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_night_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.haze_night_4
else -> if (context.isDarkTheme()) R.drawable.haze_night_5 else R.drawable.haze_night_5_light else -> if (context.isDarkTheme()) R.drawable.haze_night_5 else R.drawable.haze_night_5_light
} }
} }
"80n" -> { "80n" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.windy_night_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.windy_night_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.windy_night_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.windy_night_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.windy_night_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.windy_night_4
else -> if (context.isDarkTheme()) R.drawable.windy_night_5 else R.drawable.windy_night_5_light else -> if (context.isDarkTheme()) R.drawable.windy_night_5 else R.drawable.windy_night_5_light
} }
} }
"81n" -> { "81n" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.rain_snow_night_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.rain_snow_night_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rain_snow_night_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.rain_snow_night_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rain_snow_night_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.rain_snow_night_4
else -> if (context.isDarkTheme()) R.drawable.rain_snow_night_5 else R.drawable.rain_snow_night_5_light else -> if (context.isDarkTheme()) R.drawable.rain_snow_night_5 else R.drawable.rain_snow_night_5_light
} }
} }
"82n" -> { "82n" -> {
when (style) { when (style) {
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_weather_3 Constants.WeatherIconPack.COOL.rawValue -> R.drawable.haze_weather_3
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_weather_2 Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.haze_weather_2
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_weather_4 Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.haze_weather_4
else -> if (context.isDarkTheme()) R.drawable.haze_weather_5 else R.drawable.haze_weather_5_light else -> if (context.isDarkTheme()) R.drawable.haze_weather_5 else R.drawable.haze_weather_5_light
} }
} }

View File

@ -5,9 +5,6 @@ import android.app.PendingIntent
import android.content.BroadcastReceiver import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.util.Log
import androidx.core.app.AlarmManagerCompat
import androidx.core.content.ContextCompat.getSystemService
import com.tommasoberlose.anotherwidget.db.EventRepository import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Actions import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Constants
@ -110,7 +107,7 @@ class UpdatesReceiver : BroadcastReceiver() {
if (diff.hours == 0) { if (diff.hours == 0) {
var minutes = 0 var minutes = 0
when (Preferences.widgetUpdateFrequency) { when (Preferences.widgetUpdateFrequency) {
Constants.WidgetUpdateFrequency.DEFAULT.value -> { Constants.WidgetUpdateFrequency.DEFAULT.rawValue -> {
minutes = when { minutes = when {
diff.minutes > 50 -> 50 diff.minutes > 50 -> 50
diff.minutes > 30 -> 30 diff.minutes > 30 -> 30
@ -118,7 +115,7 @@ class UpdatesReceiver : BroadcastReceiver() {
else -> 0 else -> 0
} }
} }
Constants.WidgetUpdateFrequency.HIGH.value -> { Constants.WidgetUpdateFrequency.HIGH.rawValue -> {
minutes = diff.minutes - (diff.minutes % 5) minutes = diff.minutes - (diff.minutes % 5)
} }
} }

View File

@ -47,12 +47,12 @@ class WeatherProviderActivity : AppCompatActivity() {
injector injector
.text(R.id.text, WeatherHelper.getProviderName(this, provider)) .text(R.id.text, WeatherHelper.getProviderName(this, provider))
.clicked(R.id.item) { .clicked(R.id.item) {
if (Preferences.weatherProvider != provider.value) { if (Preferences.weatherProvider != provider.rawValue) {
Preferences.weatherProviderError = "-" Preferences.weatherProviderError = "-"
Preferences.weatherProviderLocationError = "" Preferences.weatherProviderLocationError = ""
} }
val oldValue = Preferences.weatherProvider val oldValue = Preferences.weatherProvider
Preferences.weatherProvider = provider.value Preferences.weatherProvider = provider.rawValue
updateListItem(oldValue) updateListItem(oldValue)
updateListItem() updateListItem()
binding.loader.isVisible = true binding.loader.isVisible = true
@ -62,12 +62,12 @@ class WeatherProviderActivity : AppCompatActivity() {
} }
} }
.clicked(R.id.radioButton) { .clicked(R.id.radioButton) {
if (Preferences.weatherProvider != provider.value) { if (Preferences.weatherProvider != provider.rawValue) {
Preferences.weatherProviderError = "-" Preferences.weatherProviderError = "-"
Preferences.weatherProviderLocationError = "" Preferences.weatherProviderLocationError = ""
} }
val oldValue = Preferences.weatherProvider val oldValue = Preferences.weatherProvider
Preferences.weatherProvider = provider.value Preferences.weatherProvider = provider.rawValue
updateListItem(oldValue) updateListItem(oldValue)
updateListItem() updateListItem()
binding.loader.isVisible = true binding.loader.isVisible = true
@ -76,7 +76,7 @@ class WeatherProviderActivity : AppCompatActivity() {
WeatherHelper.updateWeather(this@WeatherProviderActivity) WeatherHelper.updateWeather(this@WeatherProviderActivity)
} }
} }
.checked(R.id.radioButton, provider.value == Preferences.weatherProvider) .checked(R.id.radioButton, provider.rawValue == Preferences.weatherProvider)
.with<TextView>(R.id.text2) { .with<TextView>(R.id.text2) {
if (WeatherHelper.isKeyRequired(provider)) { if (WeatherHelper.isKeyRequired(provider)) {
it.text = getString(R.string.api_key_required_message) it.text = getString(R.string.api_key_required_message)
@ -98,14 +98,14 @@ class WeatherProviderActivity : AppCompatActivity() {
} }
}.show() }.show()
} }
.visibility(R.id.action_configure, if (/*WeatherHelper.isKeyRequired(provider) && */provider.value == Preferences.weatherProvider) View.VISIBLE else View.GONE) .visibility(R.id.action_configure, if (/*WeatherHelper.isKeyRequired(provider) && */provider.rawValue == Preferences.weatherProvider) View.VISIBLE else View.GONE)
.with<TextView>(R.id.provider_error) { .with<TextView>(R.id.provider_error) {
if (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-") { if (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-") {
it.text = Preferences.weatherProviderError it.text = Preferences.weatherProviderError
it.isVisible = provider.value == Preferences.weatherProvider it.isVisible = provider.rawValue == Preferences.weatherProvider
} else if (Preferences.weatherProviderLocationError != "") { } else if (Preferences.weatherProviderLocationError != "") {
it.text = Preferences.weatherProviderLocationError it.text = Preferences.weatherProviderLocationError
it.isVisible = provider.value == Preferences.weatherProvider it.isVisible = provider.rawValue == Preferences.weatherProvider
} else { } else {
it.isVisible = false it.isVisible = false
} }
@ -137,7 +137,7 @@ class WeatherProviderActivity : AppCompatActivity() {
private fun updateListItem(provider: Int = Preferences.weatherProvider) { private fun updateListItem(provider: Int = Preferences.weatherProvider) {
(adapter.data).forEachIndexed { index, item -> (adapter.data).forEachIndexed { index, item ->
if (item is Constants.WeatherProvider && item.value == provider) { if (item is Constants.WeatherProvider && item.rawValue == provider) {
adapter.notifyItemChanged(index) adapter.notifyItemChanged(index)
} }
} }

View File

@ -1,9 +1,7 @@
package com.tommasoberlose.anotherwidget.ui.fragments package com.tommasoberlose.anotherwidget.ui.fragments
import android.Manifest
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
@ -14,23 +12,14 @@ import android.util.TypedValue
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.RelativeLayout import android.widget.RelativeLayout
import androidx.core.animation.addListener
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import com.google.android.material.badge.BadgeDrawable
import com.google.android.material.card.MaterialCardView
import com.google.android.material.tabs.TabLayoutMediator
import com.google.android.material.transition.MaterialSharedAxis import com.google.android.material.transition.MaterialSharedAxis
import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
@ -39,11 +28,10 @@ import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.* import com.tommasoberlose.anotherwidget.helpers.*
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.ui.widgets.StandardWidget
import com.tommasoberlose.anotherwidget.utils.* import com.tommasoberlose.anotherwidget.utils.*
import kotlinx.coroutines.* import kotlinx.coroutines.*
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
@ -54,7 +42,7 @@ class MainFragment : Fragment() {
companion object { companion object {
fun newInstance() = MainFragment() fun newInstance() = MainFragment()
private const val PREVIEW_BASE_HEIGHT = 120 private var PREVIEW_BASE_HEIGHT: Int = if (Preferences.widgetAlign == Constants.WidgetAlign.CENTER.rawValue) 120 else 200
} }
private lateinit var viewModel: MainViewModel private lateinit var viewModel: MainViewModel
@ -164,6 +152,10 @@ class MainFragment : Fragment() {
binding.toolbar.cardElevation = if (it > 0) 24f else 0f binding.toolbar.cardElevation = if (it > 0) 24f else 0f
} }
viewModel.widgetAlign.observe(viewLifecycleOwner) {
updatePreviewVisibility()
}
viewModel.showPreview.observe(viewLifecycleOwner) { viewModel.showPreview.observe(viewLifecycleOwner) {
updatePreviewVisibility() updatePreviewVisibility()
} }
@ -209,7 +201,7 @@ class MainFragment : Fragment() {
WidgetHelper.runWithCustomTypeface(requireContext()) { typeface -> WidgetHelper.runWithCustomTypeface(requireContext()) { typeface ->
uiJob = lifecycleScope.launch(Dispatchers.IO) { uiJob = lifecycleScope.launch(Dispatchers.IO) {
val generatedView = MainWidget.generateWidgetView(requireContext(), typeface).root val generatedView = MainWidget.getWidgetView(requireContext(), typeface).root
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
generatedView.measure(0, 0) generatedView.measure(0, 0)
@ -252,13 +244,13 @@ class MainFragment : Fragment() {
// Clock bottom margin // Clock bottom margin
binding.widgetDetail.clockBottomMarginNone.isVisible = binding.widgetDetail.clockBottomMarginNone.isVisible =
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.rawValue
binding.widgetDetail.clockBottomMarginSmall.isVisible = binding.widgetDetail.clockBottomMarginSmall.isVisible =
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.rawValue
binding.widgetDetail.clockBottomMarginMedium.isVisible = binding.widgetDetail.clockBottomMarginMedium.isVisible =
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.rawValue
binding.widgetDetail.clockBottomMarginLarge.isVisible = binding.widgetDetail.clockBottomMarginLarge.isVisible =
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.rawValue
} }

View File

@ -1,19 +1,14 @@
package com.tommasoberlose.anotherwidget.ui.fragments.tabs package com.tommasoberlose.anotherwidget.ui.fragments.tabs
import android.Manifest import android.Manifest
import android.app.Activity
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.provider.CalendarContract import android.provider.CalendarContract
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.chibatching.kotpref.bulk
import com.google.android.material.transition.MaterialSharedAxis import com.google.android.material.transition.MaterialSharedAxis
import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
@ -21,20 +16,15 @@ import com.tommasoberlose.anotherwidget.models.CalendarSelector
import com.tommasoberlose.anotherwidget.databinding.FragmentTabCalendarBinding import com.tommasoberlose.anotherwidget.databinding.FragmentTabCalendarBinding
import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.global.RequestCode
import com.tommasoberlose.anotherwidget.ui.activities.tabs.ChooseApplicationActivity
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.isDefaultSet
import com.tommasoberlose.anotherwidget.utils.toast import com.tommasoberlose.anotherwidget.utils.toast
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlin.Comparator
class CalendarFragment : Fragment() { class CalendarFragment : Fragment() {
@ -110,9 +100,9 @@ class CalendarFragment : Fragment() {
viewModel.widgetUpdateFrequency.observe(viewLifecycleOwner) { viewModel.widgetUpdateFrequency.observe(viewLifecycleOwner) {
maintainScrollPosition { maintainScrollPosition {
binding.widgetUpdateFrequencyLabel.text = when (it) { binding.widgetUpdateFrequencyLabel.text = when (it) {
Constants.WidgetUpdateFrequency.HIGH.value -> getString(R.string.settings_widget_update_frequency_high) Constants.WidgetUpdateFrequency.HIGH.rawValue -> getString(R.string.settings_widget_update_frequency_high)
Constants.WidgetUpdateFrequency.DEFAULT.value -> getString(R.string.settings_widget_update_frequency_default) Constants.WidgetUpdateFrequency.DEFAULT.rawValue -> getString(R.string.settings_widget_update_frequency_default)
Constants.WidgetUpdateFrequency.LOW.value -> getString(R.string.settings_widget_update_frequency_low) Constants.WidgetUpdateFrequency.LOW.rawValue -> getString(R.string.settings_widget_update_frequency_low)
else -> "" else -> ""
} }
} }
@ -244,9 +234,9 @@ class CalendarFragment : Fragment() {
binding.actionWidgetUpdateFrequency.setOnClickListener { binding.actionWidgetUpdateFrequency.setOnClickListener {
if (Preferences.showEvents && Preferences.showDiffTime) { if (Preferences.showEvents && Preferences.showDiffTime) {
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_widget_update_frequency_title), message = getString(R.string.settings_widget_update_frequency_subtitle)).setSelectedValue(Preferences.widgetUpdateFrequency) BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_widget_update_frequency_title), message = getString(R.string.settings_widget_update_frequency_subtitle)).setSelectedValue(Preferences.widgetUpdateFrequency)
.addItem(getString(R.string.settings_widget_update_frequency_high), Constants.WidgetUpdateFrequency.HIGH.value) .addItem(getString(R.string.settings_widget_update_frequency_high), Constants.WidgetUpdateFrequency.HIGH.rawValue)
.addItem(getString(R.string.settings_widget_update_frequency_default), Constants.WidgetUpdateFrequency.DEFAULT.value) .addItem(getString(R.string.settings_widget_update_frequency_default), Constants.WidgetUpdateFrequency.DEFAULT.rawValue)
.addItem(getString(R.string.settings_widget_update_frequency_low), Constants.WidgetUpdateFrequency.LOW.value) .addItem(getString(R.string.settings_widget_update_frequency_low), Constants.WidgetUpdateFrequency.LOW.rawValue)
.addOnSelectItemListener { value -> .addOnSelectItemListener { value ->
Preferences.widgetUpdateFrequency = value Preferences.widgetUpdateFrequency = value
}.show() }.show()

View File

@ -1,17 +1,14 @@
package com.tommasoberlose.anotherwidget.ui.fragments.tabs package com.tommasoberlose.anotherwidget.ui.fragments.tabs
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.chibatching.kotpref.blockingBulk
import com.google.android.material.transition.MaterialSharedAxis import com.google.android.material.transition.MaterialSharedAxis
import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
@ -22,8 +19,6 @@ import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.ColorHelper import com.tommasoberlose.anotherwidget.helpers.ColorHelper
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toHexValue import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toHexValue
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
import com.tommasoberlose.anotherwidget.helpers.DateHelper
import com.tommasoberlose.anotherwidget.ui.activities.tabs.CustomDateActivity
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.utils.isDarkTheme import com.tommasoberlose.anotherwidget.utils.isDarkTheme
@ -31,7 +26,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.util.*
class LayoutFragment : Fragment() { class LayoutFragment : Fragment() {
@ -94,20 +88,31 @@ class LayoutFragment : Fragment() {
viewModel.secondRowTopMargin.observe(viewLifecycleOwner) { viewModel.secondRowTopMargin.observe(viewLifecycleOwner) {
maintainScrollPosition { maintainScrollPosition {
binding.secondRowTopMarginLabel.text = when (it) { binding.secondRowTopMarginLabel.text = when (it) {
Constants.SecondRowTopMargin.NONE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_none) Constants.SecondRowTopMargin.NONE.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_none)
Constants.SecondRowTopMargin.SMALL.value -> getString(R.string.settings_clock_bottom_margin_subtitle_small) Constants.SecondRowTopMargin.SMALL.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_small)
Constants.SecondRowTopMargin.LARGE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_large) Constants.SecondRowTopMargin.LARGE.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_large)
else -> getString(R.string.settings_clock_bottom_margin_subtitle_medium) else -> getString(R.string.settings_clock_bottom_margin_subtitle_medium)
} }
} }
} }
viewModel.widgetAlign.observe(viewLifecycleOwner) {
maintainScrollPosition {
binding.widgetAlignLabel.text = when (it) {
Constants.WidgetAlign.LEFT.rawValue -> getString(R.string.settings_widget_align_left_subtitle)
Constants.WidgetAlign.RIGHT.rawValue -> getString(R.string.settings_widget_align_right_subtitle)
Constants.WidgetAlign.CENTER.rawValue -> getString(R.string.settings_widget_align_center_subtitle)
else -> getString(R.string.settings_widget_align_center_subtitle)
}
}
}
viewModel.clockBottomMargin.observe(viewLifecycleOwner) { viewModel.clockBottomMargin.observe(viewLifecycleOwner) {
maintainScrollPosition { maintainScrollPosition {
binding.clockBottomMarginLabel.text = when (it) { binding.clockBottomMarginLabel.text = when (it) {
Constants.ClockBottomMargin.NONE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_none) Constants.ClockBottomMargin.NONE.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_none)
Constants.ClockBottomMargin.SMALL.value -> getString(R.string.settings_clock_bottom_margin_subtitle_small) Constants.ClockBottomMargin.SMALL.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_small)
Constants.ClockBottomMargin.LARGE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_large) Constants.ClockBottomMargin.LARGE.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_large)
else -> getString(R.string.settings_clock_bottom_margin_subtitle_medium) else -> getString(R.string.settings_clock_bottom_margin_subtitle_medium)
} }
} }
@ -115,7 +120,7 @@ class LayoutFragment : Fragment() {
viewModel.backgroundCardColor.observe(viewLifecycleOwner) { viewModel.backgroundCardColor.observe(viewLifecycleOwner) {
maintainScrollPosition { maintainScrollPosition {
if (Preferences.backgroundCardAlpha == "00") { if (ColorHelper.getBackgroundAlpha(requireActivity().isDarkTheme()) == 0) {
binding.backgroundColorLabel.text = getString(R.string.transparent) binding.backgroundColorLabel.text = getString(R.string.transparent)
} else { } else {
binding.backgroundColorLabel.text = binding.backgroundColorLabel.text =
@ -141,19 +146,19 @@ class LayoutFragment : Fragment() {
).setSelectedValue(Preferences.secondRowTopMargin) ).setSelectedValue(Preferences.secondRowTopMargin)
.addItem( .addItem(
getString(R.string.settings_clock_bottom_margin_subtitle_none), getString(R.string.settings_clock_bottom_margin_subtitle_none),
Constants.SecondRowTopMargin.NONE.value Constants.SecondRowTopMargin.NONE.rawValue
) )
.addItem( .addItem(
getString(R.string.settings_clock_bottom_margin_subtitle_small), getString(R.string.settings_clock_bottom_margin_subtitle_small),
Constants.SecondRowTopMargin.SMALL.value Constants.SecondRowTopMargin.SMALL.rawValue
) )
.addItem( .addItem(
getString(R.string.settings_clock_bottom_margin_subtitle_medium), getString(R.string.settings_clock_bottom_margin_subtitle_medium),
Constants.SecondRowTopMargin.MEDIUM.value Constants.SecondRowTopMargin.MEDIUM.rawValue
) )
.addItem( .addItem(
getString(R.string.settings_clock_bottom_margin_subtitle_large), getString(R.string.settings_clock_bottom_margin_subtitle_large),
Constants.SecondRowTopMargin.LARGE.value Constants.SecondRowTopMargin.LARGE.rawValue
) )
.addOnSelectItemListener { value -> .addOnSelectItemListener { value ->
Preferences.secondRowTopMargin = value Preferences.secondRowTopMargin = value
@ -167,25 +172,47 @@ class LayoutFragment : Fragment() {
).setSelectedValue(Preferences.clockBottomMargin) ).setSelectedValue(Preferences.clockBottomMargin)
.addItem( .addItem(
getString(R.string.settings_clock_bottom_margin_subtitle_none), getString(R.string.settings_clock_bottom_margin_subtitle_none),
Constants.ClockBottomMargin.NONE.value Constants.ClockBottomMargin.NONE.rawValue
) )
.addItem( .addItem(
getString(R.string.settings_clock_bottom_margin_subtitle_small), getString(R.string.settings_clock_bottom_margin_subtitle_small),
Constants.ClockBottomMargin.SMALL.value Constants.ClockBottomMargin.SMALL.rawValue
) )
.addItem( .addItem(
getString(R.string.settings_clock_bottom_margin_subtitle_medium), getString(R.string.settings_clock_bottom_margin_subtitle_medium),
Constants.ClockBottomMargin.MEDIUM.value Constants.ClockBottomMargin.MEDIUM.rawValue
) )
.addItem( .addItem(
getString(R.string.settings_clock_bottom_margin_subtitle_large), getString(R.string.settings_clock_bottom_margin_subtitle_large),
Constants.ClockBottomMargin.LARGE.value Constants.ClockBottomMargin.LARGE.rawValue
) )
.addOnSelectItemListener { value -> .addOnSelectItemListener { value ->
Preferences.clockBottomMargin = value Preferences.clockBottomMargin = value
}.show() }.show()
} }
binding.actionWidgetAlign.setOnClickListener {
BottomSheetMenu<Int>(
requireContext(),
header = getString(R.string.settings_widget_align_title)
).setSelectedValue(Preferences.widgetAlign)
.addItem(
getString(R.string.settings_widget_align_center_subtitle),
Constants.WidgetAlign.CENTER.rawValue
)
.addItem(
getString(R.string.settings_widget_align_left_subtitle),
Constants.WidgetAlign.LEFT.rawValue
)
.addItem(
getString(R.string.settings_widget_align_right_subtitle),
Constants.WidgetAlign.RIGHT.rawValue
)
.addOnSelectItemListener { value ->
Preferences.widgetAlign = value
}.show()
}
binding.actionBackgroundColor.setOnClickListener { binding.actionBackgroundColor.setOnClickListener {
BottomSheetColorPicker(requireContext(), BottomSheetColorPicker(requireContext(),
colors = colors, colors = colors,

View File

@ -49,6 +49,7 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
val secondRowInformation = Preferences.asLiveData(Preferences::secondRowInformation) val secondRowInformation = Preferences.asLiveData(Preferences::secondRowInformation)
val showDividers = Preferences.asLiveData(Preferences::showDividers) val showDividers = Preferences.asLiveData(Preferences::showDividers)
val secondRowTopMargin = Preferences.asLiveData(Preferences::secondRowTopMargin) val secondRowTopMargin = Preferences.asLiveData(Preferences::secondRowTopMargin)
val widgetAlign = Preferences.asLiveData(Preferences::widgetAlign)
// Calendar Settings // Calendar Settings
val showEvents = Preferences.asLiveData(Preferences::showEvents) val showEvents = Preferences.asLiveData(Preferences::showEvents)

View File

@ -0,0 +1,75 @@
package com.tommasoberlose.anotherwidget.ui.widgets
import android.app.PendingIntent
import android.content.Context
import android.util.TypedValue
import android.view.View
import android.widget.RemoteViews
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
import com.tommasoberlose.anotherwidget.receivers.CrashlyticsReceiver
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
import com.tommasoberlose.anotherwidget.utils.toPixel
class ClockWidget(val context: Context) {
fun updateClockView(views: RemoteViews, widgetID: Int): RemoteViews {
try {
if (!Preferences.showClock) {
views.setViewVisibility(R.id.time, View.GONE)
views.setViewVisibility(R.id.time_am_pm, View.GONE)
views.setViewVisibility(R.id.clock_bottom_margin_none, View.GONE)
views.setViewVisibility(R.id.clock_bottom_margin_small, View.GONE)
views.setViewVisibility(R.id.clock_bottom_margin_medium, View.GONE)
views.setViewVisibility(R.id.clock_bottom_margin_large, View.GONE)
} else {
views.setTextColor(R.id.time, ColorHelper.getClockFontColor(context.isDarkTheme()))
views.setTextColor(R.id.time_am_pm, ColorHelper.getClockFontColor(context.isDarkTheme()))
views.setTextViewTextSize(
R.id.time,
TypedValue.COMPLEX_UNIT_SP,
Preferences.clockTextSize.toPixel(context)
)
views.setTextViewTextSize(
R.id.time_am_pm,
TypedValue.COMPLEX_UNIT_SP,
Preferences.clockTextSize.toPixel(context) / 5 * 2
)
val clockPIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getClockIntent(context),
0
)
views.setOnClickPendingIntent(R.id.time, clockPIntent)
views.setOnClickPendingIntent(R.id.time_am_pm, clockPIntent)
views.setViewVisibility(R.id.time, View.VISIBLE)
views.setViewVisibility(R.id.time_am_pm, if (Preferences.showAMPMIndicator) View.VISIBLE else View.GONE)
views.setViewVisibility(
R.id.clock_bottom_margin_none,
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.rawValue) View.VISIBLE else View.GONE
)
views.setViewVisibility(
R.id.clock_bottom_margin_small,
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.rawValue) View.VISIBLE else View.GONE
)
views.setViewVisibility(
R.id.clock_bottom_margin_medium,
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.rawValue) View.VISIBLE else View.GONE
)
views.setViewVisibility(
R.id.clock_bottom_margin_large,
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.rawValue) View.VISIBLE else View.GONE
)
}
} catch (ex: Exception) {
ex.printStackTrace()
CrashlyticsReceiver.sendCrash(context, ex)
}
return views
}
}

View File

@ -0,0 +1,886 @@
package com.tommasoberlose.anotherwidget.ui.widgets
import android.Manifest
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.Typeface
import android.text.format.DateUtils
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.RemoteViews
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.databinding.LeftAlignedWidgetBinding
import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.*
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
import com.tommasoberlose.anotherwidget.helpers.ImageHelper.applyShadow
import com.tommasoberlose.anotherwidget.receivers.CrashlyticsReceiver
import com.tommasoberlose.anotherwidget.receivers.NewCalendarEventReceiver
import com.tommasoberlose.anotherwidget.receivers.WidgetClickListenerReceiver
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.convertDpToPixel
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
import java.text.DateFormat
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.math.roundToInt
class LeftAlignedWidget(val context: Context) {
fun generateWidget(appWidgetId: Int, w: Int, typeface: Typeface? = null): RemoteViews {
var views = RemoteViews(context.packageName, R.layout.left_aligned_widget_sans)
try {
// Background
views.setInt(
R.id.widget_shape_background,
"setColorFilter",
ColorHelper.getBackgroundColorRgb(context.isDarkTheme())
)
views.setInt(
R.id.widget_shape_background,
"setImageAlpha",
ColorHelper.getBackgroundAlpha(context.isDarkTheme())
)
val refreshIntent = PendingIntent.getActivity(
context,
appWidgetId,
IntentHelper.getWidgetUpdateIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.widget_shape_background, refreshIntent)
} catch (ex: Exception) {
ex.printStackTrace()
CrashlyticsReceiver.sendCrash(context, ex)
}
// Clock
views = ClockWidget(context).updateClockView(views, appWidgetId)
// Setup listener
try {
val generatedBinding = generateWidgetView(typeface)
views.setImageViewBitmap(
R.id.bitmap_container,
BitmapHelper.getBitmapFromView(generatedBinding.root, width = w)
)
views = updateGridView(generatedBinding, views, appWidgetId)
} catch (ex: Exception) {
ex.printStackTrace()
CrashlyticsReceiver.sendCrash(context, ex)
}
return views
}
private fun updateGridView(bindingView: LeftAlignedWidgetBinding, views: RemoteViews, widgetID: Int): RemoteViews {
val eventRepository = EventRepository(context)
try {
// Weather
if (Preferences.showWeather && Preferences.weatherIcon != "") {
views.setViewVisibility(R.id.weather_rect, View.VISIBLE)
views.setViewVisibility(R.id.weather_sub_line, View.GONE)
val i = Intent(context, WidgetClickListenerReceiver::class.java)
i.action = Actions.ACTION_OPEN_WEATHER_INTENT
val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, 0)
views.setOnClickPendingIntent(R.id.weather_rect, weatherPIntent)
views.setOnClickPendingIntent(R.id.weather_sub_line_rect, weatherPIntent)
views.setImageViewBitmap(
R.id.weather_rect,
BitmapHelper.getBitmapFromView(bindingView.weatherDateLine, draw = false)
)
views.setImageViewBitmap(
R.id.weather_sub_line_rect,
BitmapHelper.getBitmapFromView(bindingView.weatherSubLine, draw = false)
)
} else {
views.setViewVisibility(R.id.weather_rect, View.GONE)
views.setViewVisibility(R.id.weather_sub_line, View.GONE)
}
// Calendar
views.setImageViewBitmap(
R.id.date_rect,
BitmapHelper.getBitmapFromView(bindingView.date, draw = false)
)
val calPIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getCalendarIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.date_rect, calPIntent)
views.setViewVisibility(R.id.date_layout, View.VISIBLE)
val nextEvent = eventRepository.getNextEvent()
val nextAlarm = AlarmHelper.getNextAlarm(context)
// Spacing
views.setViewVisibility(
R.id.sub_line_top_margin_small_sans,
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.rawValue) View.VISIBLE else View.GONE
)
views.setViewVisibility(
R.id.sub_line_top_margin_medium_sans,
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.rawValue) View.VISIBLE else View.GONE
)
views.setViewVisibility(
R.id.sub_line_top_margin_large_sans,
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.rawValue) View.VISIBLE else View.GONE
)
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null && !Preferences.showEventsAsGlanceProvider) {
if (Preferences.showNextEvent && eventRepository.getEventsCount() > 1) {
// Action next event
views.setImageViewBitmap(
R.id.action_next_rect,
BitmapHelper.getBitmapFromView(bindingView.actionNext, draw = false)
)
views.setViewVisibility(R.id.action_next_rect, View.VISIBLE)
views.setOnClickPendingIntent(
R.id.action_next_rect,
PendingIntent.getBroadcast(
context,
widgetID,
Intent(
context,
NewCalendarEventReceiver::class.java
).apply { action = Actions.ACTION_GO_TO_NEXT_EVENT },
PendingIntent.FLAG_UPDATE_CURRENT
)
)
views.setViewVisibility(R.id.action_next_rect, View.VISIBLE)
} else {
views.setViewVisibility(R.id.action_next_rect, View.GONE)
}
// Event intent
val eventIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getEventIntent(context, nextEvent),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.next_event_rect, eventIntent)
views.setViewVisibility(R.id.next_event_rect, View.VISIBLE)
// Event time difference
if (Preferences.showDiffTime && Calendar.getInstance().timeInMillis < (nextEvent.startDate - 1000 * 60 * 60)) {
views.setImageViewBitmap(
R.id.next_event_difference_time_rect,
BitmapHelper.getBitmapFromView(
bindingView.nextEventDifferenceTime,
draw = false
)
)
views.setViewVisibility(R.id.next_event_difference_time_rect, View.VISIBLE)
views.setOnClickPendingIntent(R.id.next_event_difference_time_rect, eventIntent)
} else {
views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE)
}
// Event information
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
val mapIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getGoogleMapsIntentFromAddress(context, nextEvent.address),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.sub_line_rect, mapIntent)
} else {
val pIntentDetail = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getEventIntent(
context,
nextEvent,
forceEventDetails = true
),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.sub_line_rect, pIntentDetail)
}
views.setImageViewBitmap(
R.id.next_event_rect,
BitmapHelper.getBitmapFromView(bindingView.nextEvent, draw = false)
)
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
// Second row
views.setImageViewBitmap(
R.id.sub_line_rect,
BitmapHelper.getBitmapFromView(bindingView.subLine, draw = false)
)
views.setViewVisibility(R.id.sub_line_rect, View.VISIBLE)
} else if (GlanceProviderHelper.showGlanceProviders(context) && bindingView.calendarLayout.isVisible) {
var showSomething = false
loop@ for (provider: Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(context)) {
when (provider) {
Constants.GlanceProviderId.PLAYING_SONG -> {
if (MediaPlayerHelper.isSomeonePlaying(context)) {
val musicIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getMusicIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.sub_line_rect, musicIntent)
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
if (Preferences.showNextAlarm && nextAlarm != "") {
val alarmIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getClockIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.sub_line_rect, alarmIntent)
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
if (Preferences.showBatteryCharging) {
BatteryHelper.updateBatteryInfo(context)
if (Preferences.isCharging || Preferences.isBatteryLevelLow) {
val batteryIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getBatteryIntent(),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.sub_line_rect, batteryIntent)
showSomething = true
break@loop
}
}
}
Constants.GlanceProviderId.CUSTOM_INFO -> {
if (Preferences.customNotes.isNotEmpty()) {
break@loop
}
}
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
val fitIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getFitIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.sub_line_rect, fitIntent)
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
try {
if (Preferences.lastNotificationIcon != 0) {
val remotePackageContext = context.createPackageContext(
Preferences.lastNotificationPackage, 0)
ContextCompat.getDrawable(
remotePackageContext,
Preferences.lastNotificationIcon)
}
val notificationIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getNotificationIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(
R.id.sub_line_rect,
notificationIntent
)
showSomething = true
break@loop
} catch (ex: Exception) {}
}
}
Constants.GlanceProviderId.GREETINGS -> {
if (Preferences.showGreetings && GreetingsHelper.showGreetings() && GreetingsHelper.getRandomString(context).isNotBlank()) {
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.EVENTS -> {
if (Preferences.showEventsAsGlanceProvider&& Preferences.showEvents && context.checkGrantedPermission(
Manifest.permission.READ_CALENDAR) && nextEvent != null) {
val pIntentDetail = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getEventIntent(
context,
nextEvent,
forceEventDetails = true
),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(
R.id.sub_line_rect,
pIntentDetail
)
showSomething = true
break@loop
}
}
}
}
if (showSomething) {
views.setImageViewBitmap(
R.id.sub_line_rect,
BitmapHelper.getBitmapFromView(bindingView.subLine, draw = false)
)
views.setViewVisibility(R.id.first_line_rect, View.VISIBLE)
views.setViewVisibility(R.id.calendar_layout_rect, View.GONE)
views.setViewVisibility(R.id.sub_line_rect, View.VISIBLE)
views.setViewVisibility(R.id.weather_sub_line_rect, View.GONE)
} else {
// Spacing
views.setViewVisibility(R.id.sub_line_top_margin_small_sans, View.GONE)
views.setViewVisibility(R.id.sub_line_top_margin_medium_sans, View.GONE)
views.setViewVisibility(R.id.sub_line_top_margin_large_sans, View.GONE)
}
}
} catch (ex: Exception) {
ex.printStackTrace()
CrashlyticsReceiver.sendCrash(context, ex)
} finally {
eventRepository.close()
}
return views
}
// Generates the widget bitmap from the view
fun generateWidgetView(typeface: Typeface? = null): LeftAlignedWidgetBinding {
val eventRepository = EventRepository(context)
val bindingView = LeftAlignedWidgetBinding.inflate(LayoutInflater.from(context))
bindingView.loader.isVisible = false
// Weather
if (Preferences.showWeather && Preferences.weatherIcon != "") {
bindingView.weatherDateLine.isVisible = true
val currentTemp = String.format(
Locale.getDefault(),
"%d °%s",
Preferences.weatherTemp.roundToInt(),
Preferences.weatherRealTempUnit
)
val icon: String = Preferences.weatherIcon
if (icon == "") {
bindingView.weatherSubLineWeatherIcon.isVisible = false
bindingView.weatherDateLineWeatherIcon.isVisible = false
} else {
bindingView.weatherSubLineWeatherIcon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon))
bindingView.weatherDateLineWeatherIcon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon))
bindingView.weatherSubLineWeatherIcon.isVisible = true
bindingView.weatherDateLineWeatherIcon.isVisible = true
}
bindingView.weatherDateLineTemperature.text = currentTemp
bindingView.weatherSubLineTemperature.text = currentTemp
if (GlanceProviderHelper.showGlanceProviders(context)) {
bindingView.weatherSubLine.isVisible = false
}
} else {
bindingView.weatherDateLine.isVisible = false
bindingView.weatherSubLine.isVisible = false
}
val now = Calendar.getInstance().apply {
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}
bindingView.dateLayout.isVisible = true
bindingView.calendarLayout.isVisible = false
bindingView.nextEventDifferenceTime.isVisible = false
bindingView.actionNext.isVisible = false
bindingView.date.text = DateHelper.getDateText(context, now)
val nextEvent = eventRepository.getNextEvent()
val nextAlarm = AlarmHelper.getNextAlarm(context)
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null && !Preferences.showEventsAsGlanceProvider) {
// Multiple counter
bindingView.actionNext.isVisible =
Preferences.showNextEvent && eventRepository.getEventsCount() > 1
bindingView.nextEvent.text = nextEvent.title
if (Preferences.showDiffTime && now.timeInMillis < nextEvent.startDate) {
bindingView.nextEventDifferenceTime.text = if (!nextEvent.allDay) {
SettingsStringHelper.getDifferenceText(
context,
now.timeInMillis,
nextEvent.startDate
)
.toLowerCase(Locale.getDefault())
} else {
SettingsStringHelper.getAllDayEventDifferenceText(
context,
now.timeInMillis,
nextEvent.startDate
).toLowerCase(Locale.getDefault())
}
bindingView.nextEventDifferenceTime.isVisible = true
} else {
bindingView.nextEventDifferenceTime.isVisible = false
}
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
bindingView.subLineIcon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_place_24
)
)
bindingView.subLineText.text = nextEvent.address
} else {
bindingView.subLineIcon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_today_24
)
)
if (!nextEvent.allDay) {
val startHour =
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault())
.format(nextEvent.startDate)
val endHour =
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault())
.format(nextEvent.endDate)
var dayDiff =
TimeUnit.MILLISECONDS.toDays(nextEvent.endDate - nextEvent.startDate)
val startCal = Calendar.getInstance()
startCal.timeInMillis = nextEvent.startDate
val endCal = Calendar.getInstance()
endCal.timeInMillis = nextEvent.endDate
if (startCal.get(Calendar.HOUR_OF_DAY) > endCal.get(Calendar.HOUR_OF_DAY)) {
dayDiff++
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(
Calendar.MINUTE
) > endCal.get(Calendar.MINUTE)
) {
dayDiff++
}
var multipleDay = ""
if (dayDiff > 0) {
multipleDay = String.format(
" (+%s%s)",
dayDiff,
context.getString(R.string.day_char)
)
}
if (nextEvent.startDate != nextEvent.endDate) {
bindingView.subLineText.text =
String.format("%s - %s%s", startHour, endHour, multipleDay)
} else {
bindingView.subLineText.text =
String.format("%s", startHour)
}
} else {
val flags: Int =
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
val start = Calendar.getInstance().apply { timeInMillis = nextEvent.startDate }
bindingView.subLineText.text = if (now.get(Calendar.DAY_OF_YEAR) == start.get(
Calendar.DAY_OF_YEAR)) {
DateUtils.formatDateTime(context, nextEvent.startDate, flags)
} else if (now.get(Calendar.DAY_OF_YEAR) > start.get(Calendar.DAY_OF_YEAR) || now.get(
Calendar.YEAR) > start.get(Calendar.YEAR)) {
DateUtils.formatDateTime(context, now.timeInMillis, flags)
} else {
DateUtils.formatDateTime(context, nextEvent.startDate, flags)
}
}
}
bindingView.dateLayout.isVisible = false
bindingView.calendarLayout.isVisible = true
bindingView.subLine.isVisible = true
bindingView.weatherSubLine.isVisible = true
bindingView.subLineTopMarginSmall.visibility =
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.rawValue) View.VISIBLE else View.GONE
bindingView.subLineTopMarginMedium.visibility =
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.rawValue) View.VISIBLE else View.GONE
bindingView.subLineTopMarginLarge.visibility =
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.rawValue) View.VISIBLE else View.GONE
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
bindingView.subLineIcon.isVisible = true
var showSomething = false
loop@ for (provider: Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(
context
)) {
when (provider) {
Constants.GlanceProviderId.PLAYING_SONG -> {
if (MediaPlayerHelper.isSomeonePlaying(context)) {
bindingView.subLineIcon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_music_note_24
)
)
bindingView.subLineText.text = MediaPlayerHelper.getMediaInfo()
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
if (Preferences.showNextAlarm && nextAlarm != "") {
bindingView.subLineIcon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_alarm_24
)
)
bindingView.subLineText.text = AlarmHelper.getNextAlarm(context)
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
if (Preferences.showBatteryCharging) {
BatteryHelper.updateBatteryInfo(context)
if (Preferences.isCharging) {
bindingView.subLineIcon.isVisible = false
val batteryLevel = BatteryHelper.getBatteryLevel(context)
if (batteryLevel != 100) {
bindingView.subLineText.text = context.getString(R.string.charging)
} else {
bindingView.subLineText.text =
context.getString(R.string.charged)
}
showSomething = true
break@loop
} else if (Preferences.isBatteryLevelLow) {
bindingView.subLineIcon.isVisible = false
bindingView.subLineText.text =
context.getString(R.string.battery_low_warning)
showSomething = true
break@loop
}
}
}
Constants.GlanceProviderId.CUSTOM_INFO -> {
if (Preferences.customNotes.isNotEmpty()) {
bindingView.subLineIcon.isVisible = false
bindingView.subLineText.text = Preferences.customNotes
bindingView.subLineText.maxLines = 2
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
bindingView.subLineIcon.isVisible = false
bindingView.subLineText.text =
context.getString(R.string.daily_steps_counter)
.format(Preferences.googleFitSteps)
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
try {
if (Preferences.lastNotificationIcon != 0) {
val remotePackageContext = context.createPackageContext(
Preferences.lastNotificationPackage, 0)
val icon = ContextCompat.getDrawable(remotePackageContext,
Preferences.lastNotificationIcon)
bindingView.subLineIcon.isVisible = true
bindingView.subLineIcon.setImageDrawable(icon)
} else {
bindingView.subLineIcon.isVisible = false
}
bindingView.subLineText.text = Preferences.lastNotificationTitle
showSomething = true
break@loop
} catch (ex: Exception) {}
}
}
Constants.GlanceProviderId.GREETINGS -> {
val greetingsText = GreetingsHelper.getRandomString(context)
if (Preferences.showGreetings && GreetingsHelper.showGreetings() && greetingsText.isNotBlank()) {
bindingView.subLineText.text = greetingsText
bindingView.subLineText.maxLines = 2
bindingView.subLineIcon.isVisible = false
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.EVENTS -> {
if (Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(
Manifest.permission.READ_CALENDAR) && nextEvent != null) {
bindingView.subLineText.text = context.getString(R.string.events_glance_provider_format).format(nextEvent.title, if (Preferences.showDiffTime && now.timeInMillis < nextEvent.startDate) {
if (!nextEvent.allDay) {
SettingsStringHelper.getDifferenceText(
context,
now.timeInMillis,
nextEvent.startDate
)
.toLowerCase(Locale.getDefault())
} else {
SettingsStringHelper.getAllDayEventDifferenceText(
context,
now.timeInMillis,
nextEvent.startDate
).toLowerCase(Locale.getDefault())
}
} else "").trimEnd()
bindingView.subLineIcon.isVisible = true
bindingView.subLineIcon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_today_24
)
)
showSomething = true
break@loop
}
}
}
}
if (showSomething) {
bindingView.dateLayout.isVisible = true
bindingView.calendarLayout.isVisible = false
bindingView.subLine.isVisible = true
bindingView.weatherSubLine.isVisible = false
bindingView.subLineTopMarginSmall.visibility =
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.rawValue) View.VISIBLE else View.GONE
bindingView.subLineTopMarginMedium.visibility =
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.rawValue) View.VISIBLE else View.GONE
bindingView.subLineTopMarginLarge.visibility =
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.rawValue) View.VISIBLE else View.GONE
} else {
bindingView.subLineIcon.isVisible = false
}
}
// Color
listOf<TextView>(
bindingView.date,
bindingView.weatherDateLineTemperature,
bindingView.nextEvent,
bindingView.nextEventDifferenceTime,
).forEach {
it.setTextColor(ColorHelper.getFontColor(context.applicationContext.isDarkTheme()))
}
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.rawValue) {
listOf<ImageView>(bindingView.actionNext)
} else {
listOf<ImageView>(
bindingView.actionNext,
bindingView.weatherDateLineWeatherIcon,
bindingView.weatherSubLineWeatherIcon
)
}.forEach {
it.setColorFilter(ColorHelper.getFontColorRgb(context.applicationContext.isDarkTheme()))
it.alpha =
(if (context.isDarkTheme()) Preferences.textGlobalAlphaDark.toIntValue()
.toFloat() else Preferences.textGlobalAlpha.toIntValue()
.toFloat()) / 100
}
listOf<TextView>(bindingView.subLineText, bindingView.weatherSubLineDivider, bindingView.weatherSubLineTemperature).forEach {
it.setTextColor(ColorHelper.getSecondaryFontColor(context.applicationContext.isDarkTheme()))
}
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.rawValue) {
listOf<ImageView>(bindingView.subLineIcon, bindingView.subLineIconShadow)
} else {
listOf<ImageView>(bindingView.subLineIcon, bindingView.weatherSubLineWeatherIcon, bindingView.subLineIconShadow)
}.forEach {
it.setColorFilter(ColorHelper.getSecondaryFontColorRgb(context.applicationContext.isDarkTheme()))
it.alpha =
(if (context.isDarkTheme()) Preferences.textSecondaryAlphaDark.toIntValue()
.toFloat() else Preferences.textSecondaryAlpha.toIntValue()
.toFloat()) / 100
}
// Text Size
listOf<Pair<TextView, Float>>(
bindingView.date to Preferences.textMainSize,
bindingView.weatherDateLineTemperature to ((Preferences.textMainSize + Preferences.textSecondSize) / 2),
bindingView.nextEvent to Preferences.textMainSize,
bindingView.nextEventDifferenceTime to Preferences.textMainSize,
bindingView.subLineText to Preferences.textSecondSize,
bindingView.weatherSubLineDivider to (Preferences.textSecondSize - 2),
bindingView.weatherSubLineTemperature to Preferences.textSecondSize,
).forEach {
it.first.setTextSize(TypedValue.COMPLEX_UNIT_SP, it.second)
}
// Icons scale
bindingView.subLineIcon.scaleX = Preferences.textSecondSize / 18f
bindingView.subLineIcon.scaleY = Preferences.textSecondSize / 18f
bindingView.weatherSubLineWeatherIcon.scaleX = Preferences.textSecondSize / 18f
bindingView.weatherSubLineWeatherIcon.scaleY = Preferences.textSecondSize / 18f
bindingView.weatherDateLineWeatherIcon.scaleX = ((Preferences.textMainSize + Preferences.textSecondSize) / 2) / 20f
bindingView.weatherDateLineWeatherIcon.scaleY = ((Preferences.textMainSize + Preferences.textSecondSize) / 2) / 20f
bindingView.actionNext.scaleX = Preferences.textMainSize / 28f
bindingView.actionNext.scaleY = Preferences.textMainSize / 28f
// Shadows
val shadowRadius =
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
0 -> 0f
1 -> 5f
2 -> 5f
else -> 5f
}
val shadowColor =
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
0 -> Color.TRANSPARENT
1 -> R.color.black_50
2 -> Color.BLACK
else -> R.color.black_50
}
val shadowDy =
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
0 -> 0f
1 -> 0f
2 -> 1f
else -> 0f
}
listOf<TextView>(
bindingView.date,
bindingView.weatherDateLineTemperature,
bindingView.nextEvent,
bindingView.nextEventDifferenceTime,
bindingView.subLineText,
bindingView.weatherSubLineDivider,
bindingView.weatherSubLineTemperature,
).forEach {
it.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
}
// Icons shadow
listOf(
Pair(bindingView.subLineIcon, bindingView.subLineIconShadow),
).forEach {
if ((if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) == 0) {
it.second.isVisible = false
} else {
it.second.isVisible = it.first.isVisible
it.second.scaleX = it.first.scaleX
it.second.scaleY = it.first.scaleY
it.second.applyShadow(it.first)
}
}
listOf(
Pair(bindingView.actionNext, bindingView.actionNextShadow),
).forEach {
if ((if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) == 0) {
it.second.isVisible = false
} else {
it.second.isVisible = it.first.isVisible
it.second.scaleX = it.first.scaleX
it.second.scaleY = it.first.scaleY
it.second.applyShadow(it.first, 0.6f)
}
}
// Custom Font
if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) {
val googleSans: Typeface = when (Preferences.customFontVariant) {
"100" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_thin.ttf")
"200" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_light.ttf")
"500" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_medium.ttf")
"700" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_bold.ttf")
"800" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_black.ttf")
else -> Typeface.createFromAsset(context.assets, "fonts/google_sans_regular.ttf")
}
listOf<TextView>(
bindingView.date,
bindingView.weatherDateLineTemperature,
bindingView.nextEvent,
bindingView.nextEventDifferenceTime,
bindingView.subLineText,
bindingView.weatherSubLineDivider,
bindingView.weatherSubLineTemperature,
).forEach {
it.typeface = googleSans
}
} else if (Preferences.customFont == Constants.CUSTOM_FONT_DOWNLOADED && typeface != null) {
listOf<TextView>(
bindingView.date,
bindingView.weatherDateLineTemperature,
bindingView.nextEvent,
bindingView.nextEventDifferenceTime,
bindingView.subLineText,
bindingView.weatherSubLineDivider,
bindingView.weatherSubLineTemperature,
).forEach {
it.typeface = typeface
}
}
// Dividers
arrayOf(bindingView.weatherSubLineDivider).forEach {
it.visibility = if (Preferences.showDividers) View.VISIBLE else View.INVISIBLE
it.layoutParams = (it.layoutParams as ViewGroup.MarginLayoutParams).apply {
this.marginEnd = if (Preferences.showDividers) 8f.convertDpToPixel(context).toInt() else 0
}
}
eventRepository.close()
return bindingView
}
}

View File

@ -0,0 +1,925 @@
package com.tommasoberlose.anotherwidget.ui.widgets
import android.Manifest
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.Typeface
import android.text.format.DateUtils
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.RemoteViews
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.databinding.TheWidgetBinding
import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.*
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
import com.tommasoberlose.anotherwidget.helpers.ImageHelper.applyShadow
import com.tommasoberlose.anotherwidget.receivers.CrashlyticsReceiver
import com.tommasoberlose.anotherwidget.receivers.NewCalendarEventReceiver
import com.tommasoberlose.anotherwidget.receivers.WidgetClickListenerReceiver
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.convertDpToPixel
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
import com.tommasoberlose.anotherwidget.utils.toPixel
import java.text.DateFormat
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.math.roundToInt
class StandardWidget(val context: Context) {
fun generateWidget(appWidgetId: Int, w: Int, typeface: Typeface? = null): RemoteViews {
var views = RemoteViews(context.packageName, R.layout.the_widget_sans)
try {
// Background
views.setInt(
R.id.widget_shape_background,
"setColorFilter",
ColorHelper.getBackgroundColorRgb(context.isDarkTheme())
)
views.setInt(
R.id.widget_shape_background,
"setImageAlpha",
ColorHelper.getBackgroundAlpha(context.isDarkTheme())
)
val refreshIntent = PendingIntent.getActivity(
context,
appWidgetId,
IntentHelper.getWidgetUpdateIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.widget_shape_background, refreshIntent)
} catch (ex: Exception) {
ex.printStackTrace()
CrashlyticsReceiver.sendCrash(context, ex)
}
// Clock
views = ClockWidget(context).updateClockView(views, appWidgetId)
// Setup listener
try {
val generatedBinding = generateWidgetView(typeface)
views.setImageViewBitmap(
R.id.bitmap_container,
BitmapHelper.getBitmapFromView(generatedBinding.root, width = w)
)
views = updateGridView(generatedBinding, views, appWidgetId)
} catch (ex: Exception) {
ex.printStackTrace()
CrashlyticsReceiver.sendCrash(context, ex)
}
return views
}
private fun updateGridView(bindingView: TheWidgetBinding, views: RemoteViews, widgetID: Int): RemoteViews {
val eventRepository = EventRepository(context)
try {
// Weather
if (Preferences.showWeather && Preferences.weatherIcon != "") {
views.setViewVisibility(R.id.weather_rect, View.VISIBLE)
views.setViewVisibility(R.id.weather_sub_line, View.GONE)
val i = Intent(context, WidgetClickListenerReceiver::class.java)
i.action = Actions.ACTION_OPEN_WEATHER_INTENT
val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, 0)
views.setOnClickPendingIntent(R.id.weather_rect, weatherPIntent)
views.setOnClickPendingIntent(R.id.weather_sub_line_rect, weatherPIntent)
views.setImageViewBitmap(
R.id.weather_rect,
BitmapHelper.getBitmapFromView(bindingView.weatherDateLine, draw = false)
)
views.setImageViewBitmap(
R.id.weather_sub_line_rect,
BitmapHelper.getBitmapFromView(bindingView.weatherSubLine, draw = false)
)
} else {
views.setViewVisibility(R.id.weather_rect, View.GONE)
views.setViewVisibility(R.id.weather_sub_line, View.GONE)
}
// Calendar
views.setImageViewBitmap(
R.id.date_rect,
BitmapHelper.getBitmapFromView(bindingView.date, draw = false)
)
val calPIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getCalendarIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.date_rect, calPIntent)
views.setViewVisibility(R.id.date_layout, View.VISIBLE)
val nextEvent = eventRepository.getNextEvent()
val nextAlarm = AlarmHelper.getNextAlarm(context)
// Spacing
views.setViewVisibility(
R.id.sub_line_top_margin_small_sans,
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.rawValue) View.VISIBLE else View.GONE
)
views.setViewVisibility(
R.id.sub_line_top_margin_medium_sans,
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.rawValue) View.VISIBLE else View.GONE
)
views.setViewVisibility(
R.id.sub_line_top_margin_large_sans,
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.rawValue) View.VISIBLE else View.GONE
)
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null && !Preferences.showEventsAsGlanceProvider) {
if (Preferences.showNextEvent && eventRepository.getEventsCount() > 1) {
// Action next event
views.setImageViewBitmap(
R.id.action_next_rect,
BitmapHelper.getBitmapFromView(bindingView.actionNext, draw = false)
)
views.setViewVisibility(R.id.action_next_rect, View.VISIBLE)
views.setOnClickPendingIntent(
R.id.action_next_rect,
PendingIntent.getBroadcast(
context,
widgetID,
Intent(
context,
NewCalendarEventReceiver::class.java
).apply { action = Actions.ACTION_GO_TO_NEXT_EVENT },
PendingIntent.FLAG_UPDATE_CURRENT
)
)
// Action previous event
views.setImageViewBitmap(
R.id.action_previous_rect,
BitmapHelper.getBitmapFromView(bindingView.actionPrevious, draw = false)
)
views.setViewVisibility(R.id.action_previous_rect, View.VISIBLE)
views.setOnClickPendingIntent(
R.id.action_previous_rect,
PendingIntent.getBroadcast(
context,
widgetID,
Intent(
context,
NewCalendarEventReceiver::class.java
).apply { action = Actions.ACTION_GO_TO_PREVIOUS_EVENT },
PendingIntent.FLAG_UPDATE_CURRENT
)
)
views.setViewVisibility(R.id.action_next_rect, View.VISIBLE)
views.setViewVisibility(R.id.action_previous_rect, View.VISIBLE)
} else {
views.setViewVisibility(R.id.action_next_rect, View.GONE)
views.setViewVisibility(R.id.action_previous_rect, View.GONE)
}
// Event intent
val eventIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getEventIntent(context, nextEvent),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.next_event_rect, eventIntent)
views.setViewVisibility(R.id.next_event_rect, View.VISIBLE)
// Event time difference
if (Preferences.showDiffTime && Calendar.getInstance().timeInMillis < (nextEvent.startDate - 1000 * 60 * 60)) {
views.setImageViewBitmap(
R.id.next_event_difference_time_rect,
BitmapHelper.getBitmapFromView(
bindingView.nextEventDifferenceTime,
draw = false
)
)
views.setViewVisibility(R.id.next_event_difference_time_rect, View.VISIBLE)
views.setOnClickPendingIntent(R.id.next_event_difference_time_rect, eventIntent)
} else {
views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE)
}
// Event information
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
val mapIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getGoogleMapsIntentFromAddress(context, nextEvent.address),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.sub_line_rect, mapIntent)
} else {
val pIntentDetail = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getEventIntent(
context,
nextEvent,
forceEventDetails = true
),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.sub_line_rect, pIntentDetail)
}
views.setImageViewBitmap(
R.id.next_event_rect,
BitmapHelper.getBitmapFromView(bindingView.nextEvent, draw = false)
)
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
// Second row
views.setImageViewBitmap(
R.id.sub_line_rect,
BitmapHelper.getBitmapFromView(bindingView.subLine, draw = false)
)
views.setViewVisibility(R.id.sub_line_rect, View.VISIBLE)
} else if (GlanceProviderHelper.showGlanceProviders(context) && bindingView.calendarLayout.isVisible) {
var showSomething = false
loop@ for (provider: Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(context)) {
when (provider) {
Constants.GlanceProviderId.PLAYING_SONG -> {
if (MediaPlayerHelper.isSomeonePlaying(context)) {
val musicIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getMusicIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.sub_line_rect, musicIntent)
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
if (Preferences.showNextAlarm && nextAlarm != "") {
val alarmIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getClockIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.sub_line_rect, alarmIntent)
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
if (Preferences.showBatteryCharging) {
BatteryHelper.updateBatteryInfo(context)
if (Preferences.isCharging || Preferences.isBatteryLevelLow) {
val batteryIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getBatteryIntent(),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.sub_line_rect, batteryIntent)
showSomething = true
break@loop
}
}
}
Constants.GlanceProviderId.CUSTOM_INFO -> {
if (Preferences.customNotes.isNotEmpty()) {
break@loop
}
}
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
val fitIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getFitIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(R.id.sub_line_rect, fitIntent)
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
try {
if (Preferences.lastNotificationIcon != 0) {
val remotePackageContext = context.createPackageContext(
Preferences.lastNotificationPackage, 0)
ContextCompat.getDrawable(
remotePackageContext,
Preferences.lastNotificationIcon)
}
val notificationIntent = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getNotificationIntent(context),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(
R.id.sub_line_rect,
notificationIntent
)
showSomething = true
break@loop
} catch (ex: Exception) {}
}
}
Constants.GlanceProviderId.GREETINGS -> {
if (Preferences.showGreetings && GreetingsHelper.showGreetings() && GreetingsHelper.getRandomString(context).isNotBlank()) {
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.EVENTS -> {
if (Preferences.showEventsAsGlanceProvider&& Preferences.showEvents && context.checkGrantedPermission(
Manifest.permission.READ_CALENDAR) && nextEvent != null) {
val pIntentDetail = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getEventIntent(
context,
nextEvent,
forceEventDetails = true
),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(
R.id.sub_line_rect,
pIntentDetail
)
showSomething = true
break@loop
}
}
}
}
if (showSomething) {
views.setImageViewBitmap(
R.id.sub_line_rect,
BitmapHelper.getBitmapFromView(bindingView.subLine, draw = false)
)
views.setViewVisibility(R.id.first_line_rect, View.VISIBLE)
views.setViewVisibility(R.id.calendar_layout_rect, View.GONE)
views.setViewVisibility(R.id.sub_line_rect, View.VISIBLE)
views.setViewVisibility(R.id.weather_sub_line_rect, View.GONE)
} else {
// Spacing
views.setViewVisibility(R.id.sub_line_top_margin_small_sans, View.GONE)
views.setViewVisibility(R.id.sub_line_top_margin_medium_sans, View.GONE)
views.setViewVisibility(R.id.sub_line_top_margin_large_sans, View.GONE)
}
}
} catch (ex: Exception) {
ex.printStackTrace()
CrashlyticsReceiver.sendCrash(context, ex)
} finally {
eventRepository.close()
}
return views
}
// Generates the widget bitmap from the view
fun generateWidgetView(typeface: Typeface? = null): TheWidgetBinding {
val eventRepository = EventRepository(context)
val bindingView = TheWidgetBinding.inflate(LayoutInflater.from(context))
bindingView.loader.isVisible = false
// Weather
if (Preferences.showWeather && Preferences.weatherIcon != "") {
bindingView.weatherDateLine.isVisible = true
val currentTemp = String.format(
Locale.getDefault(),
"%d °%s",
Preferences.weatherTemp.roundToInt(),
Preferences.weatherRealTempUnit
)
val icon: String = Preferences.weatherIcon
if (icon == "") {
bindingView.weatherSubLineWeatherIcon.isVisible = false
bindingView.weatherDateLineWeatherIcon.isVisible = false
} else {
bindingView.weatherSubLineWeatherIcon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon))
bindingView.weatherDateLineWeatherIcon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon))
bindingView.weatherSubLineWeatherIcon.isVisible = true
bindingView.weatherDateLineWeatherIcon.isVisible = true
}
bindingView.weatherDateLineTemperature.text = currentTemp
bindingView.weatherSubLineTemperature.text = currentTemp
if (GlanceProviderHelper.showGlanceProviders(context)) {
bindingView.weatherSubLine.isVisible = false
}
} else {
bindingView.weatherDateLine.isVisible = false
bindingView.weatherSubLine.isVisible = false
}
val now = Calendar.getInstance().apply {
set(Calendar.SECOND, 0)
set(Calendar.MILLISECOND, 0)
}
bindingView.dateLayout.isVisible = true
bindingView.calendarLayout.isVisible = false
bindingView.nextEventDifferenceTime.isVisible = false
bindingView.actionNext.isVisible = false
bindingView.actionPrevious.isVisible = false
bindingView.date.text = DateHelper.getDateText(context, now)
val nextEvent = eventRepository.getNextEvent()
val nextAlarm = AlarmHelper.getNextAlarm(context)
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null && !Preferences.showEventsAsGlanceProvider) {
// Multiple counter
bindingView.actionNext.isVisible =
Preferences.showNextEvent && eventRepository.getEventsCount() > 1
bindingView.actionPrevious.isVisible =
Preferences.showNextEvent && eventRepository.getEventsCount() > 1
bindingView.nextEvent.text = nextEvent.title
if (Preferences.showDiffTime && now.timeInMillis < nextEvent.startDate) {
bindingView.nextEventDifferenceTime.text = if (!nextEvent.allDay) {
SettingsStringHelper.getDifferenceText(
context,
now.timeInMillis,
nextEvent.startDate
)
.toLowerCase(Locale.getDefault())
} else {
SettingsStringHelper.getAllDayEventDifferenceText(
context,
now.timeInMillis,
nextEvent.startDate
).toLowerCase(Locale.getDefault())
}
bindingView.nextEventDifferenceTime.isVisible = true
} else {
bindingView.nextEventDifferenceTime.isVisible = false
}
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
bindingView.subLineIcon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_place_24
)
)
bindingView.subLineText.text = nextEvent.address
} else {
bindingView.subLineIcon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_today_24
)
)
if (!nextEvent.allDay) {
val startHour =
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault())
.format(nextEvent.startDate)
val endHour =
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault())
.format(nextEvent.endDate)
var dayDiff =
TimeUnit.MILLISECONDS.toDays(nextEvent.endDate - nextEvent.startDate)
val startCal = Calendar.getInstance()
startCal.timeInMillis = nextEvent.startDate
val endCal = Calendar.getInstance()
endCal.timeInMillis = nextEvent.endDate
if (startCal.get(Calendar.HOUR_OF_DAY) > endCal.get(Calendar.HOUR_OF_DAY)) {
dayDiff++
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(
Calendar.MINUTE
) > endCal.get(Calendar.MINUTE)
) {
dayDiff++
}
var multipleDay = ""
if (dayDiff > 0) {
multipleDay = String.format(
" (+%s%s)",
dayDiff,
context.getString(R.string.day_char)
)
}
if (nextEvent.startDate != nextEvent.endDate) {
bindingView.subLineText.text =
String.format("%s - %s%s", startHour, endHour, multipleDay)
} else {
bindingView.subLineText.text =
String.format("%s", startHour)
}
} else {
val flags: Int =
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
val start = Calendar.getInstance().apply { timeInMillis = nextEvent.startDate }
bindingView.subLineText.text = if (now.get(Calendar.DAY_OF_YEAR) == start.get(
Calendar.DAY_OF_YEAR)) {
DateUtils.formatDateTime(context, nextEvent.startDate, flags)
} else if (now.get(Calendar.DAY_OF_YEAR) > start.get(Calendar.DAY_OF_YEAR) || now.get(
Calendar.YEAR) > start.get(Calendar.YEAR)) {
DateUtils.formatDateTime(context, now.timeInMillis, flags)
} else {
DateUtils.formatDateTime(context, nextEvent.startDate, flags)
}
}
}
bindingView.dateLayout.isVisible = false
bindingView.calendarLayout.isVisible = true
bindingView.subLine.isVisible = true
bindingView.weatherSubLine.isVisible = true
bindingView.subLineTopMarginSmall.visibility =
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.rawValue) View.VISIBLE else View.GONE
bindingView.subLineTopMarginMedium.visibility =
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.rawValue) View.VISIBLE else View.GONE
bindingView.subLineTopMarginLarge.visibility =
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.rawValue) View.VISIBLE else View.GONE
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
bindingView.subLineIcon.isVisible = true
var showSomething = false
loop@ for (provider: Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(
context
)) {
when (provider) {
Constants.GlanceProviderId.PLAYING_SONG -> {
if (MediaPlayerHelper.isSomeonePlaying(context)) {
bindingView.subLineIcon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_music_note_24
)
)
bindingView.subLineText.text = MediaPlayerHelper.getMediaInfo()
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
if (Preferences.showNextAlarm && nextAlarm != "") {
bindingView.subLineIcon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_alarm_24
)
)
bindingView.subLineText.text = AlarmHelper.getNextAlarm(context)
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
if (Preferences.showBatteryCharging) {
BatteryHelper.updateBatteryInfo(context)
if (Preferences.isCharging) {
bindingView.subLineIcon.isVisible = false
val batteryLevel = BatteryHelper.getBatteryLevel(context)
if (batteryLevel != 100) {
bindingView.subLineText.text = context.getString(R.string.charging)
} else {
bindingView.subLineText.text =
context.getString(R.string.charged)
}
showSomething = true
break@loop
} else if (Preferences.isBatteryLevelLow) {
bindingView.subLineIcon.isVisible = false
bindingView.subLineText.text =
context.getString(R.string.battery_low_warning)
showSomething = true
break@loop
}
}
}
Constants.GlanceProviderId.CUSTOM_INFO -> {
if (Preferences.customNotes.isNotEmpty()) {
bindingView.subLineIcon.isVisible = false
bindingView.subLineText.text = Preferences.customNotes
bindingView.subLineText.maxLines = 2
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
bindingView.subLineIcon.isVisible = false
bindingView.subLineText.text =
context.getString(R.string.daily_steps_counter)
.format(Preferences.googleFitSteps)
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
try {
if (Preferences.lastNotificationIcon != 0) {
val remotePackageContext = context.createPackageContext(
Preferences.lastNotificationPackage, 0)
val icon = ContextCompat.getDrawable(remotePackageContext,
Preferences.lastNotificationIcon)
bindingView.subLineIcon.isVisible = true
bindingView.subLineIcon.setImageDrawable(icon)
} else {
bindingView.subLineIcon.isVisible = false
}
bindingView.subLineText.text = Preferences.lastNotificationTitle
showSomething = true
break@loop
} catch (ex: Exception) {}
}
}
Constants.GlanceProviderId.GREETINGS -> {
val greetingsText = GreetingsHelper.getRandomString(context)
if (Preferences.showGreetings && GreetingsHelper.showGreetings() && greetingsText.isNotBlank()) {
bindingView.subLineText.text = greetingsText
bindingView.subLineText.maxLines = 2
bindingView.subLineIcon.isVisible = false
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.EVENTS -> {
if (Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(
Manifest.permission.READ_CALENDAR) && nextEvent != null) {
bindingView.subLineText.text = context.getString(R.string.events_glance_provider_format).format(nextEvent.title, if (Preferences.showDiffTime && now.timeInMillis < nextEvent.startDate) {
if (!nextEvent.allDay) {
SettingsStringHelper.getDifferenceText(
context,
now.timeInMillis,
nextEvent.startDate
)
.toLowerCase(Locale.getDefault())
} else {
SettingsStringHelper.getAllDayEventDifferenceText(
context,
now.timeInMillis,
nextEvent.startDate
).toLowerCase(Locale.getDefault())
}
} else "").trimEnd()
bindingView.subLineIcon.isVisible = true
bindingView.subLineIcon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_today_24
)
)
showSomething = true
break@loop
}
}
}
}
if (showSomething) {
bindingView.dateLayout.isVisible = true
bindingView.calendarLayout.isVisible = false
bindingView.subLine.isVisible = true
bindingView.weatherSubLine.isVisible = false
bindingView.subLineTopMarginSmall.visibility =
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.rawValue) View.VISIBLE else View.GONE
bindingView.subLineTopMarginMedium.visibility =
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.rawValue) View.VISIBLE else View.GONE
bindingView.subLineTopMarginLarge.visibility =
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.rawValue) View.VISIBLE else View.GONE
} else {
bindingView.subLineIcon.isVisible = false
}
}
// Color
listOf<TextView>(
bindingView.date,
bindingView.weatherDateLineDivider,
bindingView.weatherDateLineTemperature,
bindingView.nextEvent,
bindingView.nextEventDifferenceTime,
).forEach {
it.setTextColor(ColorHelper.getFontColor(context.applicationContext.isDarkTheme()))
}
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.rawValue) {
listOf<ImageView>(bindingView.actionNext, bindingView.actionPrevious)
} else {
listOf<ImageView>(
bindingView.actionNext,
bindingView.actionPrevious,
bindingView.weatherDateLineWeatherIcon,
bindingView.weatherSubLineWeatherIcon
)
}.forEach {
it.setColorFilter(ColorHelper.getFontColorRgb(context.applicationContext.isDarkTheme()))
it.alpha =
(if (context.isDarkTheme()) Preferences.textGlobalAlphaDark.toIntValue()
.toFloat() else Preferences.textGlobalAlpha.toIntValue()
.toFloat()) / 100
}
listOf<TextView>(bindingView.subLineText, bindingView.weatherSubLineDivider, bindingView.weatherSubLineTemperature).forEach {
it.setTextColor(ColorHelper.getSecondaryFontColor(context.applicationContext.isDarkTheme()))
}
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.rawValue) {
listOf<ImageView>(bindingView.subLineIcon, bindingView.subLineIconShadow)
} else {
listOf<ImageView>(bindingView.subLineIcon, bindingView.weatherSubLineWeatherIcon, bindingView.subLineIconShadow)
}.forEach {
it.setColorFilter(ColorHelper.getSecondaryFontColorRgb(context.applicationContext.isDarkTheme()))
it.alpha =
(if (context.isDarkTheme()) Preferences.textSecondaryAlphaDark.toIntValue()
.toFloat() else Preferences.textSecondaryAlpha.toIntValue()
.toFloat()) / 100
}
// Text Size
listOf<Pair<TextView, Float>>(
bindingView.date to Preferences.textMainSize,
bindingView.weatherDateLineDivider to (Preferences.textMainSize - 2),
bindingView.weatherDateLineTemperature to Preferences.textMainSize,
bindingView.nextEvent to Preferences.textMainSize,
bindingView.nextEventDifferenceTime to Preferences.textMainSize,
bindingView.subLineText to Preferences.textSecondSize,
bindingView.weatherSubLineDivider to (Preferences.textSecondSize - 2),
bindingView.weatherSubLineTemperature to Preferences.textSecondSize,
).forEach {
it.first.setTextSize(TypedValue.COMPLEX_UNIT_SP, it.second)
}
// Icons scale
bindingView.subLineIcon.scaleX = Preferences.textSecondSize / 18f
bindingView.subLineIcon.scaleY = Preferences.textSecondSize / 18f
bindingView.weatherSubLineWeatherIcon.scaleX = Preferences.textSecondSize / 18f
bindingView.weatherSubLineWeatherIcon.scaleY = Preferences.textSecondSize / 18f
bindingView.weatherDateLineWeatherIcon.scaleX = Preferences.textMainSize / 18f
bindingView.weatherDateLineWeatherIcon.scaleY = Preferences.textMainSize / 18f
bindingView.actionNext.scaleX = Preferences.textMainSize / 28f
bindingView.actionNext.scaleY = Preferences.textMainSize / 28f
bindingView.actionPrevious.scaleX = Preferences.textMainSize / 28f
bindingView.actionPrevious.scaleY = Preferences.textMainSize / 28f
// Shadows
val shadowRadius =
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
0 -> 0f
1 -> 5f
2 -> 5f
else -> 5f
}
val shadowColor =
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
0 -> Color.TRANSPARENT
1 -> R.color.black_50
2 -> Color.BLACK
else -> R.color.black_50
}
val shadowDy =
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
0 -> 0f
1 -> 0f
2 -> 1f
else -> 0f
}
listOf<TextView>(
bindingView.date,
bindingView.weatherDateLineDivider,
bindingView.weatherDateLineTemperature,
bindingView.nextEvent,
bindingView.nextEventDifferenceTime,
bindingView.subLineText,
bindingView.weatherSubLineDivider,
bindingView.weatherSubLineTemperature,
).forEach {
it.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
}
// Icons shadow
listOf(
Pair(bindingView.subLineIcon, bindingView.subLineIconShadow),
).forEach {
if ((if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) == 0) {
it.second.isVisible = false
} else {
it.second.isVisible = it.first.isVisible
it.second.scaleX = it.first.scaleX
it.second.scaleY = it.first.scaleY
it.second.applyShadow(it.first)
}
}
listOf(
Pair(bindingView.actionNext, bindingView.actionNextShadow),
Pair(bindingView.actionPrevious, bindingView.actionPreviousShadow),
).forEach {
if ((if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) == 0) {
it.second.isVisible = false
} else {
it.second.isVisible = it.first.isVisible
it.second.scaleX = it.first.scaleX
it.second.scaleY = it.first.scaleY
it.second.applyShadow(it.first, 0.6f)
}
}
bindingView.actionPrevious.scaleX = bindingView.actionPrevious.scaleX * -1
bindingView.actionPreviousShadow.scaleX = bindingView.actionPreviousShadow.scaleX * -1
// Custom Font
if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) {
val googleSans: Typeface = when (Preferences.customFontVariant) {
"100" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_thin.ttf")
"200" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_light.ttf")
"500" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_medium.ttf")
"700" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_bold.ttf")
"800" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_black.ttf")
else -> Typeface.createFromAsset(context.assets, "fonts/google_sans_regular.ttf")
}
listOf<TextView>(
bindingView.date,
bindingView.weatherDateLineDivider,
bindingView.weatherDateLineTemperature,
bindingView.nextEvent,
bindingView.nextEventDifferenceTime,
bindingView.subLineText,
bindingView.weatherSubLineDivider,
bindingView.weatherSubLineTemperature,
).forEach {
it.typeface = googleSans
}
} else if (Preferences.customFont == Constants.CUSTOM_FONT_DOWNLOADED && typeface != null) {
listOf<TextView>(
bindingView.date,
bindingView.weatherDateLineDivider,
bindingView.weatherDateLineTemperature,
bindingView.nextEvent,
bindingView.nextEventDifferenceTime,
bindingView.subLineText,
bindingView.weatherSubLineDivider,
bindingView.weatherSubLineTemperature,
).forEach {
it.typeface = typeface
}
}
// Dividers
arrayOf(bindingView.weatherDateLineDivider, bindingView.weatherSubLineDivider).forEach {
it.visibility = if (Preferences.showDividers) View.VISIBLE else View.INVISIBLE
it.layoutParams = (it.layoutParams as ViewGroup.MarginLayoutParams).apply {
this.marginEnd = if (Preferences.showDividers) 8f.convertDpToPixel(context).toInt() else 0
}
}
eventRepository.close()
return bindingView
}
}

View File

@ -111,6 +111,43 @@
android:paddingLeft="20dp" android:paddingLeft="20dp"
android:paddingRight="20dp" android:paddingRight="20dp"
android:textAppearance="@style/AnotherWidget.Settings.Header" /> android:textAppearance="@style/AnotherWidget.Settings.Header" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:clickable="true"
android:focusable="true"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:id="@+id/action_widget_align"
android:orientation="horizontal">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="12dp"
android:src="@drawable/round_dashboard_24"
app:tint="@color/colorPrimaryText"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Settings.Title"
android:text="@string/settings_widget_align_title"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/widget_align_label"
style="@style/AnotherWidget.Settings.Subtitle"/>
</LinearLayout>
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -0,0 +1,212 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical"
android:id="@+id/main_layout">
<ProgressBar
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
android:indeterminate="true"
android:layout_centerInParent="true"
android:indeterminateTint="@color/colorPrimary"
android:id="@+id/loader" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerVertical="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:visibility="gone"
android:layout_marginBottom="8dp"
android:orientation="vertical"
android:layoutDirection="locale"
android:id="@+id/date_layout">
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:textColor="@color/colorPrimary"
android:maxLines="1"
android:ellipsize="end"
android:includeFontPadding="false"
style="@style/AnotherWidget.Widget.Title"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:visibility="gone"
android:id="@+id/weather_date_line">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:id="@+id/weather_date_line_weather_icon"
android:layout_marginStart="8dp"
android:layout_marginEnd="4dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Widget.Date.Big"
android:maxLines="1"
android:includeFontPadding="false"
android:id="@+id/weather_date_line_temperature"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layoutDirection="locale"
android:layout_gravity="center_vertical"
android:id="@+id/calendar_layout"
android:visibility="gone"
android:orientation="horizontal">
<TextView
android:id="@+id/next_event"
android:layout_width="0dp"
android:layout_weight="1"
android:maxLines="1"
android:lines="1"
android:gravity="end"
android:ellipsize="end"
android:includeFontPadding="false"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Widget.Title" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center">
<TextView
android:id="@+id/next_event_difference_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:includeFontPadding="false"
style="@style/AnotherWidget.Widget.Title" />
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical">
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:id="@+id/action_next_shadow"
android:src="@drawable/round_chevron_right_24" />
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:id="@+id/action_next"
android:src="@drawable/round_chevron_right_24" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="4dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/sub_line_top_margin_small" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="8dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/sub_line_top_margin_medium" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="12dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/sub_line_top_margin_large" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:baselineAligned="false"
android:layout_gravity="center_vertical"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingStart="4dp"
android:layoutDirection="locale"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:id="@+id/sub_line"
android:visibility="gone"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:cropToPadding="false"
android:clipChildren="false"
android:layout_marginEnd="4dp">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:cropToPadding="false"
android:clipChildren="false"
android:id="@+id/sub_line_icon_shadow"
android:src="@drawable/round_today_24"/>
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:cropToPadding="false"
android:clipChildren="false"
android:id="@+id/sub_line_icon"
android:src="@drawable/round_today_24"/>
</RelativeLayout>
<TextView
android:id="@+id/sub_line_text"
android:layout_width="wrap_content"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:includeFontPadding="false"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Widget.Subtitle" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:visibility="gone"
android:layout_marginStart="4dp"
android:id="@+id/weather_sub_line">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="4dp"
android:id="@+id/weather_sub_line_divider"
android:text="@string/divider"
android:includeFontPadding="false"
style="@style/AnotherWidget.Widget.Subtitle"/>
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:id="@+id/weather_sub_line_weather_icon"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Widget.Date.Big"
android:maxLines="1"
android:includeFontPadding="false"
android:id="@+id/weather_sub_line_temperature"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,181 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:scaleType="fitXY"
android:id="@+id/widget_shape_background"
android:src="@drawable/card_background" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:id="@+id/main_layout"
android:animateLayoutChanges="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/time_container"
android:layoutDirection="locale"
android:orientation="horizontal">
<TextClock
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:format12Hour="h:mm"
android:padding="0dp"
android:lines="1"
android:maxLines="1"
style="@style/AnotherWidget.Widget.Title"
android:gravity="center_vertical"/>
<TextClock
android:id="@+id/time_am_pm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:format12Hour="a"
android:format24Hour=""
android:padding="0dp"
android:lines="1"
android:maxLines="1"
style="@style/AnotherWidget.Widget.Title"
android:gravity="center_vertical"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginTop="-16dp"
android:orientation="horizontal"
android:id="@+id/clock_bottom_margin_none" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginTop="-8dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/clock_bottom_margin_small" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="2dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/clock_bottom_margin_medium" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="10dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/clock_bottom_margin_large" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_centerVertical="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:alpha="0"
android:visibility="gone"
android:orientation="vertical"
android:layoutDirection="locale"
android:id="@+id/first_line_rect">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/date_rect"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:id="@+id/weather_rect" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layoutDirection="locale"
android:visibility="gone"
android:id="@+id/calendar_layout_rect"
android:orientation="horizontal">
<ImageView
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:id="@+id/next_event_rect" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:id="@+id/next_event_difference_time_rect" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_gravity="center_vertical"
android:id="@+id/action_next_rect" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="4dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/sub_line_top_margin_small_sans" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="8dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/sub_line_top_margin_medium_sans" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="12dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/sub_line_top_margin_large_sans" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layoutDirection="locale"
android:gravity="center_vertical">
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/sub_line_rect" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:id="@+id/weather_sub_line_rect" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:layout_centerVertical="true"
android:id="@+id/bitmap_container"/>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,280 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:clipChildren="false"
android:clipToPadding="false"
android:id="@+id/main_layout">
<ProgressBar
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_centerInParent="true"
android:indeterminate="true"
android:indeterminateTint="@color/colorPrimary"
android:id="@+id/loader" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|end"
android:layout_centerVertical="true"
android:orientation="vertical"
android:id="@+id/date_layout">
<TextView
android:id="@+id/empty_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:textColor="@color/colorPrimary"
android:maxLines="1"
android:ellipsize="end"
android:includeFontPadding="false"
style="@style/AnotherWidget.Widget.Title"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|end"
android:visibility="gone"
android:scaleX=".8"
android:scaleY=".8"
android:transformPivotX="0dp"
android:layout_marginStart="4dp"
android:id="@+id/weather">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:id="@+id/divider1"
android:text="@string/divider"
android:includeFontPadding="false"
style="@style/AnotherWidget.Widget.Subtitle"/>
</LinearLayout>
<ImageView
android:layout_width="28dp"
android:layout_height="28dp"
android:paddingEnd="4dp"
android:paddingStart="4dp"
android:layout_marginEnd="4dp"
android:id="@+id/empty_weather_icon"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Widget.Date.Big"
android:maxLines="1"
android:includeFontPadding="false"
android:id="@+id/temp"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/calendar_layout"
android:visibility="gone"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center_vertical|end">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical">
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:id="@+id/action_previous_shadow"
android:src="@drawable/round_chevron_right_24" />
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:id="@+id/action_previous"
android:src="@drawable/round_chevron_right_24" />
</RelativeLayout>
<TextView
android:id="@+id/next_event"
android:layout_width="0dp"
android:layout_weight="1"
android:maxLines="1"
android:lines="1"
android:gravity="end"
android:ellipsize="end"
android:includeFontPadding="false"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Widget.Title" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:id="@+id/next_event_difference_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:includeFontPadding="false"
style="@style/AnotherWidget.Widget.Title" />
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical">
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:id="@+id/action_next_shadow"
android:src="@drawable/round_chevron_right_24" />
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:id="@+id/action_next"
android:src="@drawable/round_chevron_right_24" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:scaleX=".8"
android:scaleY=".8"
android:transformPivotX="0dp"
android:layout_marginStart="4dp"
android:gravity="center_vertical"
android:id="@+id/special_weather">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:id="@+id/divider3"
android:text="@string/divider"
android:includeFontPadding="false"
style="@style/AnotherWidget.Widget.Subtitle"/>
</LinearLayout>
<ImageView
android:layout_width="28dp"
android:layout_height="28dp"
android:paddingEnd="4dp"
android:paddingStart="4dp"
android:layout_marginEnd="4dp"
android:id="@+id/special_weather_icon"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Widget.Date.Big"
android:maxLines="1"
android:includeFontPadding="false"
android:id="@+id/special_temp"/>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="4dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/second_row_top_margin_small" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="8dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/second_row_top_margin_medium" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="12dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/second_row_top_margin_large" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|end"
android:id="@+id/second_row"
android:layout_marginStart="4dp"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:cropToPadding="false"
android:clipChildren="false"
android:layout_marginEnd="4dp">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:cropToPadding="false"
android:clipChildren="false"
android:id="@+id/second_row_icon_shadow"
android:src="@drawable/round_today_24"/>
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:cropToPadding="false"
android:clipChildren="false"
android:id="@+id/second_row_icon"
android:src="@drawable/round_today_24"/>
</RelativeLayout>
<TextView
android:id="@+id/next_event_date"
android:layout_width="wrap_content"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
android:includeFontPadding="false"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Widget.Subtitle" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:visibility="gone"
android:clipChildren="false"
android:clipToPadding="false"
android:layout_marginStart="8dp"
android:id="@+id/calendar_weather">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:id="@+id/divider2"
android:text="@string/divider"
android:includeFontPadding="false"
style="@style/AnotherWidget.Widget.Subtitle"/>
<ImageView
android:layout_width="18dp"
android:layout_height="18dp"
android:id="@+id/weather_icon"
android:clipChildren="false"
android:clipToPadding="false"
android:adjustViewBounds="true"
android:layout_marginEnd="2dp"
android:layout_marginStart="2dp"
android:src="@drawable/clear_night"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Widget.Date"
android:layout_marginStart="8dp"
android:ellipsize="marquee"
android:layout_marginEnd="4dp"
android:includeFontPadding="false"
android:id="@+id/calendar_temp"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,173 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:scaleType="fitXY"
android:id="@+id/widget_shape_background"
android:src="@drawable/card_background" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center_vertical|end"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:id="@+id/main_layout"
android:animateLayoutChanges="true">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/time_container"
android:orientation="horizontal">
<TextClock
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:format12Hour="h:mm"
android:padding="0dp"
android:lines="1"
android:maxLines="1"
style="@style/AnotherWidget.Widget.Title"/>
<TextClock
android:id="@+id/time_am_pm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:format12Hour="a"
android:format24Hour=""
android:padding="0dp"
android:lines="1"
android:maxLines="1"
style="@style/AnotherWidget.Widget.Title"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginTop="-16dp"
android:orientation="horizontal"
android:id="@+id/clock_bottom_margin_none" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_marginTop="-8dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/clock_bottom_margin_small" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="2dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/clock_bottom_margin_medium" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="10dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/clock_bottom_margin_large" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|end"
android:alpha="0"
android:orientation="vertical"
android:id="@+id/empty_layout_rect">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/empty_date_rect"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/weather_rect" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/calendar_layout_rect"
android:alpha="0"
android:gravity="center_vertical|end">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:id="@+id/action_previous_rect" />
<ImageView
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:id="@+id/next_event_rect" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/next_event_difference_time_rect" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:id="@+id/action_next_rect" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/calendar_weather_rect" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/special_weather_rect" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="4dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/second_row_top_margin_small_sans" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="8dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/second_row_top_margin_medium_sans" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="12dp"
android:visibility="gone"
android:orientation="horizontal"
android:id="@+id/second_row_top_margin_large_sans" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/second_row_rect" />
</LinearLayout>
</LinearLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:id="@+id/bitmap_container"/>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -4,24 +4,32 @@
android:layout_gravity="center" android:layout_gravity="center"
android:clipChildren="false" android:clipChildren="false"
android:clipToPadding="false" android:clipToPadding="false"
android:orientation="vertical"
android:id="@+id/main_layout"> android:id="@+id/main_layout">
<ProgressBar <ProgressBar
android:layout_width="32dp" android:layout_width="32dp"
android:layout_height="32dp" android:layout_height="32dp"
android:layout_centerInParent="true" android:layout_gravity="center"
android:indeterminate="true" android:indeterminate="true"
android:layout_centerInParent="true"
android:indeterminateTint="@color/colorPrimary" android:indeterminateTint="@color/colorPrimary"
android:id="@+id/loader" /> android:id="@+id/loader" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerInParent="true">
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:layout_centerInParent="true" android:visibility="gone"
android:layout_gravity="center"
android:orientation="horizontal" android:orientation="horizontal"
android:layoutDirection="locale" android:layoutDirection="locale"
android:id="@+id/empty_layout"> android:id="@+id/date_layout">
<TextView <TextView
android:id="@+id/empty_date" android:id="@+id/date"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_weight="1" android:layout_weight="1"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -37,20 +45,20 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:visibility="gone" android:visibility="gone"
android:paddingStart="8dp" android:layout_marginStart="4dp"
android:id="@+id/weather"> android:id="@+id/weather_date_line">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:id="@+id/divider1" android:id="@+id/weather_date_line_divider"
android:text="@string/divider" android:text="@string/divider"
android:includeFontPadding="false" android:includeFontPadding="false"
style="@style/AnotherWidget.Widget.Subtitle"/> style="@style/AnotherWidget.Widget.Subtitle"/>
<ImageView <ImageView
android:layout_width="20dp" android:layout_width="20dp"
android:layout_height="20dp" android:layout_height="20dp"
android:id="@+id/empty_weather_icon" android:id="@+id/weather_date_line_weather_icon"
android:layout_marginStart="4dp" android:layout_marginStart="4dp"
android:layout_marginEnd="8dp"/> android:layout_marginEnd="8dp"/>
<TextView <TextView
@ -59,24 +67,17 @@
style="@style/AnotherWidget.Widget.Date.Big" style="@style/AnotherWidget.Widget.Date.Big"
android:maxLines="1" android:maxLines="1"
android:includeFontPadding="false" android:includeFontPadding="false"
android:id="@+id/temp"/> android:id="@+id/weather_date_line_temperature"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerHorizontal="true"
android:id="@+id/calendar_layout"
android:visibility="gone"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center">
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layoutDirection="locale" android:layoutDirection="locale"
android:layout_gravity="center"
android:id="@+id/calendar_layout"
android:visibility="gone"
android:orientation="horizontal"> android:orientation="horizontal">
<RelativeLayout <RelativeLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -131,60 +132,31 @@
android:id="@+id/action_next" android:id="@+id/action_next"
android:src="@drawable/round_chevron_right_24" /> android:src="@drawable/round_chevron_right_24" />
</RelativeLayout> </RelativeLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:visibility="gone"
android:paddingStart="8dp"
android:id="@+id/special_weather">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:id="@+id/divider3"
android:text="@string/divider"
android:includeFontPadding="false"
style="@style/AnotherWidget.Widget.Subtitle"/>
<ImageView
android:layout_width="28dp"
android:layout_height="28dp"
android:paddingEnd="4dp"
android:paddingStart="4dp"
android:layout_marginEnd="4dp"
android:id="@+id/special_weather_icon"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/AnotherWidget.Widget.Date.Big"
android:maxLines="1"
android:includeFontPadding="false"
android:id="@+id/special_temp"/>
</LinearLayout>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="4dp" android:layout_height="4dp"
android:visibility="gone" android:visibility="gone"
android:orientation="horizontal" android:orientation="horizontal"
android:id="@+id/second_row_top_margin_small" /> android:id="@+id/sub_line_top_margin_small" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="8dp" android:layout_height="8dp"
android:visibility="gone" android:visibility="gone"
android:orientation="horizontal" android:orientation="horizontal"
android:id="@+id/second_row_top_margin_medium" /> android:id="@+id/sub_line_top_margin_medium" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="12dp" android:layout_height="12dp"
android:visibility="gone" android:visibility="gone"
android:orientation="horizontal" android:orientation="horizontal"
android:id="@+id/second_row_top_margin_large" /> android:id="@+id/sub_line_top_margin_large" />
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:baselineAligned="false"
android:layout_gravity="center"
android:clipChildren="false" android:clipChildren="false"
android:clipToPadding="false" android:clipToPadding="false"
android:layoutDirection="locale" android:layoutDirection="locale"
@ -194,7 +166,8 @@
android:layout_weight="1" android:layout_weight="1"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical" android:gravity="center_vertical"
android:id="@+id/second_row" android:id="@+id/sub_line"
android:visibility="gone"
android:orientation="horizontal"> android:orientation="horizontal">
<RelativeLayout <RelativeLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -207,18 +180,18 @@
android:layout_height="16dp" android:layout_height="16dp"
android:cropToPadding="false" android:cropToPadding="false"
android:clipChildren="false" android:clipChildren="false"
android:id="@+id/second_row_icon_shadow" android:id="@+id/sub_line_icon_shadow"
android:src="@drawable/round_today_24"/> android:src="@drawable/round_today_24"/>
<ImageView <ImageView
android:layout_width="16dp" android:layout_width="16dp"
android:layout_height="16dp" android:layout_height="16dp"
android:cropToPadding="false" android:cropToPadding="false"
android:clipChildren="false" android:clipChildren="false"
android:id="@+id/second_row_icon" android:id="@+id/sub_line_icon"
android:src="@drawable/round_today_24"/> android:src="@drawable/round_today_24"/>
</RelativeLayout> </RelativeLayout>
<TextView <TextView
android:id="@+id/next_event_date" android:id="@+id/sub_line_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:ellipsize="end" android:ellipsize="end"
android:lines="1" android:lines="1"
@ -230,42 +203,33 @@
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:visibility="gone" android:visibility="gone"
android:clipChildren="false" android:layout_marginStart="4dp"
android:clipToPadding="false" android:id="@+id/weather_sub_line">
android:layout_marginStart="8dp"
android:id="@+id/calendar_weather">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:id="@+id/divider2" android:id="@+id/weather_sub_line_divider"
android:text="@string/divider" android:text="@string/divider"
android:includeFontPadding="false" android:includeFontPadding="false"
style="@style/AnotherWidget.Widget.Subtitle"/> style="@style/AnotherWidget.Widget.Subtitle"/>
<ImageView <ImageView
android:layout_width="18dp" android:layout_width="20dp"
android:layout_height="18dp" android:layout_height="20dp"
android:id="@+id/weather_icon" android:id="@+id/weather_sub_line_weather_icon"
android:clipChildren="false" android:layout_marginStart="4dp"
android:clipToPadding="false" android:layout_marginEnd="8dp"/>
android:adjustViewBounds="true"
android:layout_marginEnd="2dp"
android:layout_marginStart="2dp"
android:src="@drawable/clear_night"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
style="@style/AnotherWidget.Widget.Date" style="@style/AnotherWidget.Widget.Date.Big"
android:layout_marginStart="8dp" android:maxLines="1"
android:ellipsize="marquee"
android:layout_marginEnd="4dp"
android:includeFontPadding="false" android:includeFontPadding="false"
android:id="@+id/calendar_temp"/> android:id="@+id/weather_sub_line_temperature"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>

View File

@ -74,40 +74,48 @@
<RelativeLayout <RelativeLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:layout_centerInParent="true"
android:id="@+id/bitmap_container"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_centerInParent="true"
android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:alpha="0" android:alpha="0"
android:layout_centerHorizontal="true" android:visibility="gone"
android:orientation="horizontal" android:orientation="horizontal"
android:layoutDirection="locale" android:layoutDirection="locale"
android:id="@+id/empty_layout_rect"> android:id="@+id/first_line_rect">
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/empty_date_rect"/> android:id="@+id/date_rect"/>
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone"
android:id="@+id/weather_rect" /> android:id="@+id/weather_rect" />
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerHorizontal="true"
android:id="@+id/calendar_layout_rect"
android:alpha="0"
android:gravity="center">
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layoutDirection="locale" android:layoutDirection="locale"
android:visibility="gone"
android:id="@+id/calendar_layout_rect"
android:orientation="horizontal"> android:orientation="horizontal">
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:id="@+id/action_previous_rect" /> android:id="@+id/action_previous_rect" />
<ImageView <ImageView
@ -118,35 +126,33 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone"
android:id="@+id/next_event_difference_time_rect" /> android:id="@+id/next_event_difference_time_rect" />
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:id="@+id/action_next_rect" /> android:id="@+id/action_next_rect" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/special_weather_rect" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="4dp" android:layout_height="4dp"
android:visibility="gone" android:visibility="gone"
android:orientation="horizontal" android:orientation="horizontal"
android:id="@+id/second_row_top_margin_small_sans" /> android:id="@+id/sub_line_top_margin_small_sans" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="8dp" android:layout_height="8dp"
android:visibility="gone" android:visibility="gone"
android:orientation="horizontal" android:orientation="horizontal"
android:id="@+id/second_row_top_margin_medium_sans" /> android:id="@+id/sub_line_top_margin_medium_sans" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="12dp" android:layout_height="12dp"
android:visibility="gone" android:visibility="gone"
android:orientation="horizontal" android:orientation="horizontal"
android:id="@+id/second_row_top_margin_large_sans" /> android:id="@+id/sub_line_top_margin_large_sans" />
<LinearLayout <LinearLayout
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -162,7 +168,7 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/second_row_rect" /> android:id="@+id/sub_line_rect" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
@ -172,17 +178,11 @@
<ImageView <ImageView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/calendar_weather_rect" /> android:visibility="gone"
android:id="@+id/weather_sub_line_rect" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
android:id="@+id/bitmap_container"/>
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>

View File

@ -37,6 +37,10 @@
<string name="font_700">Grassetto</string> <string name="font_700">Grassetto</string>
<string name="font_800">Nero</string> <string name="font_800">Nero</string>
<string name="font_900">Molto nero</string> <string name="font_900">Molto nero</string>
<string name="settings_widget_align_title">Allineamento widget</string>
<string name="settings_widget_align_left_subtitle">Sinistra</string>
<string name="settings_widget_align_right_subtitle">Destra</string>
<string name="settings_widget_align_center_subtitle">Centro</string>
<!-- Calendar --> <!-- Calendar -->
<string name="settings_calendar_title">Calendario</string> <string name="settings_calendar_title">Calendario</string>

View File

@ -31,6 +31,10 @@
<string name="settings_secondary_row_top_margin_title">Rows spacing</string> <string name="settings_secondary_row_top_margin_title">Rows spacing</string>
<string name="action_custom_font_to_search">Custom font…</string> <string name="action_custom_font_to_search">Custom font…</string>
<string name="font_family_settings_title">Font family</string> <string name="font_family_settings_title">Font family</string>
<string name="settings_widget_align_title">Widget align</string>
<string name="settings_widget_align_left_subtitle">Left</string>
<string name="settings_widget_align_right_subtitle">Right</string>
<string name="settings_widget_align_center_subtitle">Center</string>
<string name="font_100" translatable="false">Thin</string> <string name="font_100" translatable="false">Thin</string>
<string name="font_200" translatable="false">Light</string> <string name="font_200" translatable="false">Light</string>

View File

@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.4.21' ext.kotlin_version = '1.4.32'
repositories { repositories {
google() google()
jcenter() jcenter()
@ -10,14 +10,14 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.1.2' classpath 'com.android.tools.build:gradle:4.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.4' classpath 'com.google.gms:google-services:4.3.5'
// Add the Crashlytics Gradle plugin. // Add the Crashlytics Gradle plugin.
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.5.2'
classpath 'io.realm:realm-gradle-plugin:6.0.2' classpath 'io.realm:realm-gradle-plugin:10.4.0'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files