diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 9aff3fb..64d3a40 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/app/build.gradle b/app/build.gradle index ad1ed4b..89b5c2b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -65,14 +65,14 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 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.espresso:espresso-core:3.3.0' // UI implementation 'androidx.appcompat:appcompat:1.2.0' 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 'net.idik:slimadapter:2.1.2' implementation 'com.google.android:flexbox:2.0.1' @@ -80,17 +80,17 @@ dependencies { // Lifecycle 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.work:work-runtime-ktx:2.4.0" + implementation "androidx.work:work-runtime-ktx:2.5.0" // EventBus implementation 'org.greenrobot:eventbus:3.2.0' // Navigation - implementation 'androidx.navigation:navigation-fragment-ktx:2.3.2' - implementation 'androidx.navigation:navigation-ui-ktx:2.3.2' + implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5' + implementation 'androidx.navigation:navigation-ui-ktx:2.3.5' // Other implementation 'androidx.multidex:multidex:2.0.1' @@ -99,24 +99,24 @@ dependencies { implementation 'com.github.warkiz.widget:indicatorseekbar:2.1.2' //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' // Fitness 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 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 - implementation 'com.android.billingclient:billing:3.0.2' - implementation 'com.android.billingclient:billing-ktx:3.0.2' + implementation 'com.android.billingclient:billing:3.0.3' + implementation 'com.android.billingclient:billing-ktx:3.0.3' // KTX 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.core:core-ktx:1.3.2' @@ -128,14 +128,14 @@ dependencies { implementation "com.github.haroldadmin:NetworkResponseAdapter:4.0.1" //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. - implementation 'com.google.firebase:firebase-crashlytics:17.3.0' + implementation 'com.google.firebase:firebase-crashlytics:17.4.1' // Preferences - implementation 'com.chibatching.kotpref:kotpref:2.11.0' - implementation 'com.chibatching.kotpref:livedata-support:2.10.0' + implementation 'com.chibatching.kotpref:kotpref:2.13.1' + implementation 'com.chibatching.kotpref:livedata-support:2.13.1' implementation 'androidx.preference:preference-ktx:1.1.1' // Permissions diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/components/GlanceSettingsDialog.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/components/GlanceSettingsDialog.kt index bde5deb..dc94327 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/components/GlanceSettingsDialog.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/components/GlanceSettingsDialog.kt @@ -8,9 +8,7 @@ import android.content.Intent import android.content.pm.PackageManager import android.os.Build import android.view.LayoutInflater -import android.view.View 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.GoogleSignInAccount 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 { val dialog = BottomSheetMenu(context, header = context.getString(R.string.glance_notification_hide_timeout_title)).setSelectedValue(Preferences.hideNotificationAfter) Constants.GlanceNotificationTimer.values().forEachIndexed { index, timeout -> - dialog.addItem(stringArray[index], timeout.value) + dialog.addItem(stringArray[index], timeout.rawValue) } dialog.addOnSelectItemListener { value -> Preferences.hideNotificationAfter = value diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/components/IconPackSelector.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/components/IconPackSelector.kt index adbf455..476cc0c 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/components/IconPackSelector.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/components/IconPackSelector.kt @@ -2,7 +2,6 @@ package com.tommasoberlose.anotherwidget.components import android.content.Context import android.view.LayoutInflater -import android.view.View import android.widget.ImageView import androidx.core.content.ContextCompat import androidx.core.view.isVisible @@ -28,13 +27,13 @@ class IconPackSelector(context: Context, private val header: String? = null) : B // Menu for (item in Constants.WeatherIconPack.values()) { val itemBinding = IconPackMenuItemBinding.inflate(LayoutInflater.from(context)) - itemBinding.label.text = context.getString(R.string.settings_weather_icon_pack_default).format(item.value + 1) - itemBinding.root.isSelected = item.value == Preferences.weatherIconPack + itemBinding.label.text = context.getString(R.string.settings_weather_icon_pack_default).format(item.rawValue + 1) + itemBinding.root.isSelected = item.rawValue == Preferences.weatherIconPack - itemBinding.icon1.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "01d", item.value))) - itemBinding.icon2.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "01n", item.value))) - itemBinding.icon3.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "10d", item.value))) - itemBinding.icon4.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "09n", 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.rawValue))) + itemBinding.icon3.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "10d", item.rawValue))) + itemBinding.icon4.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "09n", item.rawValue))) listOf(itemBinding.icon1, itemBinding.icon2, itemBinding.icon3, itemBinding.icon4).forEach { if (item == Constants.WeatherIconPack.MINIMAL) { @@ -45,7 +44,7 @@ class IconPackSelector(context: Context, private val header: String? = null) : B } itemBinding.root.setOnClickListener { - Preferences.weatherIconPack = item.value + Preferences.weatherIconPack = item.rawValue this.dismiss() } binding.menu.addView(itemBinding.root) diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/global/Constants.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/global/Constants.kt index 8bc81ab..a4eab88 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/global/Constants.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/global/Constants.kt @@ -1,7 +1,5 @@ package com.tommasoberlose.anotherwidget.global -import java.text.SimpleDateFormat - object Constants { const val RESULT_CODE_CUSTOM_LOCATION = 45 const val RESULT_APP_NAME = "RESULT_APP_NAME" @@ -11,14 +9,14 @@ object Constants { const val CUSTOM_FONT_DOWNLOADED = 2 const val CUSTOM_FONT_DOWNLOAD_NEW = 3 - enum class ClockBottomMargin(val value: Int) { + enum class ClockBottomMargin(val rawValue: Int) { NONE(0), SMALL(1), MEDIUM(2), LARGE(3) } - enum class SecondRowTopMargin(val value: Int) { + enum class SecondRowTopMargin(val rawValue: Int) { NONE(0), SMALL(1), MEDIUM(2), @@ -41,13 +39,13 @@ object Constants { } } - enum class WidgetUpdateFrequency(val value: Int) { + enum class WidgetUpdateFrequency(val rawValue: Int) { LOW(0), DEFAULT(1), HIGH(2) } - enum class WeatherProvider(val value: Int) { + enum class WeatherProvider(val rawValue: Int) { OPEN_WEATHER(0), WEATHER_BIT(1), WEATHER_API(2), @@ -57,12 +55,12 @@ object Constants { YR(6); companion object { - private val map = WeatherProvider.values().associateBy(WeatherProvider::value) + private val map = WeatherProvider.values().associateBy(WeatherProvider::rawValue) fun fromInt(type: Int) = map[type] } } - enum class GlanceNotificationTimer(val value: Int) { + enum class GlanceNotificationTimer(val rawValue: Int) { HALF_MINUTE(0), ONE_MINUTE(1), FIVE_MINUTES(2), @@ -71,15 +69,21 @@ object Constants { WHEN_DISMISSED(5); companion object { - private val map = values().associateBy(GlanceNotificationTimer::value) + private val map = values().associateBy(GlanceNotificationTimer::rawValue) fun fromInt(type: Int) = map[type] } } - enum class WeatherIconPack(val value: Int) { + enum class WeatherIconPack(val rawValue: Int) { DEFAULT(0), MINIMAL(1), COOL(2), GOOGLE_NEWS(3) } + + enum class WidgetAlign(val rawValue: Int) { + LEFT(0), + RIGHT(1), + CENTER(2) + } } \ No newline at end of file diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/global/Preferences.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/global/Preferences.kt index 289b9d4..ac21240 100755 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/global/Preferences.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/global/Preferences.kt @@ -1,13 +1,11 @@ package com.tommasoberlose.anotherwidget.global -import android.os.Build import androidx.appcompat.app.AppCompatDelegate.* import androidx.core.os.ConfigurationCompat import com.chibatching.kotpref.KotprefModel import com.tommasoberlose.anotherwidget.helpers.IntentHelper import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper import com.tommasoberlose.anotherwidget.utils.isMetric -import java.util.* object Preferences : KotprefModel() { override val commitAllPropertiesByDefault: Boolean = true @@ -48,14 +46,14 @@ object Preferences : KotprefModel() { var weatherProviderApiWeatherApi by stringPref(default = "") var weatherProviderApiWeatherBit 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 weatherProviderLocationError by stringPref(default = "") var eventAppName by stringPref(key = "PREF_EVENT_APP_NAME", default = "") var eventAppPackage by stringPref(key = "PREF_EVENT_APP_PACKAGE", default = "") 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 textGlobalAlpha by stringPref(default = "FF") @@ -84,14 +82,14 @@ object Preferences : KotprefModel() { 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 var textMainSize by floatPref(key = "PREF_TEXT_MAIN_SIZE", default = 26f) var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 18f) var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 90f) - var clockBottomMargin by intPref(default = Constants.ClockBottomMargin.MEDIUM.value) - var secondRowTopMargin by intPref(default = Constants.SecondRowTopMargin.NONE.value) + var clockBottomMargin by intPref(default = Constants.ClockBottomMargin.MEDIUM.rawValue) + var secondRowTopMargin by intPref(default = Constants.SecondRowTopMargin.NONE.rawValue) var showClock by booleanPref(key = "PREF_SHOW_CLOCK", default = false) var clockAppName by stringPref(key = "PREF_CLOCK_APP_NAME", 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 widgetAlign by intPref(default = Constants.WidgetAlign.CENTER.rawValue) + // Settings var showWallpaper by booleanPref(default = true) var showPreview by booleanPref(default = true) @@ -127,7 +127,7 @@ object Preferences : KotprefModel() { var showDailySteps by booleanPref(default = false) var showGreetings 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 lastNotificationTitle by stringPref(default = "") diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt index f80505c..5e38c04 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt @@ -96,13 +96,13 @@ object SettingsStringHelper { difference <= 0 -> { 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() } - 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() } - 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) } TimeUnit.MILLISECONDS.toHours(difference) < 1 -> { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/WeatherHelper.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/WeatherHelper.kt index 59241ba..26b3ce7 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/WeatherHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/WeatherHelper.kt @@ -2,23 +2,15 @@ package com.tommasoberlose.anotherwidget.helpers import android.Manifest import android.content.Context -import android.os.Build -import android.util.Log import com.chibatching.kotpref.Kotpref -import com.google.android.gms.location.LocationServices import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi import com.tommasoberlose.anotherwidget.services.LocationService -import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission 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) { "01d" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.clear_day_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.clear_day_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.clear_day_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.clear_day_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.clear_day_2 + 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 } } "02d" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.partly_cloudy_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.partly_cloudy_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.partly_cloudy_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.partly_cloudy_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.partly_cloudy_2 + 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 } } "03d" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.mostly_cloudy_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.mostly_cloudy_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.mostly_cloudy_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.mostly_cloudy_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.mostly_cloudy_2 + 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 } } "04d" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.cloudy_weather_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.cloudy_weather_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.cloudy_weather_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.cloudy_weather_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.cloudy_weather_2 + 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 } } "09d" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.storm_weather_day_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.storm_weather_day_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.storm_weather_day_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.storm_weather_day_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.storm_weather_day_2 + 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 } } "10d" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.rainy_day_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rainy_day_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rainy_day_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.rainy_day_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.rainy_day_2 + 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 } } "11d" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.thunder_day_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.thunder_day_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.thunder_day_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.thunder_day_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.thunder_day_2 + 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 } } "13d" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.snow_day_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.snow_day_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.snow_day_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.snow_day_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.snow_day_2 + 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 } } "50d" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.haze_day_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_day_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_day_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.haze_day_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.haze_day_2 + 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 } } "80d" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.windy_day_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.windy_day_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.windy_day_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.windy_day_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.windy_day_2 + 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 } } "81d" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.rain_snow_day_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rain_snow_day_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rain_snow_day_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.rain_snow_day_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.rain_snow_day_2 + 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 } } "82d" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.haze_weather_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_weather_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_weather_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.haze_weather_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.haze_weather_2 + 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 } } @@ -221,97 +213,97 @@ object WeatherHelper { "01n" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.clear_night_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.clear_night_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.clear_night_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.clear_night_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.clear_night_2 + 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 } } "02n" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.partly_cloudy_night_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.partly_cloudy_night_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.partly_cloudy_night_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.partly_cloudy_night_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.partly_cloudy_night_2 + 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 } } "03n" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.mostly_cloudy_night_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.mostly_cloudy_night_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.mostly_cloudy_night_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.mostly_cloudy_night_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.mostly_cloudy_night_2 + 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 } } "04n" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.cloudy_weather_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.cloudy_weather_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.cloudy_weather_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.cloudy_weather_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.cloudy_weather_2 + 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 } } "09n" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.storm_weather_night_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.storm_weather_night_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.storm_weather_night_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.storm_weather_night_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.storm_weather_night_2 + 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 } } "10n" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.rainy_night_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rainy_night_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rainy_night_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.rainy_night_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.rainy_night_2 + 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 } } "11n" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.thunder_night_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.thunder_night_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.thunder_night_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.thunder_night_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.thunder_night_2 + 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 } } "13n" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.snow_night_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.snow_night_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.snow_night_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.snow_night_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.snow_night_2 + 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 } } "50n" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.haze_night_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_night_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_night_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.haze_night_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.haze_night_2 + 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 } } "80n" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.windy_night_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.windy_night_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.windy_night_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.windy_night_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.windy_night_2 + 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 } } "81n" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.rain_snow_night_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rain_snow_night_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rain_snow_night_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.rain_snow_night_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.rain_snow_night_2 + 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 } } "82n" -> { when (style) { - Constants.WeatherIconPack.COOL.value -> R.drawable.haze_weather_3 - Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_weather_2 - Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_weather_4 + Constants.WeatherIconPack.COOL.rawValue -> R.drawable.haze_weather_3 + Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.haze_weather_2 + 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 } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt index 73c458d..36330f4 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt @@ -5,9 +5,6 @@ import android.app.PendingIntent import android.content.BroadcastReceiver import android.content.Context 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.global.Actions import com.tommasoberlose.anotherwidget.global.Constants @@ -110,7 +107,7 @@ class UpdatesReceiver : BroadcastReceiver() { if (diff.hours == 0) { var minutes = 0 when (Preferences.widgetUpdateFrequency) { - Constants.WidgetUpdateFrequency.DEFAULT.value -> { + Constants.WidgetUpdateFrequency.DEFAULT.rawValue -> { minutes = when { diff.minutes > 50 -> 50 diff.minutes > 30 -> 30 @@ -118,7 +115,7 @@ class UpdatesReceiver : BroadcastReceiver() { else -> 0 } } - Constants.WidgetUpdateFrequency.HIGH.value -> { + Constants.WidgetUpdateFrequency.HIGH.rawValue -> { minutes = diff.minutes - (diff.minutes % 5) } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/tabs/WeatherProviderActivity.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/tabs/WeatherProviderActivity.kt index 544334f..ec5297a 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/tabs/WeatherProviderActivity.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/tabs/WeatherProviderActivity.kt @@ -47,12 +47,12 @@ class WeatherProviderActivity : AppCompatActivity() { injector .text(R.id.text, WeatherHelper.getProviderName(this, provider)) .clicked(R.id.item) { - if (Preferences.weatherProvider != provider.value) { + if (Preferences.weatherProvider != provider.rawValue) { Preferences.weatherProviderError = "-" Preferences.weatherProviderLocationError = "" } val oldValue = Preferences.weatherProvider - Preferences.weatherProvider = provider.value + Preferences.weatherProvider = provider.rawValue updateListItem(oldValue) updateListItem() binding.loader.isVisible = true @@ -62,12 +62,12 @@ class WeatherProviderActivity : AppCompatActivity() { } } .clicked(R.id.radioButton) { - if (Preferences.weatherProvider != provider.value) { + if (Preferences.weatherProvider != provider.rawValue) { Preferences.weatherProviderError = "-" Preferences.weatherProviderLocationError = "" } val oldValue = Preferences.weatherProvider - Preferences.weatherProvider = provider.value + Preferences.weatherProvider = provider.rawValue updateListItem(oldValue) updateListItem() binding.loader.isVisible = true @@ -76,7 +76,7 @@ class WeatherProviderActivity : AppCompatActivity() { WeatherHelper.updateWeather(this@WeatherProviderActivity) } } - .checked(R.id.radioButton, provider.value == Preferences.weatherProvider) + .checked(R.id.radioButton, provider.rawValue == Preferences.weatherProvider) .with(R.id.text2) { if (WeatherHelper.isKeyRequired(provider)) { it.text = getString(R.string.api_key_required_message) @@ -98,14 +98,14 @@ class WeatherProviderActivity : AppCompatActivity() { } }.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(R.id.provider_error) { if (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-") { it.text = Preferences.weatherProviderError - it.isVisible = provider.value == Preferences.weatherProvider + it.isVisible = provider.rawValue == Preferences.weatherProvider } else if (Preferences.weatherProviderLocationError != "") { it.text = Preferences.weatherProviderLocationError - it.isVisible = provider.value == Preferences.weatherProvider + it.isVisible = provider.rawValue == Preferences.weatherProvider } else { it.isVisible = false } @@ -137,7 +137,7 @@ class WeatherProviderActivity : AppCompatActivity() { private fun updateListItem(provider: Int = Preferences.weatherProvider) { (adapter.data).forEachIndexed { index, item -> - if (item is Constants.WeatherProvider && item.value == provider) { + if (item is Constants.WeatherProvider && item.rawValue == provider) { adapter.notifyItemChanged(index) } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/MainFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/MainFragment.kt index 0bae616..048acf8 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/MainFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/MainFragment.kt @@ -1,9 +1,7 @@ package com.tommasoberlose.anotherwidget.ui.fragments -import android.Manifest import android.animation.ValueAnimator import android.content.Intent -import android.content.SharedPreferences import android.net.Uri import android.os.Build import android.os.Bundle @@ -14,23 +12,14 @@ import android.util.TypedValue import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.FrameLayout import android.widget.RelativeLayout -import androidx.core.animation.addListener -import androidx.core.app.NotificationManagerCompat import androidx.core.content.ContextCompat import androidx.core.view.isVisible import androidx.fragment.app.Fragment -import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope -import androidx.navigation.NavController import androidx.navigation.Navigation -import androidx.navigation.fragment.FragmentNavigatorExtras 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.tommasoberlose.anotherwidget.R 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.helpers.* 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.adapters.ViewPagerAdapter import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget +import com.tommasoberlose.anotherwidget.ui.widgets.StandardWidget import com.tommasoberlose.anotherwidget.utils.* import kotlinx.coroutines.* import org.greenrobot.eventbus.EventBus @@ -54,7 +42,7 @@ class MainFragment : Fragment() { companion object { 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 @@ -164,6 +152,10 @@ class MainFragment : Fragment() { binding.toolbar.cardElevation = if (it > 0) 24f else 0f } + viewModel.widgetAlign.observe(viewLifecycleOwner) { + updatePreviewVisibility() + } + viewModel.showPreview.observe(viewLifecycleOwner) { updatePreviewVisibility() } @@ -209,7 +201,7 @@ class MainFragment : Fragment() { WidgetHelper.runWithCustomTypeface(requireContext()) { typeface -> uiJob = lifecycleScope.launch(Dispatchers.IO) { - val generatedView = MainWidget.generateWidgetView(requireContext(), typeface).root + val generatedView = MainWidget.getWidgetView(requireContext(), typeface).root withContext(Dispatchers.Main) { generatedView.measure(0, 0) @@ -252,13 +244,13 @@ class MainFragment : Fragment() { // Clock bottom margin binding.widgetDetail.clockBottomMarginNone.isVisible = - Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value + Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.rawValue binding.widgetDetail.clockBottomMarginSmall.isVisible = - Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value + Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.rawValue binding.widgetDetail.clockBottomMarginMedium.isVisible = - Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value + Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.rawValue binding.widgetDetail.clockBottomMarginLarge.isVisible = - Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value + Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.rawValue } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/CalendarFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/CalendarFragment.kt index 3b23956..1b0ac73 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/CalendarFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/CalendarFragment.kt @@ -1,19 +1,14 @@ package com.tommasoberlose.anotherwidget.ui.fragments.tabs import android.Manifest -import android.app.Activity -import android.content.Intent import android.os.Bundle import android.provider.CalendarContract import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment -import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope -import com.chibatching.kotpref.bulk import com.google.android.material.transition.MaterialSharedAxis import com.tommasoberlose.anotherwidget.R 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.global.Constants 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.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.helpers.CalendarHelper -import com.tommasoberlose.anotherwidget.helpers.IntentHelper import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission -import com.tommasoberlose.anotherwidget.utils.isDefaultSet import com.tommasoberlose.anotherwidget.utils.toast import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import kotlin.Comparator class CalendarFragment : Fragment() { @@ -110,9 +100,9 @@ class CalendarFragment : Fragment() { viewModel.widgetUpdateFrequency.observe(viewLifecycleOwner) { maintainScrollPosition { binding.widgetUpdateFrequencyLabel.text = when (it) { - Constants.WidgetUpdateFrequency.HIGH.value -> getString(R.string.settings_widget_update_frequency_high) - Constants.WidgetUpdateFrequency.DEFAULT.value -> getString(R.string.settings_widget_update_frequency_default) - Constants.WidgetUpdateFrequency.LOW.value -> getString(R.string.settings_widget_update_frequency_low) + Constants.WidgetUpdateFrequency.HIGH.rawValue -> getString(R.string.settings_widget_update_frequency_high) + Constants.WidgetUpdateFrequency.DEFAULT.rawValue -> getString(R.string.settings_widget_update_frequency_default) + Constants.WidgetUpdateFrequency.LOW.rawValue -> getString(R.string.settings_widget_update_frequency_low) else -> "" } } @@ -244,9 +234,9 @@ class CalendarFragment : Fragment() { binding.actionWidgetUpdateFrequency.setOnClickListener { if (Preferences.showEvents && Preferences.showDiffTime) { BottomSheetMenu(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_default), Constants.WidgetUpdateFrequency.DEFAULT.value) - .addItem(getString(R.string.settings_widget_update_frequency_low), Constants.WidgetUpdateFrequency.LOW.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.rawValue) + .addItem(getString(R.string.settings_widget_update_frequency_low), Constants.WidgetUpdateFrequency.LOW.rawValue) .addOnSelectItemListener { value -> Preferences.widgetUpdateFrequency = value }.show() diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/LayoutFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/LayoutFragment.kt index c19a10d..8df929f 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/LayoutFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/LayoutFragment.kt @@ -1,17 +1,14 @@ package com.tommasoberlose.anotherwidget.ui.fragments.tabs import android.annotation.SuppressLint -import android.content.Intent import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment -import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope -import com.chibatching.kotpref.blockingBulk import com.google.android.material.transition.MaterialSharedAxis import com.tommasoberlose.anotherwidget.R 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.toHexValue 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.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.utils.isDarkTheme @@ -31,7 +26,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import java.util.* class LayoutFragment : Fragment() { @@ -94,20 +88,31 @@ class LayoutFragment : Fragment() { viewModel.secondRowTopMargin.observe(viewLifecycleOwner) { maintainScrollPosition { binding.secondRowTopMarginLabel.text = when (it) { - Constants.SecondRowTopMargin.NONE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_none) - Constants.SecondRowTopMargin.SMALL.value -> getString(R.string.settings_clock_bottom_margin_subtitle_small) - Constants.SecondRowTopMargin.LARGE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_large) + Constants.SecondRowTopMargin.NONE.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_none) + Constants.SecondRowTopMargin.SMALL.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_small) + Constants.SecondRowTopMargin.LARGE.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_large) 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) { maintainScrollPosition { binding.clockBottomMarginLabel.text = when (it) { - Constants.ClockBottomMargin.NONE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_none) - Constants.ClockBottomMargin.SMALL.value -> getString(R.string.settings_clock_bottom_margin_subtitle_small) - Constants.ClockBottomMargin.LARGE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_large) + Constants.ClockBottomMargin.NONE.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_none) + Constants.ClockBottomMargin.SMALL.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_small) + Constants.ClockBottomMargin.LARGE.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_large) else -> getString(R.string.settings_clock_bottom_margin_subtitle_medium) } } @@ -115,7 +120,7 @@ class LayoutFragment : Fragment() { viewModel.backgroundCardColor.observe(viewLifecycleOwner) { maintainScrollPosition { - if (Preferences.backgroundCardAlpha == "00") { + if (ColorHelper.getBackgroundAlpha(requireActivity().isDarkTheme()) == 0) { binding.backgroundColorLabel.text = getString(R.string.transparent) } else { binding.backgroundColorLabel.text = @@ -141,19 +146,19 @@ class LayoutFragment : Fragment() { ).setSelectedValue(Preferences.secondRowTopMargin) .addItem( getString(R.string.settings_clock_bottom_margin_subtitle_none), - Constants.SecondRowTopMargin.NONE.value + Constants.SecondRowTopMargin.NONE.rawValue ) .addItem( getString(R.string.settings_clock_bottom_margin_subtitle_small), - Constants.SecondRowTopMargin.SMALL.value + Constants.SecondRowTopMargin.SMALL.rawValue ) .addItem( getString(R.string.settings_clock_bottom_margin_subtitle_medium), - Constants.SecondRowTopMargin.MEDIUM.value + Constants.SecondRowTopMargin.MEDIUM.rawValue ) .addItem( getString(R.string.settings_clock_bottom_margin_subtitle_large), - Constants.SecondRowTopMargin.LARGE.value + Constants.SecondRowTopMargin.LARGE.rawValue ) .addOnSelectItemListener { value -> Preferences.secondRowTopMargin = value @@ -167,25 +172,47 @@ class LayoutFragment : Fragment() { ).setSelectedValue(Preferences.clockBottomMargin) .addItem( getString(R.string.settings_clock_bottom_margin_subtitle_none), - Constants.ClockBottomMargin.NONE.value + Constants.ClockBottomMargin.NONE.rawValue ) .addItem( getString(R.string.settings_clock_bottom_margin_subtitle_small), - Constants.ClockBottomMargin.SMALL.value + Constants.ClockBottomMargin.SMALL.rawValue ) .addItem( getString(R.string.settings_clock_bottom_margin_subtitle_medium), - Constants.ClockBottomMargin.MEDIUM.value + Constants.ClockBottomMargin.MEDIUM.rawValue ) .addItem( getString(R.string.settings_clock_bottom_margin_subtitle_large), - Constants.ClockBottomMargin.LARGE.value + Constants.ClockBottomMargin.LARGE.rawValue ) .addOnSelectItemListener { value -> Preferences.clockBottomMargin = value }.show() } + binding.actionWidgetAlign.setOnClickListener { + BottomSheetMenu( + 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 { BottomSheetColorPicker(requireContext(), colors = colors, diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/viewmodels/MainViewModel.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/viewmodels/MainViewModel.kt index 42dab9d..915f85a 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/viewmodels/MainViewModel.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/viewmodels/MainViewModel.kt @@ -49,6 +49,7 @@ class MainViewModel(context: Application) : AndroidViewModel(context) { val secondRowInformation = Preferences.asLiveData(Preferences::secondRowInformation) val showDividers = Preferences.asLiveData(Preferences::showDividers) val secondRowTopMargin = Preferences.asLiveData(Preferences::secondRowTopMargin) + val widgetAlign = Preferences.asLiveData(Preferences::widgetAlign) // Calendar Settings val showEvents = Preferences.asLiveData(Preferences::showEvents) diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/ClockWidget.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/ClockWidget.kt new file mode 100644 index 0000000..6433989 --- /dev/null +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/ClockWidget.kt @@ -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 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/LeftAlignedWidget.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/LeftAlignedWidget.kt new file mode 100644 index 0000000..7a28fc2 --- /dev/null +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/LeftAlignedWidget.kt @@ -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( + bindingView.date, + bindingView.weatherDateLineTemperature, + bindingView.nextEvent, + bindingView.nextEventDifferenceTime, + ).forEach { + it.setTextColor(ColorHelper.getFontColor(context.applicationContext.isDarkTheme())) + } + + if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.rawValue) { + listOf(bindingView.actionNext) + } else { + listOf( + 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(bindingView.subLineText, bindingView.weatherSubLineDivider, bindingView.weatherSubLineTemperature).forEach { + it.setTextColor(ColorHelper.getSecondaryFontColor(context.applicationContext.isDarkTheme())) + } + + if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.rawValue) { + listOf(bindingView.subLineIcon, bindingView.subLineIconShadow) + } else { + listOf(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>( + 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( + 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( + 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( + 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 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/MainWidget.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/MainWidget.kt index c797dcc..adb1dcc 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/MainWidget.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/MainWidget.kt @@ -7,13 +7,11 @@ import android.appwidget.AppWidgetProvider import android.content.ComponentName import android.content.Context import android.content.Intent -import android.content.IntentSender import android.content.res.Resources import android.graphics.Color import android.graphics.Typeface import android.os.Bundle import android.text.format.DateUtils -import android.util.Log import android.util.TypedValue import android.view.LayoutInflater import android.view.View @@ -23,8 +21,9 @@ import android.widget.RemoteViews import android.widget.TextView import androidx.core.content.ContextCompat import androidx.core.view.isVisible -import com.google.gson.Gson +import androidx.viewbinding.ViewBinding import com.tommasoberlose.anotherwidget.R +import com.tommasoberlose.anotherwidget.databinding.LeftAlignedWidgetBinding import com.tommasoberlose.anotherwidget.databinding.TheWidgetBinding import com.tommasoberlose.anotherwidget.db.EventRepository import com.tommasoberlose.anotherwidget.global.Actions @@ -98,991 +97,21 @@ class MainWidget : AppWidgetProvider() { val dimensions = WidgetHelper.WidgetSizeProvider(context, appWidgetManager).getWidgetsSize(appWidgetId) WidgetHelper.runWithCustomTypeface(context) { - generateWidgetView(context, appWidgetId, appWidgetManager, min(dimensions.first - 8.toPixel(context), min(width, height) - 16.toPixel(context)), it) + val views = when (Preferences.widgetAlign) { + Constants.WidgetAlign.LEFT.rawValue -> LeftAlignedWidget(context).generateWidget(appWidgetId, min(dimensions.first - 8.toPixel(context), min(width, height) - 16.toPixel(context)), it) + Constants.WidgetAlign.RIGHT.rawValue -> LeftAlignedWidget(context).generateWidget(appWidgetId, min(dimensions.first - 8.toPixel(context), min(width, height) - 16.toPixel(context)), it) + else -> StandardWidget(context).generateWidget(appWidgetId, min(dimensions.first - 8.toPixel(context), min(width, height) - 16.toPixel(context)), it) + } + appWidgetManager.updateAppWidget(appWidgetId, views) } } - private fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int, typeface: Typeface? = null) { - - 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) + fun getWidgetView(context: Context, typeface: Typeface?): ViewBinding { + return when (Preferences.widgetAlign) { + Constants.WidgetAlign.LEFT.rawValue -> LeftAlignedWidget(context).generateWidgetView(typeface) + Constants.WidgetAlign.RIGHT.rawValue -> LeftAlignedWidget(context).generateWidgetView(typeface) + else -> StandardWidget(context).generateWidgetView(typeface) } - - // Clock - views = updateClockView(context, views, appWidgetId) - - // Setup listener - try { - - val generatedBinding = generateWidgetView(context, typeface) - views.setImageViewBitmap( - R.id.bitmap_container, - BitmapHelper.getBitmapFromView(generatedBinding.root, width = w) - ) - views = updateCalendarView(context, generatedBinding, views, appWidgetId) - views = updateWeatherView(context, generatedBinding, views, appWidgetId) - } catch (ex: Exception) { - ex.printStackTrace() - CrashlyticsReceiver.sendCrash(context, ex) - } - - appWidgetManager.updateAppWidget(appWidgetId, views) - } - - private fun updateCalendarView(context: Context, bindingView: TheWidgetBinding, views: RemoteViews, widgetID: Int): RemoteViews { - val eventRepository = EventRepository(context) - try { - views.setImageViewBitmap( - R.id.empty_date_rect, - BitmapHelper.getBitmapFromView(bindingView.emptyDate, draw = false) - ) - - views.setViewVisibility(R.id.empty_layout_rect, View.VISIBLE) - views.setViewVisibility(R.id.calendar_layout_rect, View.GONE) - views.setViewVisibility(R.id.second_row_rect, View.GONE) - views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE) - - val calPIntent = PendingIntent.getActivity( - context, - widgetID, - IntentHelper.getCalendarIntent(context), - PendingIntent.FLAG_UPDATE_CURRENT - ) - views.setOnClickPendingIntent(R.id.empty_date_rect, calPIntent) - - val nextEvent = eventRepository.getNextEvent() - val nextAlarm = AlarmHelper.getNextAlarm(context) - - if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null && !Preferences.showEventsAsGlanceProvider) { - if (Preferences.showNextEvent && eventRepository.getEventsCount() > 1) { - 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.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 - ) - ) - } else { - views.setViewVisibility(R.id.action_next_rect, View.GONE) - views.setViewVisibility(R.id.action_previous_rect, View.GONE) - } - - val pIntent = PendingIntent.getActivity( - context, - widgetID, - IntentHelper.getEventIntent(context, nextEvent), - PendingIntent.FLAG_UPDATE_CURRENT - ) - views.setOnClickPendingIntent(R.id.next_event_rect, pIntent) - views.setOnClickPendingIntent(R.id.next_event_difference_time_rect, pIntent) - - 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) - } else { - views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE) - } - - 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.second_row_rect, mapIntent) - } else { - val pIntentDetail = PendingIntent.getActivity( - context, - widgetID, - IntentHelper.getEventIntent( - context, - nextEvent, - forceEventDetails = true - ), - PendingIntent.FLAG_UPDATE_CURRENT - ) - views.setOnClickPendingIntent(R.id.second_row_rect, pIntentDetail) - } - - views.setImageViewBitmap( - R.id.next_event_rect, - BitmapHelper.getBitmapFromView(bindingView.nextEvent, draw = false) - ) - - views.setImageViewBitmap( - R.id.second_row_rect, - BitmapHelper.getBitmapFromView(bindingView.secondRow, draw = false) - ) - views.setViewVisibility(R.id.second_row_rect, View.VISIBLE) - - views.setViewVisibility(R.id.empty_layout_rect, View.GONE) - views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE) - - views.setViewVisibility( - R.id.second_row_top_margin_small_sans, - if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.value) View.VISIBLE else View.GONE - ) - views.setViewVisibility( - R.id.second_row_top_margin_medium_sans, - if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.value) View.VISIBLE else View.GONE - ) - views.setViewVisibility( - R.id.second_row_top_margin_large_sans, - if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.value) View.VISIBLE else View.GONE - ) - } 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.second_row_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.second_row_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.second_row_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.second_row_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.second_row_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.second_row_rect, - pIntentDetail - ) - showSomething = true - break@loop - } - } - } - } - - - if (showSomething) { - views.setImageViewBitmap( - R.id.next_event_rect, - BitmapHelper.getBitmapFromView(bindingView.nextEvent, draw = false) - ) - - views.setImageViewBitmap( - R.id.second_row_rect, - BitmapHelper.getBitmapFromView(bindingView.secondRow, draw = false) - ) - - views.setViewVisibility(R.id.second_row_rect, View.VISIBLE) - views.setViewVisibility(R.id.empty_layout_rect, View.GONE) - views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE) - views.setOnClickPendingIntent(R.id.next_event_rect, calPIntent) - - - views.setViewVisibility( - R.id.second_row_top_margin_small_sans, - if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.value) View.VISIBLE else View.GONE - ) - views.setViewVisibility( - R.id.second_row_top_margin_medium_sans, - if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.value) View.VISIBLE else View.GONE - ) - views.setViewVisibility( - R.id.second_row_top_margin_large_sans, - if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.value) View.VISIBLE else View.GONE - ) - } - } - } catch (ex: Exception) { - ex.printStackTrace() - CrashlyticsReceiver.sendCrash(context, ex) - } finally { - eventRepository.close() - } - - return views - } - - private fun updateWeatherView(context: Context, bindingView: TheWidgetBinding, views: RemoteViews, widgetID: Int): RemoteViews { - try { - if (Preferences.showWeather && Preferences.weatherIcon != "") { - views.setViewVisibility(R.id.weather_rect, View.VISIBLE) - views.setViewVisibility(R.id.calendar_weather_rect, View.VISIBLE) - views.setViewVisibility(R.id.special_weather_rect, View.VISIBLE) - - 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.calendar_weather_rect, weatherPIntent) - views.setOnClickPendingIntent(R.id.special_weather_rect, weatherPIntent) - - views.setImageViewBitmap( - R.id.weather_rect, - BitmapHelper.getBitmapFromView(bindingView.weather, draw = false) - ) - - views.setImageViewBitmap( - R.id.calendar_weather_rect, - BitmapHelper.getBitmapFromView(bindingView.calendarWeather, draw = false) - ) - - views.setImageViewBitmap( - R.id.special_weather_rect, - BitmapHelper.getBitmapFromView(bindingView.calendarWeather, draw = false) - ) - - if (GlanceProviderHelper.showGlanceProviders(context)) { - views.setViewVisibility(R.id.calendar_weather_rect, View.GONE) - } else { - views.setViewVisibility(R.id.special_weather_rect, View.GONE) - } - } else { - views.setViewVisibility(R.id.weather_rect, View.GONE) - views.setViewVisibility(R.id.calendar_weather_rect, View.GONE) - views.setViewVisibility(R.id.special_weather_rect, View.GONE) - } - } catch (ex: Exception) { - ex.printStackTrace() - CrashlyticsReceiver.sendCrash(context, ex) - } - return views - } - - private fun updateClockView(context: Context, 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.value) View.VISIBLE else View.GONE - ) - views.setViewVisibility( - R.id.clock_bottom_margin_small, - if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value) View.VISIBLE else View.GONE - ) - views.setViewVisibility( - R.id.clock_bottom_margin_medium, - if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value) View.VISIBLE else View.GONE - ) - views.setViewVisibility( - R.id.clock_bottom_margin_large, - if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value) View.VISIBLE else View.GONE - ) - } - } catch (ex: Exception) { - ex.printStackTrace() - CrashlyticsReceiver.sendCrash(context, ex) - } - - return views - } - - - // Generates the widget bitmap from the view - fun generateWidgetView(context: Context, typeface: Typeface? = null): TheWidgetBinding { - val eventRepository = EventRepository(context) - val bindingView = TheWidgetBinding.inflate(LayoutInflater.from(context)) - - bindingView.loader.isVisible = false - - val now = Calendar.getInstance().apply { - set(Calendar.SECOND, 0) - set(Calendar.MILLISECOND, 0) - } - - bindingView.emptyLayout.visibility = View.VISIBLE - bindingView.calendarLayout.visibility = View.GONE - bindingView.nextEventDifferenceTime.visibility = View.GONE - bindingView.actionNext.isVisible = false - bindingView.actionPrevious.isVisible = false - - bindingView.emptyDate.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.visibility = View.VISIBLE - } else { - bindingView.nextEventDifferenceTime.visibility = View.GONE - } - - if (nextEvent.address != "" && Preferences.secondRowInformation == 1) { - bindingView.secondRowIcon.setImageDrawable( - ContextCompat.getDrawable( - context, - R.drawable.round_place_24 - ) - ) - bindingView.nextEventDate.text = nextEvent.address - } else { - bindingView.secondRowIcon.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.nextEventDate.text = - String.format("%s - %s%s", startHour, endHour, multipleDay) - } else { - bindingView.nextEventDate.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.nextEventDate.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.emptyLayout.visibility = View.GONE - bindingView.calendarLayout.visibility = View.VISIBLE - - bindingView.secondRowTopMarginSmall.visibility = - if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.value) View.VISIBLE else View.GONE - bindingView.secondRowTopMarginMedium.visibility = - if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.value) View.VISIBLE else View.GONE - bindingView.secondRowTopMarginLarge.visibility = - if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.value) View.VISIBLE else View.GONE - } else if (GlanceProviderHelper.showGlanceProviders(context)) { - bindingView.secondRowIcon.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.secondRowIcon.setImageDrawable( - ContextCompat.getDrawable( - context, - R.drawable.round_music_note_24 - ) - ) - bindingView.nextEventDate.text = MediaPlayerHelper.getMediaInfo() - showSomething = true - break@loop - } - } - Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> { - if (Preferences.showNextAlarm && nextAlarm != "") { - bindingView.secondRowIcon.setImageDrawable( - ContextCompat.getDrawable( - context, - R.drawable.round_alarm_24 - ) - ) - bindingView.nextEventDate.text = AlarmHelper.getNextAlarm(context) - showSomething = true - break@loop - } - } - Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> { - if (Preferences.showBatteryCharging) { - BatteryHelper.updateBatteryInfo(context) - if (Preferences.isCharging) { - bindingView.secondRowIcon.isVisible = false - val batteryLevel = BatteryHelper.getBatteryLevel(context) - if (batteryLevel != 100) { - bindingView.nextEventDate.text = context.getString(R.string.charging) - } else { - bindingView.nextEventDate.text = - context.getString(R.string.charged) - } - showSomething = true - break@loop - } else if (Preferences.isBatteryLevelLow) { - bindingView.secondRowIcon.isVisible = false - bindingView.nextEventDate.text = - context.getString(R.string.battery_low_warning) - showSomething = true - break@loop - } - } - } - Constants.GlanceProviderId.CUSTOM_INFO -> { - if (Preferences.customNotes.isNotEmpty()) { - bindingView.secondRowIcon.isVisible = false - bindingView.nextEventDate.text = Preferences.customNotes - bindingView.nextEventDate.maxLines = 2 - showSomething = true - break@loop - } - } - Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> { - if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) { - bindingView.secondRowIcon.isVisible = false - bindingView.nextEventDate.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.secondRowIcon.isVisible = true - bindingView.secondRowIcon.setImageDrawable(icon) - } else { - bindingView.secondRowIcon.isVisible = false - } - bindingView.nextEventDate.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.nextEventDate.text = greetingsText - bindingView.nextEventDate.maxLines = 2 - bindingView.secondRowIcon.isVisible = false - showSomething = true - break@loop - } - } - Constants.GlanceProviderId.EVENTS -> { - if (Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) { - bindingView.nextEventDate.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.secondRowIcon.isVisible = true - bindingView.secondRowIcon.setImageDrawable( - ContextCompat.getDrawable( - context, - R.drawable.round_today_24 - ) - ) - showSomething = true - break@loop - } - } - } - } - - if (showSomething) { - bindingView.nextEvent.text = DateHelper.getDateText(context, now) - bindingView.emptyLayout.visibility = View.GONE - bindingView.calendarLayout.visibility = View.VISIBLE - - bindingView.secondRowTopMarginSmall.visibility = - if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.value) View.VISIBLE else View.GONE - bindingView.secondRowTopMarginMedium.visibility = - if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.value) View.VISIBLE else View.GONE - bindingView.secondRowTopMarginLarge.visibility = - if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.value) View.VISIBLE else View.GONE - } else { - bindingView.secondRowIcon.isVisible = false - } - } - - - // Color - listOf( - bindingView.emptyDate, - bindingView.divider1, - bindingView.temp, - bindingView.nextEvent, - bindingView.nextEventDifferenceTime, - bindingView.divider3, - bindingView.specialTemp - ).forEach { - it.setTextColor(ColorHelper.getFontColor(context.applicationContext.isDarkTheme())) - } - - if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.value) { - listOf(bindingView.actionNext, bindingView.actionPrevious) - } else { - listOf( - bindingView.actionNext, - bindingView.actionPrevious, - bindingView.emptyWeatherIcon, - bindingView.specialWeatherIcon - ) - }.forEach { - it.setColorFilter(ColorHelper.getFontColorRgb(context.applicationContext.isDarkTheme())) - it.alpha = - (if (context.isDarkTheme()) Preferences.textGlobalAlphaDark.toIntValue() - .toFloat() else Preferences.textGlobalAlpha.toIntValue() - .toFloat()) / 100 - } - - listOf(bindingView.nextEventDate, bindingView.divider2, bindingView.calendarTemp).forEach { - it.setTextColor(ColorHelper.getSecondaryFontColor(context.applicationContext.isDarkTheme())) - } - - if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.value) { - listOf(bindingView.secondRowIcon, bindingView.secondRowIconShadow) - } else { - listOf(bindingView.secondRowIcon, bindingView.weatherIcon, bindingView.secondRowIconShadow) - }.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>( - bindingView.emptyDate to Preferences.textMainSize, - bindingView.divider1 to (Preferences.textMainSize - 2), - bindingView.temp to Preferences.textMainSize, - bindingView.nextEvent to Preferences.textMainSize, - bindingView.nextEventDifferenceTime to Preferences.textMainSize, - bindingView.nextEventDate to Preferences.textSecondSize, - bindingView.divider2 to (Preferences.textSecondSize - 2), - bindingView.calendarTemp to Preferences.textSecondSize, - bindingView.divider3 to (Preferences.textMainSize - 2), - bindingView.specialTemp to Preferences.textMainSize - ).forEach { - it.first.setTextSize(TypedValue.COMPLEX_UNIT_SP, it.second) - } - - // Icons scale - bindingView.secondRowIcon.scaleX = Preferences.textSecondSize / 18f - bindingView.secondRowIcon.scaleY = Preferences.textSecondSize / 18f - - bindingView.weatherIcon.scaleX = Preferences.textSecondSize / 14f - bindingView.weatherIcon.scaleY = Preferences.textSecondSize / 14f - - bindingView.emptyWeatherIcon.scaleX = Preferences.textMainSize / 18f - bindingView.emptyWeatherIcon.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 - - bindingView.specialWeatherIcon.scaleX = Preferences.textMainSize / 18f - bindingView.specialWeatherIcon.scaleY = Preferences.textMainSize / 18f - - - // 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( - bindingView.emptyDate, - bindingView.divider1, - bindingView.temp, - bindingView.nextEvent, - bindingView.nextEventDifferenceTime, - bindingView.nextEventDate, - bindingView.divider2, - bindingView.calendarTemp, - bindingView.divider3, - bindingView.specialTemp - ).forEach { - it.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor) - } - - // Icons shadow - - listOf( - Pair(bindingView.secondRowIcon, bindingView.secondRowIconShadow), - ).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( - bindingView.emptyDate, - bindingView.divider1, - bindingView.temp, - bindingView.nextEvent, - bindingView.nextEventDifferenceTime, - bindingView.nextEventDate, - bindingView.divider2, - bindingView.calendarTemp, - bindingView.divider3, - bindingView.specialTemp - ).forEach { - it.typeface = googleSans - } - } else if (Preferences.customFont == Constants.CUSTOM_FONT_DOWNLOADED && typeface != null) { - listOf( - bindingView.emptyDate, - bindingView.divider1, - bindingView.temp, - bindingView.nextEvent, - bindingView.nextEventDifferenceTime, - bindingView.nextEventDate, - bindingView.divider2, - bindingView.calendarTemp, - bindingView.divider3, - bindingView.specialTemp - ).forEach { - it.typeface = typeface - } - } - - // Weather - if (Preferences.showWeather && Preferences.weatherIcon != "") { - bindingView.weather.visibility = View.VISIBLE - bindingView.calendarWeather.visibility = View.VISIBLE - bindingView.specialWeather.visibility = View.VISIBLE - val currentTemp = String.format( - Locale.getDefault(), - "%d °%s", - Preferences.weatherTemp.roundToInt(), - Preferences.weatherRealTempUnit - ) - - val icon: String = Preferences.weatherIcon - if (icon == "") { - bindingView.weatherIcon.visibility = View.GONE - bindingView.emptyWeatherIcon.visibility = View.GONE - bindingView.specialWeatherIcon.visibility = View.GONE - } else { - bindingView.weatherIcon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon)) - bindingView.emptyWeatherIcon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon)) - bindingView.specialWeatherIcon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon)) - bindingView.weatherIcon.visibility = View.VISIBLE - bindingView.emptyWeatherIcon.visibility = View.VISIBLE - bindingView.specialWeatherIcon.visibility = View.VISIBLE - } - - bindingView.temp.text = currentTemp - bindingView.calendarTemp.text = currentTemp - bindingView.specialTemp.text = currentTemp - - if (GlanceProviderHelper.showGlanceProviders(context)) { - bindingView.calendarWeather.visibility = View.GONE - } else { - bindingView.specialWeather.visibility = View.GONE - } - } else { - bindingView.weather.visibility = View.GONE - bindingView.calendarWeather.visibility = View.GONE - bindingView.specialWeather.visibility = View.GONE - } - - // Dividers - arrayOf(bindingView.divider1, bindingView.divider2, bindingView.divider3).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 } } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/StandardWidget.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/StandardWidget.kt new file mode 100644 index 0000000..1901107 --- /dev/null +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/widgets/StandardWidget.kt @@ -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( + 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(bindingView.actionNext, bindingView.actionPrevious) + } else { + listOf( + 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(bindingView.subLineText, bindingView.weatherSubLineDivider, bindingView.weatherSubLineTemperature).forEach { + it.setTextColor(ColorHelper.getSecondaryFontColor(context.applicationContext.isDarkTheme())) + } + + if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.rawValue) { + listOf(bindingView.subLineIcon, bindingView.subLineIconShadow) + } else { + listOf(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>( + 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( + 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( + 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( + 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 + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_tab_layout.xml b/app/src/main/res/layout/fragment_tab_layout.xml index 5761e31..3492aec 100644 --- a/app/src/main/res/layout/fragment_tab_layout.xml +++ b/app/src/main/res/layout/fragment_tab_layout.xml @@ -111,6 +111,43 @@ android:paddingLeft="20dp" android:paddingRight="20dp" android:textAppearance="@style/AnotherWidget.Settings.Header" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/left_aligned_widget_sans.xml b/app/src/main/res/layout/left_aligned_widget_sans.xml new file mode 100644 index 0000000..11fa721 --- /dev/null +++ b/app/src/main/res/layout/left_aligned_widget_sans.xml @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/right_aligned_widget.xml b/app/src/main/res/layout/right_aligned_widget.xml new file mode 100644 index 0000000..5519290 --- /dev/null +++ b/app/src/main/res/layout/right_aligned_widget.xml @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/right_aligned_widget_sans.xml b/app/src/main/res/layout/right_aligned_widget_sans.xml new file mode 100644 index 0000000..85ce6f5 --- /dev/null +++ b/app/src/main/res/layout/right_aligned_widget_sans.xml @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/the_widget.xml b/app/src/main/res/layout/the_widget.xml index c0b260e..2282237 100644 --- a/app/src/main/res/layout/the_widget.xml +++ b/app/src/main/res/layout/the_widget.xml @@ -4,79 +4,80 @@ android:layout_gravity="center" android:clipChildren="false" android:clipToPadding="false" + android:orientation="vertical" android:id="@+id/main_layout"> - + android:orientation="vertical" + android:layout_centerInParent="true"> + android:layout_gravity="center" + android:orientation="horizontal" + android:layoutDirection="locale" + android:id="@+id/date_layout"> - - + style="@style/AnotherWidget.Widget.Title"/> + + + + + - - - - - - - + android:id="@+id/sub_line_top_margin_small" /> + android:id="@+id/sub_line_top_margin_medium" /> + android:id="@+id/sub_line_top_margin_large" /> + android:layout_marginStart="4dp" + android:id="@+id/weather_sub_line"> + android:layout_width="20dp" + android:layout_height="20dp" + android:id="@+id/weather_sub_line_weather_icon" + android:layout_marginStart="4dp" + android:layout_marginEnd="8dp"/> + android:id="@+id/weather_sub_line_temperature"/> - \ No newline at end of file diff --git a/app/src/main/res/layout/the_widget_sans.xml b/app/src/main/res/layout/the_widget_sans.xml index 697b42a..75e8cda 100644 --- a/app/src/main/res/layout/the_widget_sans.xml +++ b/app/src/main/res/layout/the_widget_sans.xml @@ -74,40 +74,48 @@ + - + - - - + android:gravity="center" + android:alpha="0" + android:visibility="gone" + android:orientation="horizontal" + android:layoutDirection="locale" + android:id="@+id/first_line_rect"> + + + - + android:id="@+id/sub_line_top_margin_small_sans" /> + android:id="@+id/sub_line_top_margin_medium_sans" /> + android:id="@+id/sub_line_top_margin_large_sans" /> + android:id="@+id/sub_line_rect" /> + android:visibility="gone" + android:id="@+id/weather_sub_line_rect" /> - - - \ No newline at end of file diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 24eb9f2..f37c356 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -37,6 +37,10 @@ Grassetto Nero Molto nero + Allineamento widget + Sinistra + Destra + Centro Calendario diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3d2c9b0..218745c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -31,6 +31,10 @@ Rows spacing Custom font… Font family + Widget align + Left + Right + Center Thin Light diff --git a/build.gradle b/build.gradle index abafc28..8238dc1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.4.21' + ext.kotlin_version = '1.4.32' repositories { google() jcenter() @@ -10,14 +10,14 @@ buildscript { } 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 'com.google.gms:google-services:4.3.4' + classpath 'com.google.gms:google-services:4.3.5' // 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 // in the individual module build.gradle files