From 102efd60415d25c19d34238c9b589303c0c575ac Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sun, 17 May 2026 16:39:08 -0400 Subject: [PATCH 01/67] gradle: update dependencies --- gradle/libs.versions.toml | 54 +++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f45f47e3..519f6641 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,37 +5,37 @@ targetSdkVersion = "36" gradleVersion = "8.13.2" kotlin_version = '2.1.20' -kotlinx_version = '1.10.2' +kotlinx_version = "1.11.0" ksp_version = '2.1.20-2.0.1' desugar_version = '2.1.5' -firebase_version = "34.7.0" -firebaseCrashlyticsGradleVersion = "3.0.6" +firebase_version = "34.13.0" +firebaseCrashlyticsGradleVersion = "3.0.7" firebasePerfPluginVersion = "2.0.2" gms_location_version = '21.3.0' -gms_base_version = '18.9.0' -gms_basement_version = '18.9.0' -gms_tasks_version = '18.4.0' -gms_wearable_version = '19.0.0' +gms_base_version = "18.10.0" +gms_basement_version = "18.10.0" +gms_tasks_version = "18.4.1" +gms_wearable_version = "20.0.1" googleServicesVersion = "4.4.4" -annotation_version = '1.9.1' -activity_version = "1.12.1" +annotation_version = "1.10.0" +activity_version = "1.13.0" appcompat_version = '1.7.1' constraintlayout_version = '2.2.1' -core_version = '1.17.0' +core_version = "1.18.0" arch_core_runtime_version = '2.2.0' fragment_version = '1.8.9' lifecycle_version = "2.10.0" -nav_version = "2.9.6" -paging_version = '3.3.6' +nav_version = "2.9.8" +paging_version = "3.5.0" preference_version = '1.2.1' recyclerview_version = '1.4.0' room_version = "2.8.4" coresplash_version = "1.2.0" vectordrawable_version = '1.2.0' -work_version = '2.11.0' +work_version = "2.11.2" test_core_version = '1.7.0' test_runner_version = '1.7.0' @@ -46,27 +46,27 @@ androidx_truth_version = '1.7.0' google_truth_version = '1.4.5' espresso_core_version = "3.7.0" -material_version = "1.14.0-alpha07" -material_compose_version = "1.5.0-alpha10" +material_version = "1.14.0" +material_compose_version = "1.5.0-alpha19" compose_compiler_version = '1.5.15' -compose_bom_version = "2025.12.00" -wear_version = '1.3.0' -wear_compose_version = "1.5.6" +compose_bom_version = "2026.05.00" +wear_version = "1.4.0" +wear_compose_version = "1.6.1" wear_input_version = '1.2.0' -wear_tiles_version = '1.5.0' -wear_watchface_version = '1.2.1' +wear_tiles_version = "1.6.0" +wear_watchface_version = "1.3.0" horologist_version = '0.7.15' accompanist_version = '0.37.3' -glide_version = '5.0.5' -icu4j_version = "78.1" +glide_version = "5.0.7" +icu4j_version = "78.3" jjwt_version = '0.13.0' moshi_version = '1.15.2' okhttp_version = "5.3.2" timber_version = '5.0.1' -revcat_version = "9.15.4" +revcat_version = "10.6.0" [libraries] com-google-devtools-ksp-gradle-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp_version" } @@ -135,7 +135,7 @@ wear = { module = "androidx.wear:wear", version.ref = "wear_version" } wear-input = { module = "androidx.wear:wear-input", version.ref = "wear_input_version" } wear-input-testing = { module = "androidx.wear:wear-input-testing", version.ref = "wear_input_version" } wear-phone-interactions = { module = "androidx.wear:wear-phone-interactions", version = "1.1.0" } -wear-remote-interactions = { module = "androidx.wear:wear-remote-interactions", version = "1.1.0" } +wear-remote-interactions = { module = "androidx.wear:wear-remote-interactions", version = "1.2.0" } wear-watchface-complications-data = { module = "androidx.wear.watchface:watchface-complications-data", version.ref = "wear_watchface_version" } wear-watchface-complications-data-source-ktx = { module = "androidx.wear.watchface:watchface-complications-data-source-ktx", version.ref = "wear_watchface_version" } wear-tiles = { module = "androidx.wear.tiles:tiles", version.ref = "wear_tiles_version" } @@ -163,7 +163,7 @@ wear-tooling-preview = { module = "androidx.wear:wear-tooling-preview", version accompanist-drawablepainter = { module = "com.google.accompanist:accompanist-drawablepainter", version.ref = "accompanist_version" } horologist-compose-layout = { module = "com.google.android.horologist:horologist-compose-layout", version.ref = "horologist_version" } horologist-compose-tools = { module = "com.google.android.horologist:horologist-compose-tools", version.ref = "horologist_version" } -reorderable = { module = "sh.calvin.reorderable:reorderable", version = "3.0.0" } +reorderable = { module = "sh.calvin.reorderable:reorderable", version = "3.1.0" } compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" } compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" } firebase-perf = { module = "com.google.firebase:firebase-perf" } @@ -176,9 +176,9 @@ navigation-fragment-ktx = { module = "androidx.navigation:navigation-fragment-kt navigation-ui-ktx = { module = "androidx.navigation:navigation-ui-ktx", version.ref = "nav_version" } glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide_version" } glide-ksp = { module = "com.github.bumptech.glide:ksp", version.ref = "glide_version" } -colorpickerview = { module = "com.github.skydoves:colorpickerview", version = "2.3.0" } +colorpickerview = { module = "com.github.skydoves:colorpickerview", version = "2.4.0" } firebase-messaging = { module = "com.google.firebase:firebase-messaging" } -gms-play-services-maps = { module = "com.google.android.gms:play-services-maps", version = "19.2.0" } +gms-play-services-maps = { module = "com.google.android.gms:play-services-maps", version = "20.0.0" } play-app-update-ktx = { module = "com.google.android.play:app-update-ktx", version = "2.1.0" } play-feature-delivery-ktx = { module = "com.google.android.play:feature-delivery-ktx", version = "2.1.0" } play-review-ktx = { module = "com.google.android.play:review-ktx", version = "2.0.2" } From 1cb489e82fe1212dba24b9910c23de3bbc7c94d5 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Mon, 18 May 2026 16:50:28 -0400 Subject: [PATCH 02/67] gradle: AGP 9.2.1 --- .gitignore | 3 ++- app/build.gradle | 4 ++-- build.gradle | 2 +- common/build.gradle | 10 +++++++--- gradle.properties | 5 ++--- gradle/gradle-daemon-jvm.properties | 13 +++++++++++++ gradle/libs.versions.toml | 11 ++++++----- gradle/wrapper/gradle-wrapper.properties | 2 +- settings.gradle | 3 +++ shared_resources/build.gradle | 9 +++++++-- wearapp/build.gradle | 2 -- weather-api/build.gradle | 22 +++++++++++++++------- 12 files changed, 59 insertions(+), 27 deletions(-) create mode 100644 gradle/gradle-daemon-jvm.properties diff --git a/.gitignore b/.gitignore index 47da38f6..9ea96b57 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,5 @@ API_KEY.txt google-services.json /.privado/ /.detekt -/.kotlin \ No newline at end of file +/.kotlin +/.skills \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 6a5687ae..f2701d4d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,8 +1,7 @@ plugins { id 'com.android.application' id 'androidx.navigation.safeargs' - id 'kotlin-android' - id 'kotlin-kapt' + id 'com.android.legacy-kapt' id 'com.google.devtools.ksp' } @@ -47,6 +46,7 @@ android { dataBinding true viewBinding true buildConfig true + resValues true } compileOptions { diff --git a/build.gradle b/build.gradle index 0872f147..61ef7560 100644 --- a/build.gradle +++ b/build.gradle @@ -9,13 +9,13 @@ buildscript { dependencies { classpath libs.gradle + classpath libs.legacy.kapt.plugin classpath libs.com.google.devtools.ksp.gradle.plugin classpath libs.google.services classpath libs.firebase.crashlytics.gradle classpath libs.firebase.perf.plugin classpath libs.nav.safe.args.plugin classpath libs.room.plugin - classpath libs.kotlin.gradle.plugin classpath libs.compose.compiler.gradle.plugin // NOTE: Do not place your application dependencies here; they belong diff --git a/common/build.gradle b/common/build.gradle index 3a18584f..4c185d06 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -1,7 +1,6 @@ plugins { id 'com.android.library' - id 'kotlin-android' - id 'kotlin-kapt' + id 'com.android.legacy-kapt' } android { @@ -9,7 +8,6 @@ android { defaultConfig { minSdk libs.versions.minSdkVersion.get().toInteger() - targetSdk libs.versions.targetSdkVersion.get().toInteger() testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -54,6 +52,12 @@ android { } } namespace 'com.thewizrd.common' + lint { + targetSdk libs.versions.targetSdkVersion.get().toInteger() + } + testOptions { + targetSdk libs.versions.targetSdkVersion.get().toInteger() + } } dependencies { diff --git a/gradle.properties b/gradle.properties index 13908a33..81306c04 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,6 +20,5 @@ android.useAndroidX=true android.enableJetifier=false # Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official -android.nonTransitiveRClass=false -android.nonFinalResIds=false -org.gradle.configuration-cache=false \ No newline at end of file +org.gradle.configuration-cache=false +android.r8.strictFullModeForKeepRules=false \ No newline at end of file diff --git a/gradle/gradle-daemon-jvm.properties b/gradle/gradle-daemon-jvm.properties new file mode 100644 index 00000000..baa28d15 --- /dev/null +++ b/gradle/gradle-daemon-jvm.properties @@ -0,0 +1,13 @@ +#This file is generated by updateDaemonJvm +toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/491f83666ae7f4d6ebb28fee72ebb035/redirect +toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/0d1a1acdc708062093673f65aa9aba4b/redirect +toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/491f83666ae7f4d6ebb28fee72ebb035/redirect +toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/0d1a1acdc708062093673f65aa9aba4b/redirect +toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/7083b89563e7ce20943037b8cd2b8cc2/redirect +toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/060bbb778a1f55ea705fdebd2ccfeab9/redirect +toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/491f83666ae7f4d6ebb28fee72ebb035/redirect +toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/0d1a1acdc708062093673f65aa9aba4b/redirect +toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/d09679dc60fe5aa05ef7d03efdefac20/redirect +toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/ed4e3bf2f5e7c5d9aabc4cbd8acd555e/redirect +toolchainVendor=JETBRAINS +toolchainVersion=21 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 519f6641..0cd6202c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,12 +1,12 @@ [versions] -compileSdkVersion = "36" +compileSdkVersion = "37" minSdkVersion = "23" targetSdkVersion = "36" -gradleVersion = "8.13.2" -kotlin_version = '2.1.20' +gradleVersion = "9.2.1" +kotlin_version = "2.3.21" kotlinx_version = "1.11.0" -ksp_version = '2.1.20-2.0.1' +ksp_version = "2.3.6" desugar_version = '2.1.5' @@ -70,6 +70,7 @@ revcat_version = "10.6.0" [libraries] com-google-devtools-ksp-gradle-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp_version" } +legacy-kapt-plugin = { module = "com.android.legacy-kapt:com.android.legacy-kapt.gradle.plugin", version.ref = "gradleVersion" } compose-compiler-gradle-plugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin_version" } espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso_core_version" } junit = { module = "junit:junit", version.ref = "junit_version" } @@ -79,7 +80,6 @@ firebase-crashlytics-gradle = { module = "com.google.firebase:firebase-crashlyti google-services = { module = "com.google.gms:google-services", version.ref = "googleServicesVersion" } gradle = { module = "com.android.tools.build:gradle", version.ref = "gradleVersion" } firebase-perf-plugin = { module = "com.google.firebase:perf-plugin", version.ref = "firebasePerfPluginVersion" } -kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin_version" } nav-safe-args-plugin = { module = "androidx.navigation:navigation-safe-args-gradle-plugin", version.ref = "nav_version" } room-plugin = { module = "androidx.room:room-gradle-plugin", version.ref = "room_version" } @@ -187,6 +187,7 @@ jjwt-api = { module = "io.jsonwebtoken:jjwt-api", version.ref = "jjwt_version" } jjwt-impl = { module = "io.jsonwebtoken:jjwt-impl", version.ref = "jjwt_version" } jjwt-orgjson = { module = "io.jsonwebtoken:jjwt-orgjson", version.ref = "jjwt_version" } moshi-java-codegen = { module = "com.github.nename0:moshi-java-codegen", version = "1.1.1" } +#noinspection GradleDependency places = { module = "com.google.android.libraries.places:places", version = "4.4.1" } volley = { module = "com.android.volley:volley", version = "1.2.1" } gms-play-services-basement = { module = "com.google.android.gms:play-services-basement", version.ref = "gms_basement_version" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 54fddc2e..9a6304ac 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Aug 31 15:05:29 EDT 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/settings.gradle b/settings.gradle index bab1dc21..e1e4682d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,6 @@ +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.10.0' +} include ':extras' include ':weathericons' include ':app', ':wearapp', ':shared_resources' diff --git a/shared_resources/build.gradle b/shared_resources/build.gradle index 188db7a4..7ef8927c 100644 --- a/shared_resources/build.gradle +++ b/shared_resources/build.gradle @@ -1,6 +1,5 @@ plugins { id 'com.android.library' - id 'kotlin-android' id 'com.google.devtools.ksp' id 'androidx.room' } @@ -10,7 +9,6 @@ android { defaultConfig { minSdk libs.versions.minSdkVersion.get().toInteger() - targetSdk libs.versions.targetSdkVersion.get().toInteger() testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -28,6 +26,7 @@ android { buildFeatures { buildConfig true + resValues true } buildTypes { @@ -76,6 +75,12 @@ android { } namespace 'com.thewizrd.shared_resources' + lint { + targetSdk libs.versions.targetSdkVersion.get().toInteger() + } + testOptions { + targetSdk libs.versions.targetSdkVersion.get().toInteger() + } } dependencies { diff --git a/wearapp/build.gradle b/wearapp/build.gradle index 553325a5..467a6fd4 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -1,7 +1,5 @@ plugins { id 'com.android.application' - id 'kotlin-android' - id 'kotlin-kapt' id 'com.google.devtools.ksp' id 'org.jetbrains.kotlin.plugin.compose' } diff --git a/weather-api/build.gradle b/weather-api/build.gradle index 94818738..ab044000 100644 --- a/weather-api/build.gradle +++ b/weather-api/build.gradle @@ -1,7 +1,6 @@ plugins { id 'com.android.library' - id 'kotlin-android' - id 'kotlin-kapt' + id 'com.android.legacy-kapt' id 'com.google.devtools.ksp' id 'androidx.room' } @@ -11,7 +10,6 @@ android { defaultConfig { minSdk libs.versions.minSdkVersion.get().toInteger() - targetSdk libs.versions.targetSdkVersion.get().toInteger() testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" @@ -86,6 +84,12 @@ android { } namespace 'com.thewizrd.weather_api' + lint { + targetSdk libs.versions.targetSdkVersion.get().toInteger() + } + testOptions { + targetSdk libs.versions.targetSdkVersion.get().toInteger() + } } dependencies { @@ -147,9 +151,13 @@ tasks.register('keyCheck', Exec) { } } -android.libraryVariants.configureEach { variant -> - def name = variant.flavorName - if (name.contains('fullgms')) { - variant.preBuildProvider.configure { dependsOn(keyCheck) } +androidComponents { + onVariants(selector().all()) { variant -> + if (variant.flavorName?.contains('fullgms')) { + def taskName = "pre${variant.name.capitalize()}Build" + tasks.matching { it.name == taskName }.configureEach { task -> + task.dependsOn(keyCheck) + } + } } } From 9c1e11f83e607f6d572a36d06f2c7826e9db3cdd Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Mon, 18 May 2026 20:51:15 -0400 Subject: [PATCH 03/67] gradle: update for nonTransitiveRClass --- .../simpleweather/FirebaseConfigurator.kt | 3 +- .../thewizrd/simpleweather/extras/Extras.kt | 11 +-- .../services/AppUpdaterWorker.kt | 3 +- .../activities/LocationSearchActivity.kt | 5 +- .../simpleweather/adapters/ButtonAdapter.kt | 7 +- .../adapters/CurrentAQIAdapter.kt | 3 +- .../adapters/FavoritesPanelAdapter.kt | 15 ++-- .../simpleweather/adapters/FeaturesAdapter.kt | 6 +- .../simpleweather/adapters/GPSPanelAdapter.kt | 10 ++- .../adapters/LocationQueryAdapter.kt | 2 +- .../adapters/LocationQueryFooterAdapter.kt | 3 +- .../simpleweather/controls/AQIProgressBar.kt | 5 +- .../simpleweather/controls/ClockToolbar.kt | 7 +- .../controls/CustomSearchView.kt | 2 +- .../simpleweather/controls/DetailCard.java | 16 ++-- .../simpleweather/controls/FeatureItem.kt | 9 +-- .../controls/ForecastBarGraphView.kt | 13 ++-- .../LoadingIndicatorRefreshLayout.java | 6 +- .../simpleweather/controls/LocationPanel.kt | 17 +++-- .../controls/LocationPanelUiModel.kt | 2 +- .../controls/LocationSearchView.kt | 2 +- .../controls/WeatherDetailItem.kt | 2 +- .../viewmodels/AirQualityDataMapper.kt | 2 +- .../viewmodels/ForecastGraphViewModel.java | 7 +- .../controls/viewmodels/GraphModelUtils.kt | 2 +- .../databinding/ViewBindingAdapter.java | 4 +- .../databinding/WeatherNowBindingAdapter.kt | 2 +- .../AbstractWeatherListDetailFragment.kt | 2 +- .../fragments/CollapsingToolbarFragment.kt | 6 +- .../LargeCollapsingToolbarFragment.kt | 7 +- .../fragments/ToolbarFragment.kt | 5 +- .../helpers/ItemTouchHelperCallback.java | 2 +- .../simpleweather/main/LocationsFragment.kt | 29 +++---- .../simpleweather/main/MainActivity.kt | 2 +- .../simpleweather/main/WeatherAQIFragment.kt | 5 +- .../main/WeatherAlertFragment.kt | 5 +- .../main/WeatherChartsFragment.kt | 5 +- .../simpleweather/main/WeatherListFragment.kt | 9 ++- .../simpleweather/main/WeatherNowFragment.kt | 29 +++---- .../main/WeatherRadarFragment.kt | 5 +- .../WeatherAlertNotificationBuilder.kt | 25 ++++--- .../WeatherNotificationWorker.kt | 7 +- .../ArrayMultiSelectListPreference.java | 4 +- .../preferences/BaseSettingsFragment.kt | 3 +- .../preferences/DevSettingsFragment.kt | 4 +- .../preferences/SettingsFragment.kt | 75 ++++++++++--------- .../SettingsPreferenceGroupAdapter.kt | 3 +- .../ToolbarPreferenceFragmentCompat.kt | 7 +- .../chippreference/ChipPreference.kt | 14 ++-- .../colorpreference/ColorPreference.java | 2 +- .../services/ServiceNotificationHelper.kt | 5 +- .../services/WeatherUpdaterWorker.kt | 12 ++- .../simpleweather/setup/SetupActivity.kt | 3 +- .../setup/SetupLocationFragment.kt | 3 +- .../setup/SetupProviderFragment.kt | 12 ++- .../setup/SetupSettingsFragment.kt | 17 +++-- .../snackbar/SnackbarManager.java | 20 ++--- .../stepper/BottomStepperNavigationBar.java | 8 +- .../viewmodels/LocationsViewModel.kt | 3 +- .../widgets/AppChoiceDialogBuilder.kt | 4 +- .../widgets/WeatherWidgetProvider.kt | 3 +- .../widgets/WidgetUpdaterHelper.kt | 3 +- ...AbstractWeatherWidgetPreferenceFragment.kt | 13 ++-- .../BaseWeatherWidgetPreferenceFragment.kt | 5 +- .../WeatherWidget4x3LocationFragment.kt | 15 ++-- .../WeatherWidgetPreferenceFragment.kt | 17 +++-- ...CustomBackgroundWidgetRemoteViewCreator.kt | 3 +- .../remoteviews/WeatherWidget1x1Creator.kt | 10 ++- .../remoteviews/WeatherWidget2x2Creator.kt | 28 ++++--- .../remoteviews/WeatherWidget4x1Creator.kt | 10 ++- .../WeatherWidget4x1GoogleCreator.kt | 12 ++- .../WeatherWidget4x1NotificationCreator.kt | 14 ++-- .../WeatherWidget4x2ClockCreator.kt | 19 +++-- .../remoteviews/WeatherWidget4x2Creator.kt | 20 +++-- .../WeatherWidget4x2GraphCreator.kt | 27 ++++--- .../WeatherWidget4x2HuaweiCreator.kt | 19 +++-- .../WeatherWidget4x2TomorrowCreator.kt | 27 ++++--- .../WeatherWidget4x3LocationsCreator.kt | 19 +++-- .../common/location/LocationProvider.kt | 2 +- .../common/controls/WeatherAlertPanel.java | 2 +- .../KeyEntryPreferenceDialogFragment.kt | 11 +-- .../common/preferences/SliderPreference.kt | 5 +- .../viewmodels/LocationSearchViewModel.kt | 2 +- .../simpleweather/FirebaseConfigurator.kt | 1 + .../thewizrd/simpleweather/extras/Extras.kt | 2 +- .../simpleweather/main/MainActivity.kt | 3 +- .../KeyEntryPreferenceDialogFragment.kt | 26 ++++--- .../preferences/SettingsActivity.kt | 48 ++++++------ .../services/ServiceNotificationHelper.kt | 9 ++- .../services/WeatherUpdaterWorker.kt | 3 +- .../ui/components/ConfirmationOverlay.kt | 5 +- .../ui/components/WeatherAlertPanel.kt | 3 +- .../ui/components/WeatherDetailItem.kt | 3 +- .../ui/components/WeatherForecastPanel.kt | 13 ++-- .../components/WeatherHourlyForecastPanel.kt | 9 ++- .../WeatherMinutelyForecastPanel.kt | 5 +- .../preferences/WearEditTextPreference.kt | 3 +- .../preferences/WearListPreference.kt | 3 +- .../DetailsWeatherTileConfigScreen.kt | 53 ++++++------- .../ui/setup/SetupLocationListScreen.kt | 10 ++- .../ui/setup/SetupLocationSearchScreen.kt | 11 ++- .../simpleweather/ui/setup/SetupScreen.kt | 22 +++--- .../simpleweather/ui/setup/SetupSyncScreen.kt | 5 +- .../simpleweather/ui/theme/ViewModelExtras.kt | 24 +++--- .../ui/weather/WeatherNowScreen.kt | 41 +++++----- .../viewmodels/ConfirmationViewModel.kt | 8 +- .../complications/AQIComplicationService.kt | 12 +-- .../BeaufortComplicationService.kt | 14 ++-- ...tionFeelsLikeWeatherComplicationService.kt | 10 +-- ...rrentLocationWeatherComplicationService.kt | 3 +- .../DewPointComplicationService.kt | 13 ++-- .../FeelsLikeComplicationService.kt | 21 ++++-- .../HumidityComplicationService.kt | 21 +++--- .../PrecipitationComplicationService.kt | 11 +-- .../PressureComplicationService.kt | 35 +++++---- .../SunriseSunsetComplicationService.kt | 21 +++--- .../complications/UVComplicationService.kt | 9 ++- .../WeatherComplicationService.kt | 5 +- .../WeatherHiLoComplicationService.kt | 9 ++- .../complications/WindComplicationService.kt | 41 +++++----- .../ForecastWeatherTileProviderService.kt | 7 +- ...ourlyForecastWeatherTileProviderService.kt | 7 +- .../layouts/CurrentWeatherGoogleTileLayout.kt | 5 +- .../tiles/layouts/CurrentWeatherTileLayout.kt | 5 +- .../tiles/layouts/DetailsWeatherTileLayout.kt | 7 +- .../layouts/ForecastWeatherTileLayout.kt | 13 ++-- .../layouts/HourlyForecastCardTileLayout.kt | 9 ++- .../layouts/HourlyForecastPillsTileLayout.kt | 9 ++- .../HourlyForecastWeatherTileLayout.kt | 13 ++-- .../layouts/M3ForecastWeatherTileLayout.kt | 9 ++- .../M3HourlyForecastWeatherTileLayout.kt | 9 ++- .../weather_api/eccc/ECCCWeatherProvider.kt | 2 +- .../weather_api/google/weather/WeatherData.kt | 2 +- .../weather/MeteomaticsWeatherProvider.kt | 2 +- .../tomorrow/TomorrowIOWeatherProvider.kt | 2 +- .../weather_api/tomorrow/WeatherData.kt | 2 +- .../weather_api/weatherkit/WeatherData.kt | 2 +- .../weatherkit/WeatherKitProvider.kt | 2 +- 138 files changed, 829 insertions(+), 607 deletions(-) diff --git a/app/src/fullgms/java/com/thewizrd/simpleweather/FirebaseConfigurator.kt b/app/src/fullgms/java/com/thewizrd/simpleweather/FirebaseConfigurator.kt index cd430fb4..e0e5764a 100644 --- a/app/src/fullgms/java/com/thewizrd/simpleweather/FirebaseConfigurator.kt +++ b/app/src/fullgms/java/com/thewizrd/simpleweather/FirebaseConfigurator.kt @@ -9,6 +9,7 @@ import com.google.firebase.remoteconfig.ConfigUpdate import com.google.firebase.remoteconfig.ConfigUpdateListener import com.google.firebase.remoteconfig.FirebaseRemoteConfig import com.google.firebase.remoteconfig.FirebaseRemoteConfigException +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.remoteconfig.remoteConfigService import com.thewizrd.shared_resources.utils.AnalyticsProps import com.thewizrd.shared_resources.utils.ContextUtils.isLargeTablet @@ -38,7 +39,7 @@ object FirebaseConfigurator { isCrashlyticsCollectionEnabled = true sendUnsentReports() } - FirebaseRemoteConfig.getInstance().setDefaultsAsync(R.xml.remote_config_defaults) + FirebaseRemoteConfig.getInstance().setDefaultsAsync(sharedRes.xml.remote_config_defaults) if (!BuildConfig.DEBUG) { Logger.registerLogger(CrashlyticsLoggingTree()) diff --git a/app/src/fullgms/java/com/thewizrd/simpleweather/extras/Extras.kt b/app/src/fullgms/java/com/thewizrd/simpleweather/extras/Extras.kt index 92022239..d03f0307 100644 --- a/app/src/fullgms/java/com/thewizrd/simpleweather/extras/Extras.kt +++ b/app/src/fullgms/java/com/thewizrd/simpleweather/extras/Extras.kt @@ -15,6 +15,7 @@ import com.google.android.play.core.splitcompat.SplitCompat import com.google.firebase.Firebase import com.google.firebase.installations.installations import com.thewizrd.extras.extrasModule +import com.thewizrd.extras.R as extrasRes import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.store.PlayStoreUtils import com.thewizrd.simpleweather.App @@ -84,7 +85,7 @@ fun BaseSettingsFragment.navigateToPremiumFragment() { showSnackbar( Snackbar.make( rootView.context, - R.string.message_premium_required, + extrasRes.string.message_premium_required, Snackbar.Duration.SHORT ), null @@ -102,7 +103,7 @@ fun SettingsFragment.IconsFragment.navigateUnsupportedIconPack() { showSnackbar( Snackbar.make( rootView.context, - R.string.message_premium_required, + extrasRes.string.message_premium_required, Snackbar.Duration.SHORT ), null @@ -133,8 +134,8 @@ fun areNotificationExtrasEnabled(): Boolean { fun SettingsFragment.createPremiumPreference(): Preference { val premiumPref = Preference(requireContext()).apply { - title = context.getString(R.string.pref_title_premium) - summary = context.getString(R.string.pref_summary_premium) + title = context.getString(extrasRes.string.pref_title_premium) + summary = context.getString(extrasRes.string.pref_summary_premium) setIcon(R.drawable.ic_star_24dp) order = 0 } @@ -147,7 +148,7 @@ fun SettingsFragment.createPremiumPreference(): Preference { showSnackbar( Snackbar.make( rootView.context, - R.string.message_premium_required, + extrasRes.string.message_premium_required, Snackbar.Duration.SHORT ), null diff --git a/app/src/fullgms/java/com/thewizrd/simpleweather/services/AppUpdaterWorker.kt b/app/src/fullgms/java/com/thewizrd/simpleweather/services/AppUpdaterWorker.kt index 236f66f7..467ddbbb 100644 --- a/app/src/fullgms/java/com/thewizrd/simpleweather/services/AppUpdaterWorker.kt +++ b/app/src/fullgms/java/com/thewizrd/simpleweather/services/AppUpdaterWorker.kt @@ -13,6 +13,7 @@ import androidx.core.app.NotificationCompat import androidx.work.* import com.thewizrd.common.helpers.areNotificationsEnabled import com.thewizrd.common.utils.LiveDataUtils.awaitWithTimeout +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.helpers.toImmutableCompatFlag import com.thewizrd.shared_resources.preferences.UpdateSettings import com.thewizrd.shared_resources.utils.Colors @@ -94,7 +95,7 @@ class AppUpdaterWorker(context: Context, workerParams: WorkerParameters) : initChannel(mNotifyMgr) val mNotif = NotificationCompat.Builder(applicationContext, NOT_CHANNEL_ID) - .setSmallIcon(R.drawable.ic_error_white) + .setSmallIcon(sharedRes.drawable.ic_error_white) .setContentTitle(applicationContext.getString(R.string.prompt_update_title)) .setContentText(applicationContext.getString(R.string.prompt_update_available)) .setContentIntent(getLaunchUpdatesIntent(applicationContext)) diff --git a/app/src/main/java/com/thewizrd/simpleweather/activities/LocationSearchActivity.kt b/app/src/main/java/com/thewizrd/simpleweather/activities/LocationSearchActivity.kt index bb4391fd..fc58ba67 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/activities/LocationSearchActivity.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/activities/LocationSearchActivity.kt @@ -20,6 +20,7 @@ import androidx.core.view.ViewGroupCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.updatePaddingRelative import androidx.lifecycle.lifecycleScope +import com.google.android.material.R as materialRes import com.google.android.material.search.SearchView import com.google.android.material.snackbar.Snackbar import com.google.android.material.transition.platform.MaterialContainerTransform @@ -191,7 +192,7 @@ class LocationSearchActivity : WindowColorActivity() { start = padding, end = padding, top = padding ) - val color = getAttrColor(R.attr.colorPrimarySurface) + val color = getAttrColor(materialRes.attr.colorPrimarySurface) window.setTransparentWindow(color) lifecycleScope.launch { @@ -267,7 +268,7 @@ class LocationSearchActivity : WindowColorActivity() { } private fun updateWindowColors(mode: UserThemeMode) { - var backgroundColor = getAttrColor(R.attr.colorSurfaceContainerHigh) + var backgroundColor = getAttrColor(materialRes.attr.colorSurfaceContainerHigh) if (mode == UserThemeMode.AMOLED_DARK) { backgroundColor = Colors.BLACK } diff --git a/app/src/main/java/com/thewizrd/simpleweather/adapters/ButtonAdapter.kt b/app/src/main/java/com/thewizrd/simpleweather/adapters/ButtonAdapter.kt index da770e8d..8caf4456 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/adapters/ButtonAdapter.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/adapters/ButtonAdapter.kt @@ -10,6 +10,7 @@ import androidx.annotation.Px import androidx.annotation.StringRes import androidx.core.view.updateMargins import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.R as materialRes import com.google.android.material.button.MaterialButton import com.thewizrd.simpleweather.R @@ -26,7 +27,11 @@ class ButtonAdapter( layoutParams = RecyclerView.LayoutParams(MATCH_PARENT, WRAP_CONTENT) addView( - MaterialButton(parent.context, null, R.attr.materialButtonOutlinedStyle).apply { + MaterialButton( + parent.context, + null, + materialRes.attr.materialButtonOutlinedStyle + ).apply { layoutParams = FrameLayout.LayoutParams(this@ButtonAdapter.width, WRAP_CONTENT).apply { gravity = this@ButtonAdapter.gravity diff --git a/app/src/main/java/com/thewizrd/simpleweather/adapters/CurrentAQIAdapter.kt b/app/src/main/java/com/thewizrd/simpleweather/adapters/CurrentAQIAdapter.kt index 879bf0e8..f959b883 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/adapters/CurrentAQIAdapter.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/adapters/CurrentAQIAdapter.kt @@ -8,6 +8,7 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.material.card.MaterialCardView import com.google.android.material.shape.ShapeAppearanceModel import com.thewizrd.common.controls.AirQualityViewModel +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.utils.ContextUtils.dpToPx import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.databinding.LayoutAqiForecastItemBinding @@ -32,7 +33,7 @@ class CurrentAQIAdapter : RecyclerView.Adapter() { fun bindModel(aqiData: AirQualityViewModel?) { binding.viewModel = aqiData binding.executePendingBindings() - binding.aqiDateLabel.text = context.getString(R.string.time_current) + binding.aqiDateLabel.text = context.getString(sharedRes.string.time_current) } } diff --git a/app/src/main/java/com/thewizrd/simpleweather/adapters/FavoritesPanelAdapter.kt b/app/src/main/java/com/thewizrd/simpleweather/adapters/FavoritesPanelAdapter.kt index b6e0fc07..40b58d8b 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/adapters/FavoritesPanelAdapter.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/adapters/FavoritesPanelAdapter.kt @@ -16,8 +16,10 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListUpdateCallback import androidx.recyclerview.widget.RecyclerView import com.google.android.material.snackbar.Snackbar +import com.thewizrd.common.R as commonRes import com.thewizrd.common.helpers.ObservableArrayList import com.thewizrd.common.helpers.OnListChangedListener +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.di.localBroadcastManager @@ -197,7 +199,8 @@ class FavoritesPanelAdapter : LocationPanelAdapter(), ItemTouchHelperAdapter, return when (viewType) { LocationPanelItemType.HEADER_FAV -> { HeaderViewHolder( - LayoutInflater.from(context).inflate(R.layout.locations_header, parent, false) + LayoutInflater.from(context) + .inflate(commonRes.layout.locations_header, parent, false) ).also { headerViewHolder = it } @@ -444,10 +447,10 @@ class FavoritesPanelAdapter : LocationPanelAdapter(), ItemTouchHelperAdapter, class HeaderViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView), HeaderSetterInterface { - private var header = itemView.findViewById(R.id.header) + private var header = itemView.findViewById(commonRes.id.header) override fun setHeader() { - header.setText(R.string.label_favoritelocations) + header.setText(sharedRes.string.label_favoritelocations) header.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_star_24dp, 0, 0, 0) } @@ -534,7 +537,7 @@ class FavoritesPanelAdapter : LocationPanelAdapter(), ItemTouchHelperAdapter, mSnackMgr?.show( com.thewizrd.simpleweather.snackbar.Snackbar.make( context, - R.string.message_needfavorite, + sharedRes.string.message_needfavorite, com.thewizrd.simpleweather.snackbar.Snackbar.Duration.SHORT ), null ) @@ -552,10 +555,10 @@ class FavoritesPanelAdapter : LocationPanelAdapter(), ItemTouchHelperAdapter, // Make SnackBar val snackbar = com.thewizrd.simpleweather.snackbar.Snackbar.make( context, - R.string.message_locationremoved, + sharedRes.string.message_locationremoved, com.thewizrd.simpleweather.snackbar.Snackbar.Duration.SHORT ) - snackbar.setAction(R.string.undo) { undoAction() } + snackbar.setAction(sharedRes.string.undo) { undoAction() } val callback = object : Snackbar.Callback() { override fun onDismissed(transientBottomBar: Snackbar?, event: Int) { diff --git a/app/src/main/java/com/thewizrd/simpleweather/adapters/FeaturesAdapter.kt b/app/src/main/java/com/thewizrd/simpleweather/adapters/FeaturesAdapter.kt index f57e5f90..35b3dcda 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/adapters/FeaturesAdapter.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/adapters/FeaturesAdapter.kt @@ -10,8 +10,10 @@ import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.RecyclerView import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.shape.ShapeAppearanceModel +import com.thewizrd.common.R as commonRes import com.thewizrd.common.helpers.ObservableArrayList import com.thewizrd.common.helpers.OnListChangedListener +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.utils.ContextUtils.dpToPx import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.controls.FeatureItem @@ -62,7 +64,7 @@ class FeaturesAdapter : RecyclerView.Adapter(), Item KEY_FEATURE_UV to R.string.pref_title_feature_uv, KEY_FEATURE_BEAUFORT to R.string.pref_title_feature_beaufort, KEY_FEATURE_AQINDEX to R.string.pref_title_feature_aqindex, - KEY_FEATURE_POLLEN to R.string.label_pollen_count, + KEY_FEATURE_POLLEN to sharedRes.string.label_pollen_count, KEY_FEATURE_MOONPHASE to R.string.pref_title_feature_moonphase, KEY_FEATURE_SUNPHASE to R.string.pref_title_feature_sunphase, KEY_FEATURE_RADAR to R.string.pref_title_feature_radar, @@ -208,7 +210,7 @@ class FeaturesAdapter : RecyclerView.Adapter(), Item ) { val baseShapeModel = ShapeAppearanceModel.builder( context, - R.style.ShapeAppearance_Material3_Corner_Large, + com.google.android.material.R.style.ShapeAppearance_Material3_Corner_Large, 0 ) val smallCornerSize = context.dpToPx(4f) diff --git a/app/src/main/java/com/thewizrd/simpleweather/adapters/GPSPanelAdapter.kt b/app/src/main/java/com/thewizrd/simpleweather/adapters/GPSPanelAdapter.kt index 42000ead..2dc5c70f 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/adapters/GPSPanelAdapter.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/adapters/GPSPanelAdapter.kt @@ -6,6 +6,8 @@ import android.view.ViewGroup import android.widget.TextView import androidx.core.widget.TextViewCompat import androidx.recyclerview.widget.RecyclerView +import com.thewizrd.common.R as commonRes +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.utils.ContextUtils.getAttrColor import com.thewizrd.shared_resources.utils.ContextUtils.getAttrColorStateList import com.thewizrd.simpleweather.R @@ -32,12 +34,12 @@ class GPSPanelAdapter : LocationPanelAdapter() { inner class HeaderViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView), HeaderSetterInterface { - private val header = itemView.findViewById(R.id.header) + private val header = itemView.findViewById(commonRes.id.header) override fun setHeader() { - header.setText(R.string.label_currentlocation) + header.setText(sharedRes.string.label_currentlocation) header.setCompoundDrawablesRelativeWithIntrinsicBounds( - R.drawable.ic_place_white_24dp, + sharedRes.drawable.ic_place_white_24dp, 0, 0, 0 @@ -74,7 +76,7 @@ class GPSPanelAdapter : LocationPanelAdapter() { LocationPanelItemType.HEADER_GPS -> { HeaderViewHolder( LayoutInflater.from(context) - .inflate(R.layout.locations_header, parent, false) + .inflate(commonRes.layout.locations_header, parent, false) ) } else -> { diff --git a/app/src/main/java/com/thewizrd/simpleweather/adapters/LocationQueryAdapter.kt b/app/src/main/java/com/thewizrd/simpleweather/adapters/LocationQueryAdapter.kt index 2020496b..05453f9f 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/adapters/LocationQueryAdapter.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/adapters/LocationQueryAdapter.kt @@ -85,7 +85,7 @@ class LocationQueryAdapter : private fun updateItemCorners(cardView: MaterialCardView, @CornersType cornersType: Int) { val baseShapeModel = ShapeAppearanceModel.builder( cardView.context, - R.style.ShapeAppearance_Material3_Corner_Large, + com.google.android.material.R.style.ShapeAppearance_Material3_Corner_Large, 0 ) val smallCornerSize = cardView.context.dpToPx(4f) diff --git a/app/src/main/java/com/thewizrd/simpleweather/adapters/LocationQueryFooterAdapter.kt b/app/src/main/java/com/thewizrd/simpleweather/adapters/LocationQueryFooterAdapter.kt index 98a3339c..a89200a0 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/adapters/LocationQueryFooterAdapter.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/adapters/LocationQueryFooterAdapter.kt @@ -6,6 +6,7 @@ import android.view.ViewGroup import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.thewizrd.common.R +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.weather_api.weatherModule @@ -24,7 +25,7 @@ class LocationQueryFooterAdapter : val entry = WeatherAPI.LocationAPIs.find { lapi -> locationAPI == lapi.value } val credit = String.format( "%s %s", - context.getString(R.string.credit_prefix), + context.getString(sharedRes.string.credit_prefix), entry?.toString() ?: WeatherIcons.EM_DASH ) diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/AQIProgressBar.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/AQIProgressBar.kt index eff83901..d2de459b 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/AQIProgressBar.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/AQIProgressBar.kt @@ -48,10 +48,11 @@ class AQIProgressBar @JvmOverloads constructor( thumbDrawable = MaterialShapeDrawable().apply { shadowCompatibilityMode = MaterialShapeDrawable.SHADOW_COMPAT_MODE_ALWAYS fillColor = ColorStateList.valueOf(THUMB_COLOR) - elevation = context.resources.getDimension(R.dimen.m3_slider_thumb_elevation) + elevation = + context.resources.getDimension(com.google.android.material.R.dimen.m3_slider_thumb_elevation) thumbSize = - context.resources.getDimensionPixelSize(R.dimen.mtrl_slider_thumb_radius) * 3 / 4 + context.resources.getDimensionPixelSize(com.google.android.material.R.dimen.mtrl_slider_thumb_radius) * 3 / 4 shapeAppearanceModel = ShapeAppearanceModel.builder() .setAllCorners(CornerFamily.ROUNDED, thumbSize / 2f) diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/ClockToolbar.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/ClockToolbar.kt index d7bcac1a..6c13a092 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/ClockToolbar.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/ClockToolbar.kt @@ -31,7 +31,7 @@ import java.time.format.DateTimeFormatter class ClockToolbar @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, - defStyleAttr: Int = R.attr.toolbarStyle + defStyleAttr: Int = androidx.appcompat.R.attr.toolbarStyle ) : MaterialToolbar(context, attrs, defStyleAttr) { private var mFormat12: CharSequence? = null private var mFormat24: CharSequence? = null @@ -107,7 +107,10 @@ class ClockToolbar @JvmOverloads constructor( val a = context.obtainStyledAttributes(attrs, R.styleable.ClockToolbar) ViewCompat.saveAttributeDataForStyleable( this, context, R.styleable.ClockToolbar, - attrs, a, defStyleAttr, R.style.Widget_MaterialComponents_Toolbar + attrs, + a, + defStyleAttr, + com.google.android.material.R.style.Widget_MaterialComponents_Toolbar ) try { diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/CustomSearchView.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/CustomSearchView.kt index 8f844226..d42c3070 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/CustomSearchView.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/CustomSearchView.kt @@ -4,9 +4,9 @@ import android.content.Context import android.util.AttributeSet import android.view.View import androidx.annotation.ColorInt +import com.google.android.material.R import com.google.android.material.elevation.ElevationOverlayProvider import com.google.android.material.search.SearchView -import com.thewizrd.simpleweather.R open class CustomSearchView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/DetailCard.java b/app/src/main/java/com/thewizrd/simpleweather/controls/DetailCard.java index 3ed3fb7a..971585e8 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/DetailCard.java +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/DetailCard.java @@ -78,7 +78,7 @@ private void initialize(@NonNull Context context) { binding = CardWeatherDetailBinding.inflate(inflater, this, true); bgDrawable = new MaterialShapeDrawable( - ShapeAppearanceModel.builder(context, R.style.ShapeAppearance_Material3_MediumComponent, 0) + ShapeAppearanceModel.builder(context, com.google.android.material.R.style.ShapeAppearance_Material3_MediumComponent, 0) .build()); bgDrawable.initializeElevationOverlay(context); bgDrawable.setElevation(ContextUtils.dpToPx(context, 1f)); @@ -92,19 +92,19 @@ private void initialize(@NonNull Context context) { Resources.Theme currentTheme = context.getTheme(); TypedArray array; - array = currentTheme.obtainStyledAttributes(R.style.ShadowText, new int[]{android.R.attr.shadowRadius}); + array = currentTheme.obtainStyledAttributes(com.thewizrd.shared_resources.R.style.ShadowText, new int[]{android.R.attr.shadowRadius}); mShadowRadius = array.getFloat(0, 0); array.recycle(); - array = currentTheme.obtainStyledAttributes(R.style.ShadowText, new int[]{android.R.attr.shadowDx}); + array = currentTheme.obtainStyledAttributes(com.thewizrd.shared_resources.R.style.ShadowText, new int[]{android.R.attr.shadowDx}); mShadowDx = array.getFloat(0, 0); array.recycle(); - array = currentTheme.obtainStyledAttributes(R.style.ShadowText, new int[]{android.R.attr.shadowDy}); + array = currentTheme.obtainStyledAttributes(com.thewizrd.shared_resources.R.style.ShadowText, new int[]{android.R.attr.shadowDy}); mShadowDy = array.getFloat(0, 0); array.recycle(); - array = currentTheme.obtainStyledAttributes(R.style.ShadowText, new int[]{android.R.attr.shadowColor}); + array = currentTheme.obtainStyledAttributes(com.thewizrd.shared_resources.R.style.ShadowText, new int[]{android.R.attr.shadowColor}); mShadowColor = array.getColor(0, 0); array.recycle(); @@ -112,9 +112,9 @@ private void initialize(@NonNull Context context) { } private void updateColors() { - setBackgroundColor(ContextUtils.getAttrColor(getContext(), R.attr.colorSurfaceContainer)); - ImageViewCompat.setImageTintList(binding.detailIcon, ColorStateList.valueOf(ContextUtils.getAttrColor(getContext(), R.attr.colorPrimary))); - bgDrawable.setStrokeColor(ContextCompat.getColorStateList(getContext(), R.color.m3_card_stroke_color)); + setBackgroundColor(ContextUtils.getAttrColor(getContext(), com.google.android.material.R.attr.colorSurfaceContainer)); + ImageViewCompat.setImageTintList(binding.detailIcon, ColorStateList.valueOf(ContextUtils.getAttrColor(getContext(), androidx.appcompat.R.attr.colorPrimary))); + bgDrawable.setStrokeColor(ContextCompat.getColorStateList(getContext(), com.google.android.material.R.color.m3_card_stroke_color)); } @Override diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/FeatureItem.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/FeatureItem.kt index 4ef3772d..07de4d2a 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/FeatureItem.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/FeatureItem.kt @@ -20,10 +20,9 @@ import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.dpToPx import com.thewizrd.shared_resources.utils.ContextUtils.getAttrColor -import com.thewizrd.shared_resources.utils.ContextUtils.getAttrColorStateList -import com.thewizrd.shared_resources.utils.ContextUtils.getAttrDrawable import com.thewizrd.shared_resources.utils.UserThemeMode import com.thewizrd.simpleweather.R +import com.google.android.material.R as materialRes class FeatureItem @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null @@ -63,18 +62,18 @@ class FeatureItem @JvmOverloads constructor( fillColor = ColorStateList.valueOf( if (settingsManager.getUserThemeMode() == UserThemeMode.AMOLED_DARK) { ColorUtils.compositeColors( - context.getAttrColor(R.attr.colorSurfaceDim), + context.getAttrColor(materialRes.attr.colorSurfaceDim), Colors.BLACK ) } else { - context.getAttrColor(R.attr.colorSurfaceBright) + context.getAttrColor(materialRes.attr.colorSurfaceBright) } ) initializeElevationOverlay(context) elevation = 0f shapeAppearanceModel = ShapeAppearanceModel.builder( context, - R.style.ShapeAppearance_Material3_Corner_LargeIncreased, + materialRes.style.ShapeAppearance_Material3_Corner_LargeIncreased, 0 ).build() }, diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/ForecastBarGraphView.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/ForecastBarGraphView.kt index 14db16af..aee3f972 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/ForecastBarGraphView.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/ForecastBarGraphView.kt @@ -14,6 +14,7 @@ import androidx.core.view.forEachIndexed import androidx.core.view.isGone import androidx.core.view.updateLayoutParams import androidx.databinding.DataBindingUtil +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.helpers.RecyclerOnClickListenerInterface import com.thewizrd.shared_resources.utils.ContextUtils.dpToPx import com.thewizrd.simpleweather.R @@ -219,13 +220,13 @@ class ForecastBarGraphView @JvmOverloads constructor( private fun getIconResourceFromForecastType(forecastType: ForecastType?): Int { return when (forecastType) { ForecastType.TEMPERATURE -> 0 - ForecastType.MINUTELY -> R.drawable.wi_raindrop - ForecastType.PRECIPITATION -> R.drawable.wi_raindrop - ForecastType.WIND -> R.drawable.wi_direction_up_2x - ForecastType.HUMIDITY -> R.drawable.material_humidity_percentage + ForecastType.MINUTELY -> sharedRes.drawable.wi_raindrop + ForecastType.PRECIPITATION -> sharedRes.drawable.wi_raindrop + ForecastType.WIND -> sharedRes.drawable.wi_direction_up_2x + ForecastType.HUMIDITY -> sharedRes.drawable.material_humidity_percentage ForecastType.UVINDEX -> 0 - ForecastType.RAIN -> R.drawable.material_water_drop - ForecastType.SNOW -> R.drawable.wi_snowflake_cold + ForecastType.RAIN -> sharedRes.drawable.material_water_drop + ForecastType.SNOW -> sharedRes.drawable.wi_snowflake_cold ForecastType.AIRQUALITY -> 0 null -> 0 } diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/LoadingIndicatorRefreshLayout.java b/app/src/main/java/com/thewizrd/simpleweather/controls/LoadingIndicatorRefreshLayout.java index 122441df..85c23351 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/LoadingIndicatorRefreshLayout.java +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/LoadingIndicatorRefreshLayout.java @@ -354,11 +354,11 @@ private void createProgressView() { mCircleView = new AnimationFrameLayout(getContext()); mCircleView.setLayoutParams(new LayoutParams(containerWidth, containerHeight)); mCircleView.setBackground(new ShapeDrawable(new OvalShape())); - mCircleView.setBackgroundTintList(ColorStateList.valueOf(ContextUtils.getAttrColor(getContext(), R.attr.colorPrimaryContainer))); + mCircleView.setBackgroundTintList(ColorStateList.valueOf(ContextUtils.getAttrColor(getContext(), com.google.android.material.R.attr.colorPrimaryContainer))); mCircleView.setClipToOutline(true); mLoadingIndicator = new LoadingIndicator(getContext()); - mLoadingIndicator.setIndicatorColor(ContextUtils.getAttrColor(getContext(), R.attr.colorPrimary)); + mLoadingIndicator.setIndicatorColor(ContextUtils.getAttrColor(getContext(), androidx.appcompat.R.attr.colorPrimary)); mLoadingIndicator.setContainerWidth(containerWidth); mLoadingIndicator.setContainerHeight(containerHeight); mLoadingIndicator.setIndicatorSize(indicatorSize); @@ -367,7 +367,7 @@ private void createProgressView() { mStaticLoadingView = new AppCompatImageView(getContext()); mStaticLoadingView.setImageResource(R.drawable.loading_indicator); - mStaticLoadingView.setImageTintList(ColorStateList.valueOf(ContextUtils.getAttrColor(getContext(), R.attr.colorPrimary))); + mStaticLoadingView.setImageTintList(ColorStateList.valueOf(ContextUtils.getAttrColor(getContext(), androidx.appcompat.R.attr.colorPrimary))); mStaticLoadingView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); mStaticLoadingView.setAdjustViewBounds(true); mStaticLoadingView.setLayoutParams(new FrameLayout.LayoutParams(indicatorSize, indicatorSize, Gravity.CENTER)); diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/LocationPanel.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/LocationPanel.kt index c1e3e068..bf8b70d9 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/LocationPanel.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/LocationPanel.kt @@ -25,6 +25,7 @@ import com.bumptech.glide.load.resource.bitmap.BitmapTransitionOptions import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.target.BitmapImageViewTarget import com.bumptech.glide.request.transition.Transition +import com.google.android.material.R as materialRes import com.google.android.material.card.MaterialCardView import com.google.android.material.shape.ShapeAppearanceModel import com.thewizrd.common.controls.TextViewDrawableCompat @@ -95,10 +96,14 @@ class LocationPanel : MaterialCardView { } shapeAppearanceModel = - ShapeAppearanceModel.builder(context, R.style.ShapeAppearance_Material3_Corner_Large, 0) + ShapeAppearanceModel.builder( + context, + materialRes.style.ShapeAppearance_Material3_Corner_Large, + 0 + ) .build() - setCardBackgroundColor(context.getAttrColor(R.attr.colorSurface)) + setCardBackgroundColor(context.getAttrColor(materialRes.attr.colorSurface)) overlayDrawable = ContextCompat.getDrawable(context, R.drawable.background_overlay) cardElevation = context.dpToPx(2f) @@ -115,7 +120,7 @@ class LocationPanel : MaterialCardView { checkedIconTint = if (FeatureSettings.isLocationPanelImageEnabled) { ColorStateList.valueOf(Colors.WHITE) } else ColorStateList.valueOf( - context.getAttrColor(R.attr.colorPrimary) + context.getAttrColor(androidx.appcompat.R.attr.colorPrimary) ) setRippleColorResource( if (FeatureSettings.isLocationPanelImageEnabled) { @@ -266,7 +271,7 @@ object LocationPanelBindingAdapter { view.setTextColor(Colors.WHITE) } else { view.setShadowLayer(0f, view.shadowDx, view.shadowDy, Colors.TRANSPARENT) - view.setTextColor(view.context.getAttrColor(R.attr.colorOnSurface)) + view.setTextColor(view.context.getAttrColor(materialRes.attr.colorOnSurface)) } } @@ -281,7 +286,7 @@ object LocationPanelBindingAdapter { if (panelImageEnabled) { Colors.WHITE } else { - view.context.getAttrColor(R.attr.colorOnSurface) + view.context.getAttrColor(materialRes.attr.colorOnSurface) } ) ) @@ -296,7 +301,7 @@ object LocationPanelBindingAdapter { if (panelImageEnabled) { Colors.WHITE } else { - view.context.getAttrColor(R.attr.colorOnSurface) + view.context.getAttrColor(materialRes.attr.colorOnSurface) } ) ) diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/LocationPanelUiModel.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/LocationPanelUiModel.kt index 6eb919d7..d3ec0cd0 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/LocationPanelUiModel.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/LocationPanelUiModel.kt @@ -11,7 +11,7 @@ import com.thewizrd.shared_resources.utils.LocaleUtils import com.thewizrd.shared_resources.utils.Units import com.thewizrd.shared_resources.weatherdata.model.LocationType import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R +import com.thewizrd.shared_resources.R import com.thewizrd.simpleweather.images.getImageData import com.thewizrd.weather_api.weatherModule import kotlinx.coroutines.Dispatchers diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/LocationSearchView.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/LocationSearchView.kt index 8552c9a4..7330f3bb 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/LocationSearchView.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/LocationSearchView.kt @@ -16,7 +16,7 @@ import com.thewizrd.common.helpers.SimpleGestureListener import com.thewizrd.shared_resources.helpers.ListAdapterOnClickInterface import com.thewizrd.shared_resources.locationdata.LocationQuery import com.thewizrd.shared_resources.utils.ContextUtils.dpToPx -import com.thewizrd.simpleweather.R +import com.google.android.material.R import com.thewizrd.simpleweather.adapters.LocationQueryAdapter import com.thewizrd.simpleweather.adapters.LocationQueryFooterAdapter diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/WeatherDetailItem.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/WeatherDetailItem.kt index 1cc698ce..de525089 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/WeatherDetailItem.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/WeatherDetailItem.kt @@ -18,7 +18,7 @@ import com.google.android.material.shape.ShapeAppearanceModel import com.thewizrd.common.controls.BaseForecastItemViewModel import com.thewizrd.common.controls.ForecastItemViewModel import com.thewizrd.common.controls.HourlyForecastItemViewModel -import com.thewizrd.simpleweather.R +import com.thewizrd.shared_resources.R import com.thewizrd.simpleweather.adapters.DetailsItemGridAdapter import com.thewizrd.simpleweather.databinding.WeatherDetailPanelBinding import java.util.Locale diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/AirQualityDataMapper.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/AirQualityDataMapper.kt index b969cf3d..74aeb843 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/AirQualityDataMapper.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/AirQualityDataMapper.kt @@ -5,7 +5,7 @@ import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.utils.AirQualityUtils import com.thewizrd.shared_resources.utils.DateTimeUtils import com.thewizrd.shared_resources.weatherdata.model.AirQuality -import com.thewizrd.simpleweather.R +import com.thewizrd.shared_resources.R import com.thewizrd.simpleweather.controls.graphs.BarGraphData import com.thewizrd.simpleweather.controls.graphs.BarGraphDataSet import com.thewizrd.simpleweather.controls.graphs.BarGraphEntry diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastGraphViewModel.java b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastGraphViewModel.java index 8cc9b99f..a551bd9a 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastGraphViewModel.java +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastGraphViewModel.java @@ -18,7 +18,6 @@ import com.thewizrd.shared_resources.weatherdata.model.Forecast; import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast; import com.thewizrd.shared_resources.weatherdata.model.MinutelyForecast; -import com.thewizrd.simpleweather.R; import com.thewizrd.simpleweather.controls.graphs.BarGraphData; import com.thewizrd.simpleweather.controls.graphs.BarGraphDataSet; import com.thewizrd.simpleweather.controls.graphs.BarGraphEntry; @@ -280,7 +279,7 @@ private LineDataSeries createSeriesData(List entryData, @NonNull default: case PRECIPITATION: series = new LineDataSeries(entryData); - series.setSeriesColors(ContextCompat.getColor(context, R.color.colorPrimary)); + series.setSeriesColors(ContextCompat.getColor(context, com.thewizrd.shared_resources.R.color.colorPrimary)); series.setSeriesMinMax(0f, 100f); break; case WIND: @@ -407,7 +406,7 @@ private void addEntryData(@NonNull BaseForecast forecast, @NonNull BarGraphDataS entry = new BarGraphEntry(date, new YEntryData(0f, "0%")); } - entry.setFillColor(ContextCompat.getColor(context, R.color.colorPrimary)); + entry.setFillColor(ContextCompat.getColor(context, com.thewizrd.shared_resources.R.color.colorPrimary)); dataSet.addEntry(entry); } case WIND -> { @@ -545,7 +544,7 @@ private String getDateFromForecast(BaseForecast forecast) { if (forecast instanceof Forecast) { Forecast fcast = (Forecast) forecast; - date = fcast.getDate().format(DateTimeUtils.ofPatternForUserLocale(context.getString(R.string.forecast_date_format))); + date = fcast.getDate().format(DateTimeUtils.ofPatternForUserLocale(context.getString(com.thewizrd.shared_resources.R.string.forecast_date_format))); } else if (forecast instanceof HourlyForecast) { HourlyForecast fcast = (HourlyForecast) forecast; diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/GraphModelUtils.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/GraphModelUtils.kt index fec85da7..f2d0d4d7 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/GraphModelUtils.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/GraphModelUtils.kt @@ -1,7 +1,7 @@ package com.thewizrd.simpleweather.controls.viewmodels import android.content.Context -import com.thewizrd.simpleweather.R +import com.thewizrd.shared_resources.R object GraphModelUtils { @JvmStatic diff --git a/app/src/main/java/com/thewizrd/simpleweather/databinding/ViewBindingAdapter.java b/app/src/main/java/com/thewizrd/simpleweather/databinding/ViewBindingAdapter.java index 1ea4915d..cd479aa6 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/databinding/ViewBindingAdapter.java +++ b/app/src/main/java/com/thewizrd/simpleweather/databinding/ViewBindingAdapter.java @@ -1,5 +1,6 @@ package com.thewizrd.simpleweather.databinding; +import android.annotation.SuppressLint; import android.content.Context; import android.content.res.ColorStateList; import android.graphics.PorterDuff; @@ -44,6 +45,7 @@ public static void updateProgressColor(@NonNull BaseProgressIndicator progres progressBar.setIndicatorColor(progressColor); } + @SuppressLint("RestrictedApi") @BindingAdapter("progressBackgroundColor") public static void updateProgressBackgroundColor(ProgressBar progressBar, @ColorInt int progressBackgroundColor) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { @@ -68,7 +70,7 @@ public static void updateProgressBackgroundColor(ProgressBar progressBar, @Color @BindingAdapter("attribution") public static void updateAttribution(final TextView view, final CharSequence attrib) { if (!TextUtils.isEmpty(attrib)) { - view.setText(String.format(Locale.ROOT, "%s %s", view.getContext().getString(R.string.credit_prefix), attrib)); + view.setText(String.format(Locale.ROOT, "%s %s", view.getContext().getString(com.thewizrd.shared_resources.R.string.credit_prefix), attrib)); view.setVisibility(View.VISIBLE); } else { view.setText(""); diff --git a/app/src/main/java/com/thewizrd/simpleweather/databinding/WeatherNowBindingAdapter.kt b/app/src/main/java/com/thewizrd/simpleweather/databinding/WeatherNowBindingAdapter.kt index ad10abc1..fed20b5d 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/databinding/WeatherNowBindingAdapter.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/databinding/WeatherNowBindingAdapter.kt @@ -22,7 +22,7 @@ import com.thewizrd.shared_resources.utils.StringUtils.removeNonDigitChars import com.thewizrd.shared_resources.utils.Units import com.thewizrd.shared_resources.utils.getColorFromTempF import com.thewizrd.shared_resources.weatherdata.model.MoonPhase.MoonPhaseType -import com.thewizrd.simpleweather.R +import com.thewizrd.shared_resources.R import com.thewizrd.simpleweather.adapters.DetailsItemAdapter import com.thewizrd.simpleweather.adapters.DetailsItemGridAdapter import com.thewizrd.simpleweather.adapters.HourlyForecastItemAdapter diff --git a/app/src/main/java/com/thewizrd/simpleweather/fragments/AbstractWeatherListDetailFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/fragments/AbstractWeatherListDetailFragment.kt index ed20c2ba..c22f4f58 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/fragments/AbstractWeatherListDetailFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/fragments/AbstractWeatherListDetailFragment.kt @@ -29,9 +29,9 @@ import androidx.core.content.res.use import androidx.core.view.doOnLayout import androidx.fragment.app.FragmentContainerView import androidx.fragment.app.commit +import androidx.navigation.fragment.R import androidx.navigation.fragment.NavHostFragment import androidx.slidingpanelayout.widget.SlidingPaneLayout -import com.thewizrd.simpleweather.R /** * A fragment supports adaptive two-pane layout. The first child is a list pane, which could be a diff --git a/app/src/main/java/com/thewizrd/simpleweather/fragments/CollapsingToolbarFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/fragments/CollapsingToolbarFragment.kt index d630fb47..b110e808 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/fragments/CollapsingToolbarFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/fragments/CollapsingToolbarFragment.kt @@ -9,6 +9,7 @@ import androidx.annotation.CallSuper import androidx.annotation.IdRes import androidx.annotation.StringRes import androidx.coordinatorlayout.widget.CoordinatorLayout +import com.google.android.material.R as materialRes import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.CollapsingToolbarLayout import com.google.android.material.appbar.MaterialToolbar @@ -19,7 +20,6 @@ import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.getAttrColor import com.thewizrd.shared_resources.utils.ContextUtils.getAttrResourceId import com.thewizrd.shared_resources.utils.UserThemeMode -import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.databinding.FragmentCollapsingtoolbarLayoutBinding abstract class CollapsingToolbarFragment : WindowColorFragment() { @@ -66,7 +66,7 @@ abstract class CollapsingToolbarFragment : WindowColorFragment() { protected fun setNavigationIconVisible(visible: Boolean) { if (visible) { - toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(R.attr.homeAsUpIndicator)) + toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(androidx.appcompat.R.attr.homeAsUpIndicator)) } else { toolbar.navigationIcon = null } @@ -82,7 +82,7 @@ abstract class CollapsingToolbarFragment : WindowColorFragment() { override fun updateWindowColors() { context?.let { ctx -> var backgroundColor = ctx.getAttrColor(android.R.attr.colorBackground) - var statusBarColor = ctx.getAttrColor(R.attr.colorSurface) + var statusBarColor = ctx.getAttrColor(materialRes.attr.colorSurface) if (settingsManager.getUserThemeMode() === UserThemeMode.AMOLED_DARK) { statusBarColor = Colors.BLACK backgroundColor = statusBarColor diff --git a/app/src/main/java/com/thewizrd/simpleweather/fragments/LargeCollapsingToolbarFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/fragments/LargeCollapsingToolbarFragment.kt index bc572a6f..4672f24f 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/fragments/LargeCollapsingToolbarFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/fragments/LargeCollapsingToolbarFragment.kt @@ -9,6 +9,7 @@ import androidx.annotation.CallSuper import androidx.annotation.IdRes import androidx.annotation.StringRes import androidx.coordinatorlayout.widget.CoordinatorLayout +import com.google.android.material.R as materialRes import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.CollapsingToolbarLayout import com.google.android.material.appbar.MaterialToolbar @@ -19,9 +20,7 @@ import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.getAttrColor import com.thewizrd.shared_resources.utils.ContextUtils.getAttrResourceId import com.thewizrd.shared_resources.utils.UserThemeMode -import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.databinding.FragmentCollapsingtoolbarLargeLayoutBinding -import com.thewizrd.simpleweather.databinding.FragmentCollapsingtoolbarLayoutBinding abstract class LargeCollapsingToolbarFragment : WindowColorFragment() { // Views @@ -67,7 +66,7 @@ abstract class LargeCollapsingToolbarFragment : WindowColorFragment() { protected fun setNavigationIconVisible(visible: Boolean) { if (visible) { - toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(R.attr.homeAsUpIndicator)) + toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(androidx.appcompat.R.attr.homeAsUpIndicator)) } else { toolbar.navigationIcon = null } @@ -83,7 +82,7 @@ abstract class LargeCollapsingToolbarFragment : WindowColorFragment() { override fun updateWindowColors() { context?.let { ctx -> var backgroundColor = ctx.getAttrColor(android.R.attr.colorBackground) - var statusBarColor = ctx.getAttrColor(R.attr.colorSurface) + var statusBarColor = ctx.getAttrColor(materialRes.attr.colorSurface) if (settingsManager.getUserThemeMode() === UserThemeMode.AMOLED_DARK) { statusBarColor = Colors.BLACK backgroundColor = statusBarColor diff --git a/app/src/main/java/com/thewizrd/simpleweather/fragments/ToolbarFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/fragments/ToolbarFragment.kt index 53642f89..fa8a7091 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/fragments/ToolbarFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/fragments/ToolbarFragment.kt @@ -9,6 +9,7 @@ import androidx.annotation.CallSuper import androidx.annotation.IdRes import androidx.annotation.StringRes import androidx.coordinatorlayout.widget.CoordinatorLayout +import com.google.android.material.R as materialRes import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.MaterialToolbar import com.google.android.material.shape.MaterialShapeDrawable @@ -63,7 +64,7 @@ abstract class ToolbarFragment : WindowColorFragment() { protected fun setNavigationIconVisible(visible: Boolean) { if (visible) { - toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(R.attr.homeAsUpIndicator)) + toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(androidx.appcompat.R.attr.homeAsUpIndicator)) } else { toolbar.navigationIcon = null } @@ -79,7 +80,7 @@ abstract class ToolbarFragment : WindowColorFragment() { override fun updateWindowColors() { context?.let { ctx -> var backgroundColor = ctx.getAttrColor(android.R.attr.colorBackground) - var statusBarColor = ctx.getAttrColor(R.attr.colorSurface) + var statusBarColor = ctx.getAttrColor(materialRes.attr.colorSurface) if (settingsManager.getUserThemeMode() === UserThemeMode.AMOLED_DARK) { statusBarColor = Colors.BLACK backgroundColor = statusBarColor diff --git a/app/src/main/java/com/thewizrd/simpleweather/helpers/ItemTouchHelperCallback.java b/app/src/main/java/com/thewizrd/simpleweather/helpers/ItemTouchHelperCallback.java index e283d729..a7f04aa0 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/helpers/ItemTouchHelperCallback.java +++ b/app/src/main/java/com/thewizrd/simpleweather/helpers/ItemTouchHelperCallback.java @@ -41,7 +41,7 @@ public ItemTouchHelperCallback(@NonNull Context context, @NonNull ItemTouchHelpe mAdapter = adapter; Drawable deleteIcoDrawable = ContextCompat.getDrawable(context, R.drawable.ic_delete_outline_24dp); deleteIcon = DrawableCompat.wrap(deleteIcoDrawable); - DrawableCompat.setTint(deleteIcon, ContextUtils.getAttrColor(context, R.attr.colorOnError)); + DrawableCompat.setTint(deleteIcon, ContextUtils.getAttrColor(context, com.google.android.material.R.attr.colorOnError)); deleteBackground = ContextCompat.getDrawable(context, R.drawable.swipe_delete); iconMargin = context.getResources().getDimensionPixelSize(R.dimen.delete_icon_margin); } diff --git a/app/src/main/java/com/thewizrd/simpleweather/main/LocationsFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/main/LocationsFragment.kt index ba25fce0..d2aae39d 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/main/LocationsFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/main/LocationsFragment.kt @@ -18,6 +18,7 @@ import androidx.activity.OnBackPressedCallback import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.launch import androidx.annotation.ColorInt +import androidx.appcompat.R as appcompatRes import androidx.appcompat.widget.Toolbar import androidx.core.animation.doOnEnd import androidx.core.app.ActivityOptionsCompat @@ -44,6 +45,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.ItemDecoration import androidx.transition.TransitionManager +import com.google.android.material.R as materialRes import com.google.android.material.animation.ArgbEvaluatorCompat import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.snackbar.BaseTransientBottomBar @@ -56,6 +58,7 @@ import com.thewizrd.common.helpers.OnListChangedListener import com.thewizrd.common.utils.ActivityUtils.setLightStatusBar import com.thewizrd.common.utils.ErrorMessage import com.thewizrd.common.viewmodels.LocationSearchResult +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.di.localBroadcastManager @@ -136,7 +139,7 @@ class LocationsFragment : ToolbarFragment() { private lateinit var onBackPressedCallback: OnBackPressedCallback override val titleResId: Int - get() = R.string.label_nav_locations + get() = sharedRes.string.label_nav_locations override fun createSnackManager(activity: Activity): SnackbarManager { return SnackbarManager(rootView).apply { @@ -199,7 +202,7 @@ class LocationsFragment : ToolbarFragment() { showSnackbar( Snackbar.make( it, - R.string.error_location_denied, + sharedRes.string.error_location_denied, Snackbar.Duration.SHORT ) ) @@ -632,7 +635,7 @@ class LocationsFragment : ToolbarFragment() { ErrorStatus.NETWORKERROR, ErrorStatus.NOWEATHER -> { val snackbar = Snackbar.make(rootView.context, wEx.message, Snackbar.Duration.LONG) - snackbar.setAction(R.string.action_retry) { + snackbar.setAction(sharedRes.string.action_retry) { locationsViewModel.refreshLocations() } showSnackbar(snackbar) @@ -640,7 +643,7 @@ class LocationsFragment : ToolbarFragment() { ErrorStatus.LOCATIONNOTSUPPORTED -> { showSnackbar( Snackbar.make(rootView.context, wEx.message, Snackbar.Duration.LONG).apply { - setAction(R.string.action_settings) { + setAction(sharedRes.string.action_settings) { runCatching { rootView.findNavController() .safeNavigate(NavGraphDirections.actionGlobalSettingsFragment()) @@ -787,11 +790,11 @@ class LocationsFragment : ToolbarFragment() { if (inEditMode) { val navIcon = - ContextCompat.getDrawable(toolbar.context, R.drawable.ic_close_white_24dp)!! + ContextCompat.getDrawable(toolbar.context, sharedRes.drawable.ic_close_white_24dp)!! .mutate() DrawableCompat.setTint( navIcon, - toolbar.context.getAttrColor(R.attr.colorOnPrimary) + toolbar.context.getAttrColor(materialRes.attr.colorOnPrimary) ) toolbar.navigationIcon = navIcon toolbar.setNavigationOnClickListener { @@ -812,7 +815,7 @@ class LocationsFragment : ToolbarFragment() { toolbar.setTitle(titleResId) toolbar.setTitleTextAppearance( toolbar.context, - toolbar.context.getAttrResourceId(R.attr.textAppearanceHeadline6) + toolbar.context.getAttrResourceId(materialRes.attr.textAppearanceHeadline6) ) (activity as? WindowColorManager)?.updateWindowColors() } @@ -834,14 +837,14 @@ class LocationsFragment : ToolbarFragment() { } MenuItemCompat.setIconTintList( it, - ColorStateList.valueOf(toolbar.context.getAttrColor(R.attr.colorOnPrimary)) + ColorStateList.valueOf(toolbar.context.getAttrColor(materialRes.attr.colorOnPrimary)) ) } R.id.action_done -> { it.isVisible = inEditMode MenuItemCompat.setIconTintList( it, - ColorStateList.valueOf(toolbar.context.getAttrColor(R.attr.colorOnPrimary)) + ColorStateList.valueOf(toolbar.context.getAttrColor(materialRes.attr.colorOnPrimary)) ) } else -> it.isVisible = !inEditMode @@ -850,9 +853,9 @@ class LocationsFragment : ToolbarFragment() { runAppBarAnimation( if (inEditMode) { - appBarLayout.context.getAttrColor(R.attr.colorPrimary) + appBarLayout.context.getAttrColor(appcompatRes.attr.colorPrimary) } else { - appBarLayout.context.getAttrColor(R.attr.colorSurface) + appBarLayout.context.getAttrColor(materialRes.attr.colorSurface) } ) } @@ -870,7 +873,7 @@ class LocationsFragment : ToolbarFragment() { if (mEditMode) { activity?.let { - val statusBarColor = it.getAttrColor(R.attr.colorPrimary) + val statusBarColor = it.getAttrColor(appcompatRes.attr.colorPrimary) if (appBarLayout.background is MaterialShapeDrawable) { val materialShapeDrawable = appBarLayout.background as MaterialShapeDrawable @@ -895,7 +898,7 @@ class LocationsFragment : ToolbarFragment() { materialShapeDrawable.fillColor?.defaultColor } else { (appBarLayout.background as? ColorDrawable)?.color - } ?: appBarLayout.context.getAttrColor(R.attr.colorSurface) + } ?: appBarLayout.context.getAttrColor(materialRes.attr.colorSurface) if (colorFrom != colorTo) { if (mAppBarAnimator?.isRunning == true) { mAppBarAnimator?.cancel() diff --git a/app/src/main/java/com/thewizrd/simpleweather/main/MainActivity.kt b/app/src/main/java/com/thewizrd/simpleweather/main/MainActivity.kt index 5831e506..1b2d909b 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/main/MainActivity.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/main/MainActivity.kt @@ -394,7 +394,7 @@ class MainActivity : WindowColorActivity() { private fun updateWindowColors(mode: UserThemeMode) { var backgroundColor = getAttrColor(android.R.attr.colorBackground) - var navBarColor = getAttrColor(R.attr.colorSurface) + var navBarColor = getAttrColor(com.google.android.material.R.attr.colorSurface) if (mode == UserThemeMode.AMOLED_DARK) { backgroundColor = Colors.BLACK navBarColor = Colors.BLACK diff --git a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherAQIFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherAQIFragment.kt index 8d07abb2..dcf2ecaf 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherAQIFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherAQIFragment.kt @@ -18,6 +18,7 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.material.snackbar.BaseTransientBottomBar import com.thewizrd.common.controls.AirQualityViewModel import com.thewizrd.common.helpers.SimpleRecyclerViewAdapterObserver +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.locationdata.LocationData @@ -118,7 +119,7 @@ class WeatherAQIFragment : CollapsingToolbarFragment() { binding.lifecycleOwner = viewLifecycleOwner // Setup Actionbar - toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(R.attr.homeAsUpIndicator)) + toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(androidx.appcompat.R.attr.homeAsUpIndicator)) toolbar.setNavigationOnClickListener { activity?.onBackPressedDispatcher?.onBackPressed() } // use this setting to improve performance if you know that changes @@ -246,7 +247,7 @@ class WeatherAQIFragment : CollapsingToolbarFragment() { } override val titleResId: Int - get() = R.string.label_airquality + get() = sharedRes.string.label_airquality private fun initialize() { if (locationData == null) { diff --git a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherAlertFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherAlertFragment.kt index d72b0655..a8e08e0a 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherAlertFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherAlertFragment.kt @@ -17,6 +17,7 @@ import com.google.android.material.transition.MaterialFadeThrough import com.thewizrd.common.adapters.WeatherAlertPanelAdapter import com.thewizrd.common.controls.WeatherAlertsViewModel import com.thewizrd.common.helpers.SimpleRecyclerViewAdapterObserver +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.locationdata.LocationData @@ -73,7 +74,7 @@ class WeatherAlertFragment : CollapsingToolbarFragment() { binding.lifecycleOwner = viewLifecycleOwner // Setup Actionbar - toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(R.attr.homeAsUpIndicator)) + toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(androidx.appcompat.R.attr.homeAsUpIndicator)) toolbar.setNavigationOnClickListener { activity?.onBackPressedDispatcher?.onBackPressed() } // use this setting to improve performance if you know that changes @@ -126,7 +127,7 @@ class WeatherAlertFragment : CollapsingToolbarFragment() { } override val titleResId: Int - get() = R.string.title_fragment_alerts + get() = sharedRes.string.title_fragment_alerts private suspend fun initialize() { if (locationData == null) { diff --git a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherChartsFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherChartsFragment.kt index 04f03eae..595acfa5 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherChartsFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherChartsFragment.kt @@ -17,6 +17,7 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.material.snackbar.BaseTransientBottomBar import com.thewizrd.common.helpers.SimpleRecyclerViewAdapterObserver import com.thewizrd.shared_resources.Constants +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.utils.AnalyticsLogger @@ -115,7 +116,7 @@ class WeatherChartsFragment : CollapsingToolbarFragment() { binding.lifecycleOwner = viewLifecycleOwner // Setup Actionbar - toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(R.attr.homeAsUpIndicator)) + toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(androidx.appcompat.R.attr.homeAsUpIndicator)) toolbar.setNavigationOnClickListener { activity?.onBackPressedDispatcher?.onBackPressed() } // use this setting to improve performance if you know that changes @@ -224,7 +225,7 @@ class WeatherChartsFragment : CollapsingToolbarFragment() { } override val titleResId: Int - get() = R.string.label_forecast + get() = sharedRes.string.label_forecast private fun initialize() { if (locationData == null) { diff --git a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherListFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherListFragment.kt index 1edd4f81..88ae4e49 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherListFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherListFragment.kt @@ -25,6 +25,7 @@ import com.thewizrd.common.controls.ForecastsListViewModel import com.thewizrd.common.controls.HourlyForecastItemViewModel import com.thewizrd.common.controls.WeatherAlertsViewModel import com.thewizrd.common.helpers.SimpleRecyclerViewAdapterObserver +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.locationdata.LocationData @@ -146,7 +147,7 @@ class WeatherListFragment : CollapsingToolbarFragment() { binding.lifecycleOwner = viewLifecycleOwner // Setup Actionbar - toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(R.attr.homeAsUpIndicator)) + toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(androidx.appcompat.R.attr.homeAsUpIndicator)) toolbar.setNavigationOnClickListener { activity?.onBackPressedDispatcher?.onBackPressed() } // use this setting to improve performance if you know that changes @@ -249,9 +250,9 @@ class WeatherListFragment : CollapsingToolbarFragment() { override val titleResId: Int get() = when (weatherListType) { - WeatherListType.FORECAST, WeatherListType.HOURLYFORECAST -> R.string.label_forecast - WeatherListType.ALERTS -> R.string.title_fragment_alerts - else -> R.string.label_nav_weathernow + WeatherListType.FORECAST, WeatherListType.HOURLYFORECAST -> sharedRes.string.label_forecast + WeatherListType.ALERTS -> sharedRes.string.title_fragment_alerts + else -> sharedRes.string.label_nav_weathernow } private fun initialize() { diff --git a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherNowFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherNowFragment.kt index 1e634356..84a57d56 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherNowFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherNowFragment.kt @@ -56,11 +56,13 @@ import com.bumptech.glide.load.resource.bitmap.BitmapTransitionOptions import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.target.Target +import com.google.android.material.R as materialRes import com.google.android.material.color.DynamicColorsOptions import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.shape.MaterialShapeDrawable import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.transition.MaterialFadeThrough +import com.thewizrd.common.R as commonRes import com.thewizrd.common.controls.IconControl import com.thewizrd.common.controls.WeatherAlertsViewModel import com.thewizrd.common.helpers.ColorsUtils @@ -70,6 +72,7 @@ import com.thewizrd.common.location.LocationResult import com.thewizrd.common.utils.ActivityUtils.recreateCompat import com.thewizrd.common.utils.ErrorMessage import com.thewizrd.common.utils.isTextTruncated +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.di.settingsManager @@ -261,7 +264,7 @@ class WeatherNowFragment : AbstractWeatherListDetailFragment(), BannerManagerInt showSnackbar( Snackbar.make( binding.rootView.context, - R.string.error_location_denied, + sharedRes.string.error_location_denied, Snackbar.Duration.SHORT ), null ) @@ -444,8 +447,8 @@ class WeatherNowFragment : AbstractWeatherListDetailFragment(), BannerManagerInt // SwipeRefresh binding.refreshLayout.setRefreshingDelay(350) - binding.refreshLayout.setContainerColor(requireContext().getAttrColor(R.attr.colorPrimaryContainer)) - binding.refreshLayout.setIndicatorColor(requireContext().getAttrColor(R.attr.colorPrimary)) + binding.refreshLayout.setContainerColor(requireContext().getAttrColor(materialRes.attr.colorPrimaryContainer)) + binding.refreshLayout.setIndicatorColor(requireContext().getAttrColor(androidx.appcompat.R.attr.colorPrimary)) binding.refreshLayout.setOnRefreshListener { AnalyticsLogger.logEvent("WeatherNowFragment: onRefresh") wNowViewModel.refreshWeather(true) @@ -953,10 +956,10 @@ class WeatherNowFragment : AbstractWeatherListDetailFragment(), BannerManagerInt showBanner( Banner.make( binding.root.context, - R.string.prompt_location_not_set + sharedRes.string.prompt_location_not_set ).apply { - setBannerIcon(R.drawable.ic_location_off_24dp) - setPrimaryAction(R.string.label_fab_add_location) { + setBannerIcon(sharedRes.drawable.ic_location_off_24dp) + setPrimaryAction(sharedRes.string.label_fab_add_location) { binding.root.findNavController().safeNavigate( WeatherNowFragmentDirections.actionWeatherNowFragmentToLocationsFragment() ) @@ -1143,8 +1146,8 @@ class WeatherNowFragment : AbstractWeatherListDetailFragment(), BannerManagerInt override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) - binding.refreshLayout.setContainerColor(requireContext().getAttrColor(R.attr.colorPrimaryContainer)) - binding.refreshLayout.setIndicatorColor(requireContext().getAttrColor(R.attr.colorPrimary)) + binding.refreshLayout.setContainerColor(requireContext().getAttrColor(materialRes.attr.colorPrimaryContainer)) + binding.refreshLayout.setIndicatorColor(requireContext().getAttrColor(androidx.appcompat.R.attr.colorPrimary)) // Resize necessary views adjustConditionPanelLayout() @@ -1186,7 +1189,7 @@ class WeatherNowFragment : AbstractWeatherListDetailFragment(), BannerManagerInt wEx.message, Snackbar.Duration.LONG ).apply { - setAction(R.string.action_retry) { + setAction(sharedRes.string.action_retry) { wNowViewModel.refreshWeather(false) } }) @@ -1194,7 +1197,7 @@ class WeatherNowFragment : AbstractWeatherListDetailFragment(), BannerManagerInt ErrorStatus.LOCATIONNOTSUPPORTED -> { showSnackbar( Snackbar.make(binding.root.context, wEx.message, Snackbar.Duration.LONG).apply { - setAction(R.string.action_settings) { + setAction(sharedRes.string.action_settings) { runCatching { binding.root.findNavController() .safeNavigate(WeatherNowFragmentDirections.actionWeatherNowFragmentToSettingsFragment()) @@ -1224,7 +1227,7 @@ class WeatherNowFragment : AbstractWeatherListDetailFragment(), BannerManagerInt if (forceReload || (!ObjectsCompat.equals( imageView.tag, imageURI - ) || imageView.getTag(R.id.glide_custom_view_target_tag) == null) + ) || imageView.getTag(com.bumptech.glide.R.id.glide_custom_view_target_tag) == null) ) { imageView.tag = imageURI if (!imageURI.isNullOrBlank()) { @@ -1274,7 +1277,7 @@ class WeatherNowFragment : AbstractWeatherListDetailFragment(), BannerManagerInt .contentBasedSeedColor val dominantColor = seedColor ?: imageView.context.run { - getColor(R.color.colorPrimary) + getColor(sharedRes.color.colorPrimary) } val backgroundColor = @@ -1490,7 +1493,7 @@ class WeatherNowFragment : AbstractWeatherListDetailFragment(), BannerManagerInt override fun updateWindowColors() { context?.let { var backgroundColor = it.getAttrColor(android.R.attr.colorBackground) - var navBarColor = it.getAttrColor(R.attr.colorSurface) + var navBarColor = it.getAttrColor(materialRes.attr.colorSurface) var statusBarColor = navBarColor if (settingsManager.getUserThemeMode() == UserThemeMode.AMOLED_DARK) { backgroundColor = Colors.BLACK diff --git a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherRadarFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherRadarFragment.kt index ae3c2dff..d6574a50 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherRadarFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherRadarFragment.kt @@ -17,6 +17,7 @@ import androidx.lifecycle.repeatOnLifecycle import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.transition.MaterialContainerTransform import com.google.android.material.transition.MaterialFadeThrough +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.utils.AnalyticsLogger import com.thewizrd.shared_resources.utils.ContextUtils.getAttrResourceId import com.thewizrd.simpleweather.R @@ -62,7 +63,7 @@ class WeatherRadarFragment : ToolbarFragment() { ViewCompat.setTransitionName(binding.radarWebviewContainer, "radar") // Setup Actionbar - toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(R.attr.homeAsUpIndicator)) + toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(androidx.appcompat.R.attr.homeAsUpIndicator)) toolbar.setNavigationOnClickListener { activity?.onBackPressedDispatcher?.onBackPressed() } toolbar.inflateMenu(R.menu.radar) @@ -147,5 +148,5 @@ class WeatherRadarFragment : ToolbarFragment() { } override val titleResId: Int - get() = R.string.label_radar + get() = sharedRes.string.label_radar } \ No newline at end of file diff --git a/app/src/main/java/com/thewizrd/simpleweather/notifications/WeatherAlertNotificationBuilder.kt b/app/src/main/java/com/thewizrd/simpleweather/notifications/WeatherAlertNotificationBuilder.kt index 6979f716..2b7d68c8 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/notifications/WeatherAlertNotificationBuilder.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/notifications/WeatherAlertNotificationBuilder.kt @@ -1,5 +1,7 @@ package com.thewizrd.simpleweather.notifications +import android.Manifest +import android.annotation.SuppressLint import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager @@ -9,12 +11,14 @@ import android.content.Intent import android.graphics.drawable.Icon import android.os.Build import android.os.SystemClock +import androidx.annotation.RequiresPermission import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.core.net.toUri import com.thewizrd.common.controls.WeatherAlertViewModel import com.thewizrd.common.helpers.areNotificationsEnabled import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.helpers.toImmutableCompatFlag @@ -40,6 +44,7 @@ object WeatherAlertNotificationBuilder { private const val MIN_GROUPCOUNT = 3 private const val SUMMARY_ID = -1 + @SuppressLint("MissingPermission") suspend fun createNotifications(location: LocationData, alerts: Collection) = withContext(Dispatchers.Default) { val context = appLib.context @@ -75,7 +80,7 @@ object WeatherAlertNotificationBuilder { val alertIconResId = alertVM.alertType.getDrawableFromAlertType() val notification = NotificationUtils.createNotificationBuilder(context, NOT_CHANNEL_ID) - .setSmallIcon(R.drawable.ic_error) + .setSmallIcon(sharedRes.drawable.ic_error) .setStyle(Notification.BigTextStyle().bigText(alertVM.alertBodyMessage)) .setContentTitle(title) .setContentText(contentText) @@ -161,16 +166,16 @@ object WeatherAlertNotificationBuilder { inboxStyle.addLine(notif.value) } - inboxStyle.setBigContentTitle(context.getString(R.string.title_fragment_alerts)) - inboxStyle.setSummaryText(context.getString(R.string.app_name)) + inboxStyle.setBigContentTitle(context.getString(sharedRes.string.title_fragment_alerts)) + inboxStyle.setSummaryText(context.getString(sharedRes.string.app_name)) } else { - inboxStyle.setSummaryText(context.getString(R.string.title_fragment_alerts)) + inboxStyle.setSummaryText(context.getString(sharedRes.string.title_fragment_alerts)) } val mSummaryBuilder = NotificationCompat.Builder(context, NOT_CHANNEL_ID) - .setSmallIcon(R.drawable.ic_error) - .setContentTitle(context.getString(R.string.title_fragment_alerts)) - .setContentText(context.getString(R.string.app_name)) + .setSmallIcon(sharedRes.drawable.ic_error) + .setContentTitle(context.getString(sharedRes.string.title_fragment_alerts)) + .setContentText(context.getString(sharedRes.string.app_name)) .setStyle(inboxStyle) .setGroup(TAG) .setGroupSummary(true) @@ -245,8 +250,10 @@ object WeatherAlertNotificationBuilder { val mNotifyMgr = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager var mChannel = mNotifyMgr.getNotificationChannel(NOT_CHANNEL_ID) - val notchannel_name = context.resources.getString(R.string.not_channel_name_alerts) - val notchannel_desc = context.resources.getString(R.string.not_channel_desc_alerts) + val notchannel_name = + context.resources.getString(sharedRes.string.not_channel_name_alerts) + val notchannel_desc = + context.resources.getString(sharedRes.string.not_channel_desc_alerts) if (mChannel == null) { mChannel = NotificationChannel(NOT_CHANNEL_ID, notchannel_name, NotificationManager.IMPORTANCE_DEFAULT) } diff --git a/app/src/main/java/com/thewizrd/simpleweather/notifications/WeatherNotificationWorker.kt b/app/src/main/java/com/thewizrd/simpleweather/notifications/WeatherNotificationWorker.kt index 85b1ff5d..4d27ce58 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/notifications/WeatherNotificationWorker.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/notifications/WeatherNotificationWorker.kt @@ -17,6 +17,7 @@ import com.thewizrd.common.helpers.areNotificationsEnabled import com.thewizrd.common.weatherdata.WeatherDataLoader import com.thewizrd.common.weatherdata.WeatherRequest import com.thewizrd.common.weatherdata.WeatherResult +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.preferences.SettingsManager import com.thewizrd.shared_resources.utils.Logger import com.thewizrd.simpleweather.R @@ -165,8 +166,10 @@ class WeatherNotificationWorker(context: Context, workerParams: WorkerParameters if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { var mChannel = mNotifyMgr.getNotificationChannel(NOT_CHANNEL_ID) - val notchannel_name = context.resources.getString(R.string.not_channel_name_weather) - val notchannel_desc = context.resources.getString(R.string.not_channel_desc_weather) + val notchannel_name = + context.resources.getString(sharedRes.string.not_channel_name_weather) + val notchannel_desc = + context.resources.getString(sharedRes.string.not_channel_desc_weather) if (mChannel == null) { mChannel = NotificationChannel(NOT_CHANNEL_ID, notchannel_name, NotificationManager.IMPORTANCE_LOW) diff --git a/app/src/main/java/com/thewizrd/simpleweather/preferences/ArrayMultiSelectListPreference.java b/app/src/main/java/com/thewizrd/simpleweather/preferences/ArrayMultiSelectListPreference.java index 6b6a2afc..4eb82501 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/preferences/ArrayMultiSelectListPreference.java +++ b/app/src/main/java/com/thewizrd/simpleweather/preferences/ArrayMultiSelectListPreference.java @@ -13,8 +13,6 @@ import androidx.preference.ListPreference; import androidx.preference.MultiSelectListPreference; -import com.thewizrd.simpleweather.R; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -208,7 +206,7 @@ public static ArrayMultiSelectListPreference.SimpleSummaryProvider getInstance() @Override public CharSequence provideSummary(ArrayMultiSelectListPreference preference) { if (preference.getValues() == null || preference.getValues().isEmpty()) { - return (preference.getContext().getString(R.string.not_set)); + return (preference.getContext().getString(androidx.preference.R.string.not_set)); } else { SpannableStringBuilder sb = new SpannableStringBuilder(); diff --git a/app/src/main/java/com/thewizrd/simpleweather/preferences/BaseSettingsFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/preferences/BaseSettingsFragment.kt index cd3a481a..59e44dbd 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/preferences/BaseSettingsFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/preferences/BaseSettingsFragment.kt @@ -10,6 +10,7 @@ import com.google.android.material.timepicker.TimeFormat import com.thewizrd.common.helpers.LocationPermissionLauncher import com.thewizrd.common.helpers.backgroundLocationPermissionEnabled import com.thewizrd.common.helpers.getBackgroundLocationRationale +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.preferences.timepickerpreference.TimePickerPreference @@ -44,7 +45,7 @@ abstract class BaseSettingsFragment : ToolbarPreferenceFragmentCompat() { showSnackbar( Snackbar.make( it, - R.string.error_location_denied, + sharedRes.string.error_location_denied, Snackbar.Duration.SHORT ) ) diff --git a/app/src/main/java/com/thewizrd/simpleweather/preferences/DevSettingsFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/preferences/DevSettingsFragment.kt index f6741fb9..72bd1adb 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/preferences/DevSettingsFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/preferences/DevSettingsFragment.kt @@ -12,11 +12,11 @@ import androidx.preference.Preference import androidx.preference.PreferenceCategory import androidx.preference.SwitchPreference import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.utils.Logger import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.simpleweather.BuildConfig -import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.extras.updateFirebaseIdPreference import timber.log.Timber import java.io.File @@ -25,7 +25,7 @@ import java.io.FileOutputStream class DevSettingsFragment : ToolbarPreferenceFragmentCompat() { override val titleResId: Int - get() = R.string.title_dev_settings + get() = sharedRes.string.title_dev_settings private lateinit var intentLauncher: ActivityResultLauncher private var mLogFile: File? = null diff --git a/app/src/main/java/com/thewizrd/simpleweather/preferences/SettingsFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/preferences/SettingsFragment.kt index 2306663b..42dc9169 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/preferences/SettingsFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/preferences/SettingsFragment.kt @@ -39,8 +39,10 @@ import androidx.recyclerview.widget.ConcatAdapter import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.R as materialRes import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.shape.MaterialShapeDrawable +import com.thewizrd.common.R as commonRes import com.thewizrd.common.helpers.ListChangedArgs import com.thewizrd.common.helpers.OnListChangedListener import com.thewizrd.common.helpers.PermissionLauncher @@ -51,6 +53,7 @@ import com.thewizrd.common.helpers.notificationPermissionEnabled import com.thewizrd.common.helpers.openAppSettingsActivity import com.thewizrd.common.preferences.KeyEntryPreferenceDialogFragment import com.thewizrd.common.utils.ActivityUtils.recreateCompat +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.controls.ProviderEntry @@ -165,7 +168,7 @@ class SettingsFragment : BaseSettingsFragment(), } override val titleResId: Int - get() = R.string.title_activity_settings + get() = sharedRes.string.title_activity_settings /** * Registers a listener. @@ -220,7 +223,7 @@ class SettingsFragment : BaseSettingsFragment(), showSnackbar( Snackbar.make( it, - R.string.message_enter_apikey, + sharedRes.string.message_enter_apikey, Snackbar.Duration.LONG ) ) @@ -247,7 +250,7 @@ class SettingsFragment : BaseSettingsFragment(), showSnackbar( Snackbar.make( it, - R.string.error_location_denied, + sharedRes.string.error_location_denied, Snackbar.Duration.SHORT ) ) @@ -425,7 +428,7 @@ class SettingsFragment : BaseSettingsFragment(), showSnackbar( Snackbar.make( it, - R.string.error_enable_location_services, + sharedRes.string.error_enable_location_services, Snackbar.Duration.SHORT ) ) @@ -456,11 +459,11 @@ class SettingsFragment : BaseSettingsFragment(), } intervalPref = findPreference(SettingsManager.KEY_REFRESHINTERVAL)!! if (enableAdditionalRefreshIntervals()) { - intervalPref.setEntries(R.array.premium_refreshinterval_entries) - intervalPref.setEntryValues(R.array.premium_refreshinterval_values) + intervalPref.setEntries(sharedRes.array.premium_refreshinterval_entries) + intervalPref.setEntryValues(sharedRes.array.premium_refreshinterval_values) } else { - intervalPref.setEntries(R.array.refreshinterval_entries) - intervalPref.setEntryValues(R.array.refreshinterval_values) + intervalPref.setEntries(sharedRes.array.refreshinterval_entries) + intervalPref.setEntryValues(sharedRes.array.refreshinterval_values) } themePref = findPreference(SettingsManager.KEY_USERTHEME)!! @@ -786,7 +789,7 @@ class SettingsFragment : BaseSettingsFragment(), val code = langCodes[i] if (TextUtils.isEmpty(code)) { - langEntries[i] = requireContext().getString(R.string.summary_default) + langEntries[i] = requireContext().getString(sharedRes.string.summary_default) } else { val localeCode = code.toString() val locale = LocaleUtils.getLocaleForTag(localeCode) @@ -797,7 +800,7 @@ class SettingsFragment : BaseSettingsFragment(), languagePref.summaryProvider = SummaryProvider { preference -> if (preference.value.isNullOrBlank()) { - preference.context.getString(R.string.summary_default) + preference.context.getString(sharedRes.string.summary_default) } else { LocaleUtils.getLocaleDisplayName() } @@ -859,7 +862,7 @@ class SettingsFragment : BaseSettingsFragment(), findPreference(KEY_WEATHERNOTIFICATION)?.apply { summary = - "${getString(R.string.pref_title_onnotification)}, ${getString(R.string.not_channel_name_dailynotification)}".toPascalCase() + "${getString(sharedRes.string.pref_title_onnotification)}, ${getString(R.string.not_channel_name_dailynotification)}".toPascalCase() setOnPreferenceClickListener { // Display the fragment as the main content. activity?.findNavController(R.id.fragment_container) @@ -870,7 +873,7 @@ class SettingsFragment : BaseSettingsFragment(), findPreference(KEY_ALERTS)?.apply { summary = - "${getString(R.string.pref_title_alerts)}, ${getString(R.string.not_channel_name_precipnotification)}".toPascalCase() + "${getString(sharedRes.string.pref_title_alerts)}, ${getString(R.string.not_channel_name_precipnotification)}".toPascalCase() setOnPreferenceClickListener { // Display the fragment as the main content. activity?.findNavController(R.id.fragment_container) @@ -925,7 +928,7 @@ class SettingsFragment : BaseSettingsFragment(), } else { Toast.makeText( it.context, - R.string.message_keyinvalid, + sharedRes.string.message_keyinvalid, Toast.LENGTH_SHORT ).show() } @@ -974,12 +977,14 @@ class SettingsFragment : BaseSettingsFragment(), val keyVerified = settingsManager.isKeyVerified(providerPref.value) val colorSpan = ForegroundColorSpan(if (keyVerified) Color.GREEN else Color.RED) val summary = SpannableString( - if (keyVerified) getString(R.string.message_keyverified) else getString(R.string.message_keyinvalid) + if (keyVerified) getString(sharedRes.string.message_keyverified) else getString( + sharedRes.string.message_keyinvalid + ) ) summary.setSpan(colorSpan, 0, summary.length, 0) keyEntry.summary = summary } else { - keyEntry.summary = getString(R.string.pref_summary_apikey, providerAPI) + keyEntry.summary = getString(sharedRes.string.pref_summary_apikey, providerAPI) } } @@ -1066,7 +1071,7 @@ class SettingsFragment : BaseSettingsFragment(), private var unitsChanged = false override val titleResId: Int - get() = R.string.pref_title_units + get() = sharedRes.string.pref_title_units override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.pref_units, null) @@ -1087,8 +1092,8 @@ class SettingsFragment : BaseSettingsFragment(), Preference.OnPreferenceClickListener { activity?.let { MaterialAlertDialogBuilder(it) - .setTitle(R.string.pref_title_units) - .setItems(R.array.default_units) { dialog, which -> + .setTitle(sharedRes.string.pref_title_units) + .setItems(sharedRes.array.default_units) { dialog, which -> val isFahrenheit: Boolean = which == 0 tempUnitPref.value = if (isFahrenheit) Units.FAHRENHEIT else Units.CELSIUS @@ -1129,7 +1134,7 @@ class SettingsFragment : BaseSettingsFragment(), class IconsFragment : IconProviderPickerFragment() { override val titleResId: Int - get() = R.string.pref_title_icons + get() = sharedRes.string.pref_title_icons override fun getDefaultKey(): String { return settingsManager.getIconsProvider() @@ -1192,7 +1197,7 @@ class SettingsFragment : BaseSettingsFragment(), binding.lifecycleOwner = this.viewLifecycleOwner // Setup Actionbar - toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(R.attr.homeAsUpIndicator)) + toolbar.setNavigationIcon(toolbar.context.getAttrResourceId(androidx.appcompat.R.attr.homeAsUpIndicator)) toolbar.setNavigationOnClickListener { activity?.onBackPressedDispatcher?.onBackPressed() } appBarLayout.setExpanded(false) @@ -1220,7 +1225,7 @@ class SettingsFragment : BaseSettingsFragment(), }.also { nonOrderableFeaturesAdapter = it }, SpacerAdapter(requireContext().dpToPx(4f).toInt()), ButtonAdapter( - resId = R.string.action_reset, + resId = sharedRes.string.action_reset, padding = context?.dpToPx(8f)?.toInt() ?: 0, gravity = Gravity.CENTER ) { @@ -1334,8 +1339,8 @@ class SettingsFragment : BaseSettingsFragment(), @SuppressLint("MissingSuperCall") override fun updateWindowColors() { context?.let { ctx -> - var backgroundColor = ctx.getAttrColor(R.attr.colorSurfaceContainer) - var statusBarColor = ctx.getAttrColor(R.attr.colorSurfaceContainer) + var backgroundColor = ctx.getAttrColor(materialRes.attr.colorSurfaceContainer) + var statusBarColor = ctx.getAttrColor(materialRes.attr.colorSurfaceContainer) if (settingsManager.getUserThemeMode() === UserThemeMode.AMOLED_DARK) { statusBarColor = Colors.BLACK backgroundColor = Colors.BLACK @@ -1369,7 +1374,7 @@ class SettingsFragment : BaseSettingsFragment(), private lateinit var onGoingNotifPermissionLauncher: PermissionLauncher override val titleResId: Int - get() = R.string.pref_title_onnotification + get() = sharedRes.string.pref_title_onnotification override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -1382,10 +1387,10 @@ class SettingsFragment : BaseSettingsFragment(), showSnackbar( Snackbar.make( it, - R.string.notification_perm_denied, + sharedRes.string.notification_perm_denied, Snackbar.Duration.SHORT ).apply { - setAction(R.string.action_settings) { + setAction(sharedRes.string.action_settings) { runCatching { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { it.context.openAppNotificationSettingsActivity() @@ -1487,7 +1492,7 @@ class SettingsFragment : BaseSettingsFragment(), private lateinit var popChanceNotifPermissionLauncher: PermissionLauncher override val titleResId: Int - get() = R.string.label_nav_alerts + get() = sharedRes.string.label_nav_alerts override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -1500,10 +1505,10 @@ class SettingsFragment : BaseSettingsFragment(), showSnackbar( Snackbar.make( it, - R.string.notification_perm_denied, + sharedRes.string.notification_perm_denied, Snackbar.Duration.SHORT ).apply { - setAction(R.string.action_settings) { + setAction(sharedRes.string.action_settings) { runCatching { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { it.context.openAppNotificationSettingsActivity() @@ -1525,10 +1530,10 @@ class SettingsFragment : BaseSettingsFragment(), showSnackbar( Snackbar.make( it, - R.string.notification_perm_denied, + sharedRes.string.notification_perm_denied, Snackbar.Duration.SHORT ).apply { - setAction(R.string.action_settings) { + setAction(sharedRes.string.action_settings) { runCatching { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { it.context.openAppNotificationSettingsActivity() @@ -1614,7 +1619,7 @@ class SettingsFragment : BaseSettingsFragment(), private fun updateAlertPreference(enable: Boolean) { alertNotification.isEnabled = enable alertNotification.summary = - if (enable) getString(R.string.pref_summary_alerts) else getString(R.string.pref_summary_alerts_disabled) + if (enable) getString(sharedRes.string.pref_summary_alerts) else getString(sharedRes.string.pref_summary_alerts_disabled) } } @@ -1633,7 +1638,7 @@ class SettingsFragment : BaseSettingsFragment(), private lateinit var devSettingsController: DevSettingsController override val titleResId: Int - get() = R.string.pref_title_about + get() = sharedRes.string.pref_title_about override fun onCreate(savedInstanceState: Bundle?) { devSettingsController = DevSettingsController(this, KEY_ABOUTVERSION) @@ -1708,7 +1713,7 @@ class SettingsFragment : BaseSettingsFragment(), } override val titleResId: Int - get() = R.string.pref_title_credits + get() = sharedRes.string.pref_title_credits override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.pref_credits, null) @@ -1748,7 +1753,7 @@ class SettingsFragment : BaseSettingsFragment(), class OSSCreditsFragment : BaseSettingsFragment() { override val titleResId: Int - get() = R.string.pref_title_oslibs + get() = sharedRes.string.pref_title_oslibs override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.pref_oslibs, null) diff --git a/app/src/main/java/com/thewizrd/simpleweather/preferences/SettingsPreferenceGroupAdapter.kt b/app/src/main/java/com/thewizrd/simpleweather/preferences/SettingsPreferenceGroupAdapter.kt index 64a23de4..f4175328 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/preferences/SettingsPreferenceGroupAdapter.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/preferences/SettingsPreferenceGroupAdapter.kt @@ -29,6 +29,7 @@ import androidx.preference.PreferenceCategory import androidx.preference.PreferenceGroup import androidx.preference.PreferenceGroupAdapter import androidx.preference.PreferenceViewHolder +import com.google.android.material.R as materialRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.getAttrColor @@ -187,7 +188,7 @@ class SettingsPreferenceGroupAdapter(preferenceGroup: PreferenceGroup) : if (settingsManager.getUserThemeMode() == UserThemeMode.AMOLED_DARK) { v.backgroundTintList = ColorStateList.valueOf( ColorUtils.compositeColors( - v.context.getAttrColor(R.attr.colorSurfaceDim), + v.context.getAttrColor(materialRes.attr.colorSurfaceDim), Colors.BLACK ) ) diff --git a/app/src/main/java/com/thewizrd/simpleweather/preferences/ToolbarPreferenceFragmentCompat.kt b/app/src/main/java/com/thewizrd/simpleweather/preferences/ToolbarPreferenceFragmentCompat.kt index 6036e7cb..55e4d347 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/preferences/ToolbarPreferenceFragmentCompat.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/preferences/ToolbarPreferenceFragmentCompat.kt @@ -14,6 +14,7 @@ import androidx.annotation.StringRes import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.preference.Preference import androidx.preference.PreferenceGroup +import com.google.android.material.R as materialRes import com.google.android.material.appbar.AppBarLayout import com.google.android.material.appbar.AppBarLayout.ScrollingViewBehavior import com.google.android.material.appbar.CollapsingToolbarLayout @@ -84,7 +85,7 @@ abstract class ToolbarPreferenceFragmentCompat : WindowColorPreferenceFragmentCo override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - preferenceScreen.tintIcons(requireContext().getAttrColor(R.attr.colorPrimary)) + preferenceScreen.tintIcons(requireContext().getAttrColor(androidx.appcompat.R.attr.colorPrimary)) // Toolbar binding.toolbar.setTitle(titleResId) @@ -99,8 +100,8 @@ abstract class ToolbarPreferenceFragmentCompat : WindowColorPreferenceFragmentCo @SuppressLint("NotifyDataSetChanged") protected fun updateWindowColors(mode: UserThemeMode) { activity?.let { - var backgroundColor = it.getAttrColor(R.attr.colorSurfaceContainer) - var statusBarColor = it.getAttrColor(R.attr.colorSurfaceContainer) + var backgroundColor = it.getAttrColor(materialRes.attr.colorSurfaceContainer) + var statusBarColor = it.getAttrColor(materialRes.attr.colorSurfaceContainer) if (mode == UserThemeMode.AMOLED_DARK) { statusBarColor = Colors.BLACK backgroundColor = Colors.BLACK diff --git a/app/src/main/java/com/thewizrd/simpleweather/preferences/chippreference/ChipPreference.kt b/app/src/main/java/com/thewizrd/simpleweather/preferences/chippreference/ChipPreference.kt index 42b4858a..763c3e93 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/preferences/chippreference/ChipPreference.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/preferences/chippreference/ChipPreference.kt @@ -14,6 +14,7 @@ import androidx.core.content.res.use import androidx.preference.ListPreference import androidx.preference.Preference import androidx.preference.PreferenceViewHolder +import com.google.android.material.R as materialRes import com.google.android.material.chip.Chip import com.google.android.material.chip.ChipGroup import com.google.android.material.shape.RelativeCornerSize @@ -91,7 +92,10 @@ class ChipPreference @JvmOverloads constructor( ), intArrayOf( Colors.TRANSPARENT, - ContextCompat.getColor(context, R.color.material_on_surface_stroke) + ContextCompat.getColor( + context, + materialRes.color.material_on_surface_stroke + ) ) ) shapeAppearanceModel = if (index == 0 && entries.isNotEmpty()) { @@ -113,8 +117,8 @@ class ChipPreference @JvmOverloads constructor( intArrayOf(-android.R.attr.state_checked) ), intArrayOf( - context.getAttrColor(R.attr.colorPrimaryDark), - context.getAttrColor(R.attr.colorSurfaceContainer) + context.getAttrColor(androidx.appcompat.R.attr.colorPrimaryDark), + context.getAttrColor(materialRes.attr.colorSurfaceContainer) ) ) setTextColor( @@ -124,8 +128,8 @@ class ChipPreference @JvmOverloads constructor( intArrayOf(-android.R.attr.state_checked) ), intArrayOf( - context.getAttrColor(R.attr.colorOnPrimary), - context.getAttrColor(R.attr.colorOnSurface) + context.getAttrColor(materialRes.attr.colorOnPrimary), + context.getAttrColor(materialRes.attr.colorOnSurface) ) ) ) diff --git a/app/src/main/java/com/thewizrd/simpleweather/preferences/colorpreference/ColorPreference.java b/app/src/main/java/com/thewizrd/simpleweather/preferences/colorpreference/ColorPreference.java index 5ea9c477..6cd76849 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/preferences/colorpreference/ColorPreference.java +++ b/app/src/main/java/com/thewizrd/simpleweather/preferences/colorpreference/ColorPreference.java @@ -46,7 +46,7 @@ public ColorPreference(Context context) { @SuppressLint("RestrictedApi") public ColorPreference(Context context, AttributeSet attrs) { - this(context, attrs, TypedArrayUtils.getAttr(context, R.attr.preferenceStyle, + this(context, attrs, TypedArrayUtils.getAttr(context, androidx.preference.R.attr.preferenceStyle, android.R.attr.preferenceStyle)); } diff --git a/app/src/main/java/com/thewizrd/simpleweather/services/ServiceNotificationHelper.kt b/app/src/main/java/com/thewizrd/simpleweather/services/ServiceNotificationHelper.kt index 80e7f24c..3ab11bcd 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/services/ServiceNotificationHelper.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/services/ServiceNotificationHelper.kt @@ -9,6 +9,7 @@ import android.content.Intent import android.os.Build import androidx.annotation.RequiresApi import androidx.core.app.NotificationCompat +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.helpers.toImmutableCompatFlag import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.notifications.NotificationUtils @@ -22,7 +23,7 @@ internal object ServiceNotificationHelper { // Gets an instance of the NotificationManager service val mNotifyMgr = context.getSystemService(NotificationManager::class.java) var mChannel = mNotifyMgr.getNotificationChannel(NOT_CHANNEL_ID) - val notchannel_name = context.resources.getString(R.string.not_channel_name_general) + val notchannel_name = context.resources.getString(sharedRes.string.not_channel_name_general) if (mChannel == null) { mChannel = NotificationChannel(NOT_CHANNEL_ID, notchannel_name, NotificationManager.IMPORTANCE_LOW) } @@ -38,7 +39,7 @@ internal object ServiceNotificationHelper { internal fun createForegroundNotification(context: Context): Notification { val notif = NotificationCompat.Builder(context, NOT_CHANNEL_ID).apply { setSmallIcon(R.drawable.wi_cloud_refresh) - setSubText(context.getString(R.string.app_name)) + setSubText(context.getString(sharedRes.string.app_name)) setContentTitle(context.getString(R.string.message_widgetservice_running)) setOnlyAlertOnce(true) setSilent(true) diff --git a/app/src/main/java/com/thewizrd/simpleweather/services/WeatherUpdaterWorker.kt b/app/src/main/java/com/thewizrd/simpleweather/services/WeatherUpdaterWorker.kt index 5eb385cd..ce5a59ce 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/services/WeatherUpdaterWorker.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/services/WeatherUpdaterWorker.kt @@ -1,5 +1,6 @@ package com.thewizrd.simpleweather.services +import android.annotation.SuppressLint import android.app.Notification import android.content.Context import android.content.Intent @@ -23,6 +24,7 @@ import androidx.work.WorkManager import androidx.work.WorkerParameters import androidx.work.multiprocess.RemoteWorkManager import com.thewizrd.common.helpers.locationPermissionEnabled +import com.thewizrd.common.helpers.notificationPermissionEnabled import com.thewizrd.common.location.LocationProvider import com.thewizrd.common.location.LocationResult import com.thewizrd.common.utils.ErrorMessage @@ -30,6 +32,7 @@ import com.thewizrd.common.utils.LiveDataUtils.awaitWithTimeout import com.thewizrd.common.weatherdata.WeatherDataLoader import com.thewizrd.common.weatherdata.WeatherRequest import com.thewizrd.common.weatherdata.WeatherResult +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.preferences.SettingsManager @@ -150,9 +153,9 @@ class WeatherUpdaterWorker(context: Context, workerParams: WorkerParameters) : C } return NotificationCompat.Builder(context, NOT_CHANNEL_ID) - .setSmallIcon(R.drawable.ic_launcher_monochrome) - .setContentTitle(context.getString(R.string.not_title_weather_update)) - .setColor(ContextCompat.getColor(context, R.color.colorPrimary)) + .setSmallIcon(sharedRes.drawable.ic_launcher_monochrome) + .setContentTitle(context.getString(sharedRes.string.not_title_weather_update)) + .setColor(ContextCompat.getColor(context, sharedRes.color.colorPrimary)) .setOnlyAlertOnce(true) .setSilent(true) .setPriority(NotificationCompat.PRIORITY_LOW) @@ -170,6 +173,7 @@ class WeatherUpdaterWorker(context: Context, workerParams: WorkerParameters) : C } private object WeatherUpdaterHelper { + @SuppressLint("MissingPermission") suspend fun executeWork(context: Context): Result { var result = Result.success() @@ -333,7 +337,7 @@ class WeatherUpdaterWorker(context: Context, workerParams: WorkerParameters) : C val locMan = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager? if (locMan == null || !LocationManagerCompat.isLocationEnabled(locMan)) { - return LocationResult.Error(errorMessage = ErrorMessage.Resource(R.string.error_retrieve_location)) + return LocationResult.Error(errorMessage = ErrorMessage.Resource(sharedRes.string.error_retrieve_location)) } return locationProvider.getLatestLocationData(settingsManager.getLastGPSLocData()) diff --git a/app/src/main/java/com/thewizrd/simpleweather/setup/SetupActivity.kt b/app/src/main/java/com/thewizrd/simpleweather/setup/SetupActivity.kt index 1511982f..8297341e 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/setup/SetupActivity.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/setup/SetupActivity.kt @@ -19,6 +19,7 @@ import androidx.navigation.NavOptions import androidx.navigation.findNavController import androidx.navigation.fragment.NavHostFragment import androidx.transition.TransitionManager +import com.google.android.material.R as materialRes import com.google.android.material.transition.platform.MaterialContainerTransformSharedElementCallback import com.thewizrd.common.utils.ActivityUtils.setTransparentWindow import com.thewizrd.shared_resources.Constants @@ -77,7 +78,7 @@ class SetupActivity : UserLocaleActivity() { insets } - val color = getAttrColor(R.attr.colorPrimarySurface) + val color = getAttrColor(materialRes.attr.colorPrimarySurface) window.setTransparentWindow(color) lifecycleScope.launch { diff --git a/app/src/main/java/com/thewizrd/simpleweather/setup/SetupLocationFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/setup/SetupLocationFragment.kt index 0232d0ba..c144a5d1 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/setup/SetupLocationFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/setup/SetupLocationFragment.kt @@ -20,6 +20,7 @@ import com.thewizrd.common.helpers.locationPermissionEnabled import com.thewizrd.common.utils.ErrorMessage import com.thewizrd.common.viewmodels.LocationSearchResult import com.thewizrd.common.viewmodels.LocationSearchViewModel +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.locationdata.LocationData @@ -85,7 +86,7 @@ class SetupLocationFragment : CustomFragment() { showSnackbar( Snackbar.make( requireContext(), - R.string.error_location_denied, + sharedRes.string.error_location_denied, Snackbar.Duration.SHORT ) ) diff --git a/app/src/main/java/com/thewizrd/simpleweather/setup/SetupProviderFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/setup/SetupProviderFragment.kt index a2062bde..42d65e4b 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/setup/SetupProviderFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/setup/SetupProviderFragment.kt @@ -21,6 +21,7 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.material.snackbar.BaseTransientBottomBar import com.google.android.material.transition.MaterialSharedAxis import com.thewizrd.common.preferences.KeyEntryPreferenceDialogFragment +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.controls.ProviderEntry import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.exceptions.WeatherException @@ -273,7 +274,7 @@ class SetupProviderFragment : CustomPreferenceFragmentCompat(), StepperFragment fragment.dialog?.dismiss() } else { - showToast(R.string.message_keyinvalid, Toast.LENGTH_SHORT) + showToast(sharedRes.string.message_keyinvalid, Toast.LENGTH_SHORT) } } catch (e: WeatherException) { Logger.writeLine(Log.ERROR, e) @@ -297,13 +298,16 @@ class SetupProviderFragment : CustomPreferenceFragmentCompat(), StepperFragment val keyVerified = settingsManager.isKeyVerified(providerPref.value) val colorSpan = ForegroundColorSpan(if (keyVerified) Color.GREEN else Color.RED) val summary = SpannableString( - if (keyVerified) getString(R.string.message_keyverified) else getString(R.string.message_keyinvalid) + if (keyVerified) getString(sharedRes.string.message_keyverified) else getString( + sharedRes.string.message_keyinvalid + ) ) summary.setSpan(colorSpan, 0, summary.length, 0) keyEntry.summary = summary } else { val colorSpan = ForegroundColorSpan(Color.RED) - val summary = SpannableString(getString(R.string.pref_summary_apikey, providerAPI)) + val summary = + SpannableString(getString(sharedRes.string.pref_summary_apikey, providerAPI)) summary.setSpan(colorSpan, 0, summary.length, 0) keyEntry.summary = summary } @@ -333,7 +337,7 @@ class SetupProviderFragment : CustomPreferenceFragmentCompat(), StepperFragment showSnackbar( Snackbar.make( it, - R.string.message_enter_apikey, + sharedRes.string.message_enter_apikey, Snackbar.Duration.LONG ) ) diff --git a/app/src/main/java/com/thewizrd/simpleweather/setup/SetupSettingsFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/setup/SetupSettingsFragment.kt index ab01fdf8..4ac8450a 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/setup/SetupSettingsFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/setup/SetupSettingsFragment.kt @@ -27,6 +27,7 @@ import com.thewizrd.shared_resources.preferences.SettingsManager import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.dpToPx import com.thewizrd.shared_resources.utils.Units +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.adapters.SpacerAdapter import com.thewizrd.simpleweather.databinding.FragmentSetupSettingsBinding @@ -67,10 +68,10 @@ class SetupSettingsFragment : CustomPreferenceFragmentCompat() { showSnackbar( Snackbar.make( it, - R.string.notification_perm_denied, + sharedRes.string.notification_perm_denied, Snackbar.Duration.SHORT ).apply { - setAction(R.string.action_settings) { + setAction(sharedRes.string.action_settings) { runCatching { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { it.context.openAppNotificationSettingsActivity() @@ -92,10 +93,10 @@ class SetupSettingsFragment : CustomPreferenceFragmentCompat() { showSnackbar( Snackbar.make( it, - R.string.notification_perm_denied, + sharedRes.string.notification_perm_denied, Snackbar.Duration.SHORT ).apply { - setAction(R.string.action_settings) { + setAction(sharedRes.string.action_settings) { runCatching { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { it.context.openAppNotificationSettingsActivity() @@ -179,11 +180,11 @@ class SetupSettingsFragment : CustomPreferenceFragmentCompat() { } if (enableAdditionalRefreshIntervals()) { - intervalPref.setEntries(R.array.premium_refreshinterval_entries) - intervalPref.setEntryValues(R.array.premium_refreshinterval_values) + intervalPref.setEntries(sharedRes.array.premium_refreshinterval_entries) + intervalPref.setEntryValues(sharedRes.array.premium_refreshinterval_values) } else { - intervalPref.setEntries(R.array.refreshinterval_entries) - intervalPref.setEntryValues(R.array.refreshinterval_values) + intervalPref.setEntries(sharedRes.array.refreshinterval_entries) + intervalPref.setEntryValues(sharedRes.array.refreshinterval_values) } onGoingPref.setOnPreferenceChangeListener { preference, newValue -> diff --git a/app/src/main/java/com/thewizrd/simpleweather/snackbar/SnackbarManager.java b/app/src/main/java/com/thewizrd/simpleweather/snackbar/SnackbarManager.java index 0e280842..2ffe084f 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/snackbar/SnackbarManager.java +++ b/app/src/main/java/com/thewizrd/simpleweather/snackbar/SnackbarManager.java @@ -15,7 +15,6 @@ import com.google.android.material.snackbar.BaseTransientBottomBar; import com.thewizrd.shared_resources.ApplicationLibKt; -import com.thewizrd.simpleweather.R; import java.util.Stack; @@ -168,18 +167,15 @@ public boolean canSwipeDismissView(View child) { mSnackbarView.setText(snackPair.snackbar.getMessageText()); mSnackbarView.setAction(snackPair.snackbar.getActionText(), snackPair.snackbar.getAction()); // Override Snackbar action click listener to prevent it from being dismissed on click - mSnackbarView.getView().findViewById(R.id.snackbar_action).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (snackPair.snackbar.getAction() != null) { - snackPair.snackbar.getAction().onClick(v); - } - // Now dismiss the Snackbar - if (snackPair.callback != null) - snackPair.callback.onDismissed(mSnackbarView, BaseTransientBottomBar.BaseCallback.DISMISS_EVENT_ACTION); - if (!mSnacks.isEmpty()) mSnacks.pop(); - updateView(); + mSnackbarView.getView().findViewById(com.google.android.material.R.id.snackbar_action).setOnClickListener(v -> { + if (snackPair.snackbar.getAction() != null) { + snackPair.snackbar.getAction().onClick(v); } + // Now dismiss the Snackbar + if (snackPair.callback != null) + snackPair.callback.onDismissed(mSnackbarView, BaseTransientBottomBar.BaseCallback.DISMISS_EVENT_ACTION); + if (!mSnacks.isEmpty()) mSnacks.pop(); + updateView(); }); if (!mSnackbarView.isShown()) mSnackbarView.show(); diff --git a/app/src/main/java/com/thewizrd/simpleweather/stepper/BottomStepperNavigationBar.java b/app/src/main/java/com/thewizrd/simpleweather/stepper/BottomStepperNavigationBar.java index 23ed48d4..e37bb070 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/stepper/BottomStepperNavigationBar.java +++ b/app/src/main/java/com/thewizrd/simpleweather/stepper/BottomStepperNavigationBar.java @@ -90,11 +90,11 @@ private void initialize(Context context, @Nullable AttributeSet attrs, @AttrRes private void initDefaultValues(Context context) { mBackgroundColor = ContextUtils.getAttrResourceId(context, android.R.attr.colorBackground); - mForegroundColor = ContextUtils.getAttrColorStateList(context, R.attr.colorAccent); + mForegroundColor = ContextUtils.getAttrColorStateList(context, androidx.appcompat.R.attr.colorAccent); - mBackButtonText = context.getString(R.string.label_back); - mStartButtonText = mNextButtonText = context.getString(R.string.label_next); - mCompleteButtonText = context.getString(R.string.abc_action_mode_done); + mBackButtonText = context.getString(com.thewizrd.shared_resources.R.string.label_back); + mStartButtonText = mNextButtonText = context.getString(com.thewizrd.shared_resources.R.string.label_next); + mCompleteButtonText = context.getString(androidx.appcompat.R.string.abc_action_mode_done); mBackButtonIcon = ContextCompat.getDrawable(context, R.drawable.ic_chevron_left); mNextButtonIcon = ContextCompat.getDrawable(context, R.drawable.ic_chevron_right); diff --git a/app/src/main/java/com/thewizrd/simpleweather/viewmodels/LocationsViewModel.kt b/app/src/main/java/com/thewizrd/simpleweather/viewmodels/LocationsViewModel.kt index 0bf7775b..f7422437 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/viewmodels/LocationsViewModel.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/viewmodels/LocationsViewModel.kt @@ -21,6 +21,7 @@ import com.thewizrd.shared_resources.exceptions.WeatherException import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.utils.CommonActions import com.thewizrd.shared_resources.weatherdata.model.LocationType +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.controls.LocationPanelUiModel import kotlinx.coroutines.Dispatchers @@ -263,7 +264,7 @@ class LocationsViewModel(app: Application) : AndroidViewModel(app) { getApplication().getSystemService(Context.LOCATION_SERVICE) as? LocationManager if (locMan == null || !LocationManagerCompat.isLocationEnabled(locMan)) { - return LocationResult.Error(errorMessage = ErrorMessage.Resource(R.string.error_retrieve_location)) + return LocationResult.Error(errorMessage = ErrorMessage.Resource(sharedRes.string.error_retrieve_location)) } return locationProvider.getLatestLocationData() diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/AppChoiceDialogBuilder.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/AppChoiceDialogBuilder.kt index 55028f56..ca99d94f 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/AppChoiceDialogBuilder.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/AppChoiceDialogBuilder.kt @@ -20,7 +20,7 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.thewizrd.common.helpers.SimpleRecyclerViewAdapterObserver import com.thewizrd.shared_resources.helpers.ListAdapterOnClickInterface -import com.thewizrd.simpleweather.R +import com.thewizrd.shared_resources.R import com.thewizrd.simpleweather.databinding.AppItemLayoutBinding import com.thewizrd.simpleweather.databinding.DialogAppchooserBinding import kotlinx.coroutines.CoroutineScope @@ -75,7 +75,7 @@ class AppChoiceDialogBuilder(private val context: Context) { fun show() { val dialog = MaterialAlertDialogBuilder(context) - .setTitle(R.string.abc_activitychooserview_choose_application) + .setTitle(androidx.appcompat.R.string.abc_activitychooserview_choose_application) .setCancelable(true) .setView(createView()) .setNegativeButton(android.R.string.cancel) { dialog, which -> dialog.cancel() } diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/WeatherWidgetProvider.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/WeatherWidgetProvider.kt index 05fb0792..8721d7b0 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/WeatherWidgetProvider.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/WeatherWidgetProvider.kt @@ -8,6 +8,7 @@ import android.os.Bundle import android.util.Log import android.widget.RemoteViews import android.widget.Toast +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.utils.Logger import com.thewizrd.simpleweather.BuildConfig import com.thewizrd.simpleweather.R @@ -50,7 +51,7 @@ abstract class WeatherWidgetProvider : AppWidgetProvider() { Toast.makeText( context, - context.getString(R.string.action_refresh) + "...", + context.getString(sharedRes.string.action_refresh) + "...", Toast.LENGTH_SHORT ).show() refreshWidget(context, intArrayOf(appWidgetId)) diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/WidgetUpdaterHelper.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/WidgetUpdaterHelper.kt index 491959ee..5fcddff4 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/WidgetUpdaterHelper.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/WidgetUpdaterHelper.kt @@ -20,6 +20,7 @@ import com.thewizrd.common.controls.HourlyForecastItemViewModel import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.helpers.ColorsUtils import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.helpers.toImmutableCompatFlag @@ -439,7 +440,7 @@ object WidgetUpdaterHelper { val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowText) + TextAppearanceSpan(context, sharedRes.style.ShadowText) } else { null } diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/AbstractWeatherWidgetPreferenceFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/AbstractWeatherWidgetPreferenceFragment.kt index 860a9bbc..267fcd0e 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/AbstractWeatherWidgetPreferenceFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/AbstractWeatherWidgetPreferenceFragment.kt @@ -43,6 +43,7 @@ import com.thewizrd.common.location.LocationProvider import com.thewizrd.common.location.LocationResult import com.thewizrd.common.utils.ErrorMessage import com.thewizrd.common.viewmodels.LocationSearchResult +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.locationdata.LocationData @@ -191,7 +192,7 @@ abstract class AbstractWeatherWidgetPreferenceFragment : ToolbarPreferenceFragme showSnackbar( Snackbar.make( it, - R.string.error_location_denied, + sharedRes.string.error_location_denied, Snackbar.Duration.SHORT ) ) @@ -206,7 +207,7 @@ abstract class AbstractWeatherWidgetPreferenceFragment : ToolbarPreferenceFragme showSnackbar( Snackbar.make( it, - R.string.error_location_denied, + sharedRes.string.error_location_denied, Snackbar.Duration.SHORT ) ) @@ -467,7 +468,7 @@ abstract class AbstractWeatherWidgetPreferenceFragment : ToolbarPreferenceFragme requireContext().getSystemService(Context.LOCATION_SERVICE) as? LocationManager if (locMan == null || !LocationManagerCompat.isLocationEnabled(locMan)) { - return LocationResult.Error(errorMessage = ErrorMessage.Resource(R.string.error_retrieve_location)) + return LocationResult.Error(errorMessage = ErrorMessage.Resource(sharedRes.string.error_retrieve_location)) } return locationProvider.getLatestLocationData() @@ -518,7 +519,7 @@ abstract class AbstractWeatherWidgetPreferenceFragment : ToolbarPreferenceFragme highC = 23f + index / 2f lowF = 60f - index lowC = 17f - index / 2f - condition = getString(R.string.weather_sunny) + condition = getString(sharedRes.string.weather_sunny) icon = WeatherIcons.DAY_SUNNY extras = ForecastExtras().apply { feelslikeF = 80f @@ -550,7 +551,7 @@ abstract class AbstractWeatherWidgetPreferenceFragment : ToolbarPreferenceFragme date = ZonedDateTime.now().plusHours(index.toLong()) highF = 70f + index highC = 23f + index / 2f - condition = getString(R.string.weather_sunny) + condition = getString(sharedRes.string.weather_sunny) icon = WeatherIcons.DAY_SUNNY windMph = 5f windKph = 8f @@ -596,7 +597,7 @@ abstract class AbstractWeatherWidgetPreferenceFragment : ToolbarPreferenceFragme } } condition = Condition().apply { - weather = getString(R.string.weather_sunny) + weather = getString(sharedRes.string.weather_sunny) tempF = 70f tempC = 21f windDegrees = 292 diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/BaseWeatherWidgetPreferenceFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/BaseWeatherWidgetPreferenceFragment.kt index 2d48dfd9..66e4c9d4 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/BaseWeatherWidgetPreferenceFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/BaseWeatherWidgetPreferenceFragment.kt @@ -16,6 +16,7 @@ import com.bumptech.glide.load.resource.bitmap.CenterCrop import com.bumptech.glide.request.RequestOptions import com.thewizrd.common.preferences.SliderPreference import com.thewizrd.common.utils.glide.TransparentOverlay +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.preferences.colorpreference.ColorPreference import com.thewizrd.simpleweather.widgets.AppChoiceDialogBuilder @@ -286,7 +287,7 @@ abstract class BaseWeatherWidgetPreferenceFragment : AbstractWeatherWidgetPrefer } } - clockPref.setSummary(R.string.summary_default) + clockPref.setSummary(sharedRes.string.summary_default) } private fun updateCalPreference(context: Context) { @@ -304,7 +305,7 @@ abstract class BaseWeatherWidgetPreferenceFragment : AbstractWeatherWidgetPrefer } } - calPref.setSummary(R.string.summary_default) + calPref.setSummary(sharedRes.string.summary_default) } protected fun updateBackground() { diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WeatherWidget4x3LocationFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WeatherWidget4x3LocationFragment.kt index cfb5eb43..25615c84 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WeatherWidget4x3LocationFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WeatherWidget4x3LocationFragment.kt @@ -22,6 +22,7 @@ import com.google.android.material.snackbar.BaseTransientBottomBar import com.thewizrd.common.helpers.backgroundLocationPermissionEnabled import com.thewizrd.common.helpers.getBackgroundLocationRationale import com.thewizrd.common.location.LocationResult +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.di.localBroadcastManager import com.thewizrd.shared_resources.di.settingsManager @@ -265,7 +266,7 @@ class WeatherWidget4x3LocationFragment : BaseWeatherWidgetPreferenceFragment() { showSnackbar( Snackbar.make( ctx, - R.string.error_retrieve_location, + sharedRes.string.error_retrieve_location, Snackbar.Duration.SHORT ) ) @@ -295,7 +296,11 @@ class WeatherWidget4x3LocationFragment : BaseWeatherWidgetPreferenceFragment() { finalizeWidgetUpdate() } else { showSnackbar( - Snackbar.make(ctx, R.string.prompt_location_not_set, Snackbar.Duration.SHORT) + Snackbar.make( + ctx, + sharedRes.string.prompt_location_not_set, + Snackbar.Duration.SHORT + ) ) } } @@ -336,7 +341,7 @@ class WeatherWidget4x3LocationFragment : BaseWeatherWidgetPreferenceFragment() { showSnackbar( Snackbar.make( ctx, - R.string.error_enable_location_services, + sharedRes.string.error_enable_location_services, Snackbar.Duration.SHORT ) ) @@ -359,7 +364,7 @@ class WeatherWidget4x3LocationFragment : BaseWeatherWidgetPreferenceFragment() { showSnackbar( Snackbar.make( ctx, - R.string.error_location_denied, + sharedRes.string.error_location_denied, Snackbar.Duration.SHORT ) ) @@ -369,7 +374,7 @@ class WeatherWidget4x3LocationFragment : BaseWeatherWidgetPreferenceFragment() { showSnackbar( Snackbar.make( ctx, - R.string.error_retrieve_location, + sharedRes.string.error_retrieve_location, Snackbar.Duration.SHORT ) ) diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WeatherWidgetPreferenceFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WeatherWidgetPreferenceFragment.kt index ec9217a2..a8dabfb5 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WeatherWidgetPreferenceFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WeatherWidgetPreferenceFragment.kt @@ -30,6 +30,7 @@ import com.thewizrd.common.helpers.getBackgroundLocationRationale import com.thewizrd.common.helpers.locationPermissionEnabled import com.thewizrd.common.location.LocationResult import com.thewizrd.common.viewmodels.LocationSearchResult +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.controls.ComboBoxItem import com.thewizrd.shared_resources.di.localBroadcastManager @@ -79,7 +80,7 @@ class WeatherWidgetPreferenceFragment : BaseWeatherWidgetPreferenceFragment() { lifecycleScope.launch { locationPref.addEntry(R.string.pref_item_gpslocation, Constants.KEY_GPS) - locationPref.addEntry(R.string.label_btn_add_location, Constants.KEY_SEARCH) + locationPref.addEntry(sharedRes.string.label_btn_add_location, Constants.KEY_SEARCH) val favs = settingsManager.getFavorites() favorites.addAll(favs) @@ -412,7 +413,7 @@ class WeatherWidgetPreferenceFragment : BaseWeatherWidgetPreferenceFragment() { locationPref.findEntryFromValue(it)?.toString() } ?: locationView.context.getString(R.string.pref_location)).run { if (WidgetUtils.isBackgroundOptionalWidget(mWidgetType) && txtShadowPref.isChecked) { - applySpan(TextAppearanceSpan(locationView.context, R.style.ShadowText)) + applySpan(TextAppearanceSpan(locationView.context, sharedRes.style.ShadowText)) } else { this } @@ -491,7 +492,11 @@ class WeatherWidgetPreferenceFragment : BaseWeatherWidgetPreferenceFragment() { } else { context?.let { showSnackbar( - Snackbar.make(it, R.string.error_retrieve_location, Snackbar.Duration.SHORT) + Snackbar.make( + it, + sharedRes.string.error_retrieve_location, + Snackbar.Duration.SHORT + ) ) } } @@ -527,7 +532,7 @@ class WeatherWidgetPreferenceFragment : BaseWeatherWidgetPreferenceFragment() { showSnackbar( Snackbar.make( ctx, - R.string.error_enable_location_services, + sharedRes.string.error_enable_location_services, Snackbar.Duration.SHORT ) ) @@ -550,7 +555,7 @@ class WeatherWidgetPreferenceFragment : BaseWeatherWidgetPreferenceFragment() { showSnackbar( Snackbar.make( ctx, - R.string.error_location_denied, + sharedRes.string.error_location_denied, Snackbar.Duration.SHORT ) ) @@ -560,7 +565,7 @@ class WeatherWidgetPreferenceFragment : BaseWeatherWidgetPreferenceFragment() { showSnackbar( Snackbar.make( ctx, - R.string.error_retrieve_location, + sharedRes.string.error_retrieve_location, Snackbar.Duration.SHORT ) ) diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/CustomBackgroundWidgetRemoteViewCreator.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/CustomBackgroundWidgetRemoteViewCreator.kt index c2042912..fb90222f 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/CustomBackgroundWidgetRemoteViewCreator.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/CustomBackgroundWidgetRemoteViewCreator.kt @@ -21,6 +21,7 @@ import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.utils.ImageUtils import com.thewizrd.common.utils.glide.CustomRoundedCorners import com.thewizrd.common.utils.glide.TransparentOverlay +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.dpToPx @@ -96,7 +97,7 @@ abstract class CustomBackgroundWidgetRemoteViewCreator( updateViews.setColorAttr( R.id.panda_container, "setBackgroundColor", - R.attr.colorSurface + com.google.android.material.R.attr.colorSurface ) } else { updateViews.addView( diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget1x1Creator.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget1x1Creator.kt index ff4d1df3..7b97387d 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget1x1Creator.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget1x1Creator.kt @@ -10,6 +10,7 @@ import android.widget.RemoteViews import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.helpers.ColorsUtils import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.ContextUtils.dpToPx @@ -64,7 +65,7 @@ class WeatherWidget1x1Creator(context: Context) : WidgetRemoteViewCreator(contex ColorsUtils.isSuperLight(backgroundColor) ) val textAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(viewCtx, R.style.ShadowText) + TextAppearanceSpan(viewCtx, sharedRes.style.ShadowText) } else { null } @@ -121,7 +122,7 @@ class WeatherWidget1x1Creator(context: Context) : WidgetRemoteViewCreator(contex updateViews.setInt(R.id.refresh_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.refresh_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.refresh_button, R.drawable.ic_refresh) + updateViews.setImageViewResource(R.id.refresh_button, sharedRes.drawable.ic_refresh) // Setting icon updateViews.setImageViewBitmap(R.id.settings_button, null) @@ -129,7 +130,10 @@ class WeatherWidget1x1Creator(context: Context) : WidgetRemoteViewCreator(contex updateViews.setInt(R.id.settings_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.settings_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.settings_button, R.drawable.ic_outline_settings_24) + updateViews.setImageViewResource( + R.id.settings_button, + sharedRes.drawable.ic_outline_settings_24 + ) // Location Name updateViews.setTextViewText( diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget2x2Creator.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget2x2Creator.kt index a6f7475d..e1d658e6 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget2x2Creator.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget2x2Creator.kt @@ -14,6 +14,7 @@ import com.thewizrd.common.controls.WeatherDetailsType import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.helpers.ColorsUtils import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.locationdata.LocationData @@ -135,7 +136,7 @@ class WeatherWidget2x2Creator(context: Context, loadBackground: Boolean = true) val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowText) + TextAppearanceSpan(context, sharedRes.style.ShadowText) } else { null } @@ -195,7 +196,7 @@ class WeatherWidget2x2Creator(context: Context, loadBackground: Boolean = true) R.id.hi_icon, ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_direction_up, + sharedRes.drawable.wi_direction_up, Colors.WHITE, tempArrowIconSize, tempArrowIconSize @@ -205,7 +206,7 @@ class WeatherWidget2x2Creator(context: Context, loadBackground: Boolean = true) R.id.lo_icon, ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_direction_down, + sharedRes.drawable.wi_direction_down, Colors.WHITE, tempArrowIconSize, tempArrowIconSize @@ -227,8 +228,8 @@ class WeatherWidget2x2Creator(context: Context, loadBackground: Boolean = true) updateViews.setInt(R.id.hi_icon, "setMaxWidth", tempArrowIconSize.toInt()) updateViews.setInt(R.id.lo_icon, "setMaxWidth", tempArrowIconSize.toInt()) - updateViews.setImageViewResource(R.id.hi_icon, R.drawable.wi_direction_up) - updateViews.setImageViewResource(R.id.lo_icon, R.drawable.wi_direction_down) + updateViews.setImageViewResource(R.id.hi_icon, sharedRes.drawable.wi_direction_up) + updateViews.setImageViewResource(R.id.lo_icon, sharedRes.drawable.wi_direction_down) } val chanceModel = weather.weatherDetailsMap[WeatherDetailsType.POPCHANCE] @@ -411,7 +412,7 @@ class WeatherWidget2x2Creator(context: Context, loadBackground: Boolean = true) updateViews.setInt(R.id.refresh_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.refresh_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.refresh_button, R.drawable.ic_refresh) + updateViews.setImageViewResource(R.id.refresh_button, sharedRes.drawable.ic_refresh) // Setting icon updateViews.setImageViewBitmap(R.id.settings_button, null) @@ -419,7 +420,10 @@ class WeatherWidget2x2Creator(context: Context, loadBackground: Boolean = true) updateViews.setInt(R.id.settings_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.settings_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.settings_button, R.drawable.ic_outline_settings_24) + updateViews.setImageViewResource( + R.id.settings_button, + sharedRes.drawable.ic_outline_settings_24 + ) // Location Name updateViews.setTextViewText( @@ -587,13 +591,14 @@ class WeatherWidget2x2Creator(context: Context, loadBackground: Boolean = true) val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textClockAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowTextClock) + TextAppearanceSpan(context, sharedRes.style.ShadowTextClock) } else { null } // Update clock widgets - val timeStr12hr = SpannableString(context.getText(R.string.clock_12_hours_ampm_format)) + val timeStr12hr = + SpannableString(context.getText(sharedRes.string.clock_12_hours_ampm_format)) val start12hr = timeStr12hr.length - 2 timeStr12hr.setSpan( RelativeSizeSpan(0.875f), @@ -608,7 +613,8 @@ class WeatherWidget2x2Creator(context: Context, loadBackground: Boolean = true) ) views.setCharSequence( R.id.clock_panel, "setFormat24Hour", - context.getText(R.string.clock_24_hours_format).applySpan(textClockAppearanceSpan) + context.getText(sharedRes.string.clock_24_hours_format) + .applySpan(textClockAppearanceSpan) ) var clockTextSize = @@ -639,7 +645,7 @@ class WeatherWidget2x2Creator(context: Context, loadBackground: Boolean = true) val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textClockAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowTextClock) + TextAppearanceSpan(context, sharedRes.style.ShadowTextClock) } else { null } diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x1Creator.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x1Creator.kt index 2db31ff0..0b3eb709 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x1Creator.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x1Creator.kt @@ -8,6 +8,7 @@ import android.util.TypedValue import android.view.View import android.widget.RemoteViews import com.thewizrd.common.controls.WeatherUiModel +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.utils.ContextUtils.dpToPx import com.thewizrd.shared_resources.utils.TextUtils.applySpan @@ -69,7 +70,7 @@ class WeatherWidget4x1Creator(context: Context) : WidgetRemoteViewCreator(contex val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowText) + TextAppearanceSpan(context, sharedRes.style.ShadowText) } else { null } @@ -98,7 +99,7 @@ class WeatherWidget4x1Creator(context: Context) : WidgetRemoteViewCreator(contex updateViews.setInt(R.id.refresh_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.refresh_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.refresh_button, R.drawable.ic_refresh) + updateViews.setImageViewResource(R.id.refresh_button, sharedRes.drawable.ic_refresh) // Setting icon updateViews.setImageViewBitmap(R.id.settings_button, null) @@ -106,7 +107,10 @@ class WeatherWidget4x1Creator(context: Context) : WidgetRemoteViewCreator(contex updateViews.setInt(R.id.settings_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.settings_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.settings_button, R.drawable.ic_outline_settings_24) + updateViews.setImageViewResource( + R.id.settings_button, + sharedRes.drawable.ic_outline_settings_24 + ) if (!hideLocationName) { updateViews.setViewVisibility( diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x1GoogleCreator.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x1GoogleCreator.kt index 16098d57..d83ba6f7 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x1GoogleCreator.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x1GoogleCreator.kt @@ -10,6 +10,7 @@ import android.widget.RemoteViews import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.helpers.ColorsUtils import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.sharedDeps @@ -68,7 +69,7 @@ class WeatherWidget4x1GoogleCreator(context: Context) : WidgetRemoteViewCreator( ColorsUtils.isSuperLight(backgroundColor) ) val textAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(viewCtx, R.style.ShadowText) + TextAppearanceSpan(viewCtx, sharedRes.style.ShadowText) } else { null } @@ -136,7 +137,7 @@ class WeatherWidget4x1GoogleCreator(context: Context) : WidgetRemoteViewCreator( updateViews.setInt(R.id.refresh_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.refresh_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.refresh_button, R.drawable.ic_refresh) + updateViews.setImageViewResource(R.id.refresh_button, sharedRes.drawable.ic_refresh) // Setting icon updateViews.setImageViewBitmap(R.id.settings_button, null) @@ -144,7 +145,10 @@ class WeatherWidget4x1GoogleCreator(context: Context) : WidgetRemoteViewCreator( updateViews.setInt(R.id.settings_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.settings_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.settings_button, R.drawable.ic_outline_settings_24) + updateViews.setImageViewResource( + R.id.settings_button, + sharedRes.drawable.ic_outline_settings_24 + ) // Location Name updateViews.setTextViewText( @@ -289,7 +293,7 @@ class WeatherWidget4x1GoogleCreator(context: Context) : WidgetRemoteViewCreator( val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textClockAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowTextHeavy) + TextAppearanceSpan(context, sharedRes.style.ShadowTextHeavy) } else { null } diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x1NotificationCreator.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x1NotificationCreator.kt index 9a437a73..f2e48136 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x1NotificationCreator.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x1NotificationCreator.kt @@ -11,6 +11,7 @@ import com.thewizrd.common.controls.WeatherDetailsType import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.helpers.ColorsUtils import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.sharedDeps @@ -68,7 +69,7 @@ class WeatherWidget4x1NotificationCreator(context: Context) : WidgetRemoteViewCr ColorsUtils.isSuperLight(backgroundColor) ) val textAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(viewCtx, R.style.ShadowText) + TextAppearanceSpan(viewCtx, sharedRes.style.ShadowText) } else { null } @@ -114,7 +115,7 @@ class WeatherWidget4x1NotificationCreator(context: Context) : WidgetRemoteViewCr R.id.hi_icon, ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_direction_up, + sharedRes.drawable.wi_direction_up, textColor, tempArrowIconSize, tempArrowIconSize @@ -124,7 +125,7 @@ class WeatherWidget4x1NotificationCreator(context: Context) : WidgetRemoteViewCr R.id.lo_icon, ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_direction_down, + sharedRes.drawable.wi_direction_down, textColor, tempArrowIconSize, tempArrowIconSize @@ -245,7 +246,7 @@ class WeatherWidget4x1NotificationCreator(context: Context) : WidgetRemoteViewCr updateViews.setInt(R.id.refresh_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.refresh_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.refresh_button, R.drawable.ic_refresh) + updateViews.setImageViewResource(R.id.refresh_button, sharedRes.drawable.ic_refresh) // Setting icon updateViews.setImageViewBitmap(R.id.settings_button, null) @@ -253,7 +254,10 @@ class WeatherWidget4x1NotificationCreator(context: Context) : WidgetRemoteViewCr updateViews.setInt(R.id.settings_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.settings_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.settings_button, R.drawable.ic_outline_settings_24) + updateViews.setImageViewResource( + R.id.settings_button, + sharedRes.drawable.ic_outline_settings_24 + ) // Location Name updateViews.setTextViewText( diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2ClockCreator.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2ClockCreator.kt index 4abcac58..ffcc399f 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2ClockCreator.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2ClockCreator.kt @@ -11,6 +11,7 @@ import android.widget.RemoteViews import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.helpers.ColorsUtils import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.sharedDeps @@ -72,7 +73,7 @@ class WeatherWidget4x2ClockCreator(context: Context) : WidgetRemoteViewCreator(c ColorsUtils.isSuperLight(backgroundColor) ) val textAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(viewCtx, R.style.ShadowText) + TextAppearanceSpan(viewCtx, sharedRes.style.ShadowText) } else { null } @@ -146,7 +147,7 @@ class WeatherWidget4x2ClockCreator(context: Context) : WidgetRemoteViewCreator(c updateViews.setInt(R.id.refresh_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.refresh_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.refresh_button, R.drawable.ic_refresh) + updateViews.setImageViewResource(R.id.refresh_button, sharedRes.drawable.ic_refresh) // Setting icon updateViews.setImageViewBitmap(R.id.settings_button, null) @@ -154,7 +155,10 @@ class WeatherWidget4x2ClockCreator(context: Context) : WidgetRemoteViewCreator(c updateViews.setInt(R.id.settings_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.settings_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.settings_button, R.drawable.ic_outline_settings_24) + updateViews.setImageViewResource( + R.id.settings_button, + sharedRes.drawable.ic_outline_settings_24 + ) // Location Name updateViews.setTextViewText( @@ -306,13 +310,13 @@ class WeatherWidget4x2ClockCreator(context: Context) : WidgetRemoteViewCreator(c val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textClockAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowTextHeavy) + TextAppearanceSpan(context, sharedRes.style.ShadowTextHeavy) } else { null } // Update clock widgets - val timeStr12hr = SpannableString(context.getText(R.string.clock_12_hours_format)) + val timeStr12hr = SpannableString(context.getText(sharedRes.string.clock_12_hours_format)) views.setCharSequence( R.id.clock_panel, "setFormat12Hour", @@ -320,7 +324,8 @@ class WeatherWidget4x2ClockCreator(context: Context) : WidgetRemoteViewCreator(c ) views.setCharSequence( R.id.clock_panel, "setFormat24Hour", - context.getText(R.string.clock_24_hours_format).applySpan(textClockAppearanceSpan) + context.getText(sharedRes.string.clock_24_hours_format) + .applySpan(textClockAppearanceSpan) ) views.setTextViewTextSize( @@ -346,7 +351,7 @@ class WeatherWidget4x2ClockCreator(context: Context) : WidgetRemoteViewCreator(c val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textClockAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowText) + TextAppearanceSpan(context, sharedRes.style.ShadowText) } else { null } diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2Creator.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2Creator.kt index a4853c31..33fee92b 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2Creator.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2Creator.kt @@ -14,6 +14,7 @@ import com.thewizrd.common.controls.WeatherDetailsType import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.helpers.ColorsUtils import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.sharedDeps @@ -97,7 +98,7 @@ class WeatherWidget4x2Creator(context: Context, loadBackground: Boolean = true) val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowText) + TextAppearanceSpan(context, sharedRes.style.ShadowText) } else { null } @@ -207,7 +208,7 @@ class WeatherWidget4x2Creator(context: Context, loadBackground: Boolean = true) updateViews.setInt(R.id.refresh_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.refresh_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.refresh_button, R.drawable.ic_refresh) + updateViews.setImageViewResource(R.id.refresh_button, sharedRes.drawable.ic_refresh) // Setting icon updateViews.setImageViewBitmap(R.id.settings_button, null) @@ -215,7 +216,10 @@ class WeatherWidget4x2Creator(context: Context, loadBackground: Boolean = true) updateViews.setInt(R.id.settings_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.settings_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.settings_button, R.drawable.ic_outline_settings_24) + updateViews.setImageViewResource( + R.id.settings_button, + sharedRes.drawable.ic_outline_settings_24 + ) // Location Name updateViews.setTextViewText( @@ -398,13 +402,14 @@ class WeatherWidget4x2Creator(context: Context, loadBackground: Boolean = true) val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textClockAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowTextClock) + TextAppearanceSpan(context, sharedRes.style.ShadowTextClock) } else { null } // Update clock widgets - val timeStr12hr = SpannableString(context.getText(R.string.clock_12_hours_ampm_format)) + val timeStr12hr = + SpannableString(context.getText(sharedRes.string.clock_12_hours_ampm_format)) val start12hr = timeStr12hr.length - 2 timeStr12hr.setSpan( RelativeSizeSpan(0.875f), @@ -419,7 +424,8 @@ class WeatherWidget4x2Creator(context: Context, loadBackground: Boolean = true) ) views.setCharSequence( R.id.clock_panel, "setFormat24Hour", - context.getText(R.string.clock_24_hours_format).applySpan(textClockAppearanceSpan) + context.getText(sharedRes.string.clock_24_hours_format) + .applySpan(textClockAppearanceSpan) ) var clockTextSize = 32f @@ -444,7 +450,7 @@ class WeatherWidget4x2Creator(context: Context, loadBackground: Boolean = true) val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textClockAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowTextClock) + TextAppearanceSpan(context, sharedRes.style.ShadowTextClock) } else { null } diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2GraphCreator.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2GraphCreator.kt index 9f07b9aa..6df9f874 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2GraphCreator.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2GraphCreator.kt @@ -16,6 +16,7 @@ import androidx.core.view.forEach import androidx.databinding.DataBindingUtil import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.helpers.ColorsUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.dpToPx @@ -98,7 +99,7 @@ class WeatherWidget4x2GraphCreator(context: Context) : WidgetRemoteViewCreator(c val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowText) + TextAppearanceSpan(context, sharedRes.style.ShadowText) } else { null } @@ -120,7 +121,7 @@ class WeatherWidget4x2GraphCreator(context: Context) : WidgetRemoteViewCreator(c updateViews.setInt(R.id.refresh_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.refresh_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.refresh_button, R.drawable.ic_refresh) + updateViews.setImageViewResource(R.id.refresh_button, sharedRes.drawable.ic_refresh) // Setting icon updateViews.setImageViewBitmap(R.id.settings_button, null) @@ -128,7 +129,10 @@ class WeatherWidget4x2GraphCreator(context: Context) : WidgetRemoteViewCreator(c updateViews.setInt(R.id.settings_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.settings_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.settings_button, R.drawable.ic_outline_settings_24) + updateViews.setImageViewResource( + R.id.settings_button, + sharedRes.drawable.ic_outline_settings_24 + ) // Location Name updateViews.setTextViewText( @@ -206,7 +210,7 @@ class WeatherWidget4x2GraphCreator(context: Context) : WidgetRemoteViewCreator(c val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowText) + TextAppearanceSpan(context, sharedRes.style.ShadowText) } else { null } @@ -243,46 +247,47 @@ class WeatherWidget4x2GraphCreator(context: Context) : WidgetRemoteViewCreator(c WidgetGraphType.HourlyForecast -> { updateViews.setTextViewText( R.id.graph_label, - context.getString(R.string.label_hourlyforecast) + context.getString(sharedRes.string.label_hourlyforecast) .applySpan(textAppearanceSpan) ) } WidgetGraphType.Precipitation -> { updateViews.setTextViewText( R.id.graph_label, - context.getString(R.string.label_precipitation) + context.getString(sharedRes.string.label_precipitation) .applySpan(textAppearanceSpan) ) } WidgetGraphType.Wind -> { updateViews.setTextViewText( R.id.graph_label, - context.getString(R.string.label_wind).applySpan(textAppearanceSpan) + context.getString(sharedRes.string.label_wind).applySpan(textAppearanceSpan) ) } WidgetGraphType.Humidity -> { updateViews.setTextViewText( R.id.graph_label, - context.getString(R.string.label_humidity).applySpan(textAppearanceSpan) + context.getString(sharedRes.string.label_humidity) + .applySpan(textAppearanceSpan) ) } WidgetGraphType.UVIndex -> { updateViews.setTextViewText( R.id.graph_label, - context.getString(R.string.label_uv).applySpan(textAppearanceSpan) + context.getString(sharedRes.string.label_uv).applySpan(textAppearanceSpan) ) } WidgetGraphType.AirQuality -> { updateViews.setTextViewText( R.id.graph_label, - context.getString(R.string.label_airquality_short) + context.getString(sharedRes.string.label_airquality_short) .applySpan(textAppearanceSpan) ) } WidgetGraphType.Minutely -> { updateViews.setTextViewText( R.id.graph_label, - context.getString(R.string.label_precipitation) + context.getString(sharedRes.string.label_precipitation) .applySpan(textAppearanceSpan) ) } diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2HuaweiCreator.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2HuaweiCreator.kt index 8c490ae5..3b8dc67b 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2HuaweiCreator.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2HuaweiCreator.kt @@ -11,6 +11,7 @@ import android.widget.RemoteViews import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.helpers.ColorsUtils import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.locationdata.LocationData @@ -73,7 +74,7 @@ class WeatherWidget4x2HuaweiCreator(context: Context) : WidgetRemoteViewCreator( ColorsUtils.isSuperLight(backgroundColor) ) val textAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(viewCtx, R.style.ShadowText) + TextAppearanceSpan(viewCtx, sharedRes.style.ShadowText) } else { null } @@ -165,7 +166,7 @@ class WeatherWidget4x2HuaweiCreator(context: Context) : WidgetRemoteViewCreator( updateViews.setInt(R.id.refresh_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.refresh_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.refresh_button, R.drawable.ic_refresh) + updateViews.setImageViewResource(R.id.refresh_button, sharedRes.drawable.ic_refresh) // Setting icon updateViews.setImageViewBitmap(R.id.settings_button, null) @@ -173,7 +174,10 @@ class WeatherWidget4x2HuaweiCreator(context: Context) : WidgetRemoteViewCreator( updateViews.setInt(R.id.settings_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.settings_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.settings_button, R.drawable.ic_outline_settings_24) + updateViews.setImageViewResource( + R.id.settings_button, + sharedRes.drawable.ic_outline_settings_24 + ) // Location Name updateViews.setTextViewText( @@ -275,13 +279,13 @@ class WeatherWidget4x2HuaweiCreator(context: Context) : WidgetRemoteViewCreator( val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textClockAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowTextHeavy) + TextAppearanceSpan(context, sharedRes.style.ShadowTextHeavy) } else { null } // Update clock widgets - val timeStr12hr = SpannableString(context.getText(R.string.clock_12_hours_format)) + val timeStr12hr = SpannableString(context.getText(sharedRes.string.clock_12_hours_format)) views.setCharSequence( R.id.clock_panel, "setFormat12Hour", @@ -289,7 +293,8 @@ class WeatherWidget4x2HuaweiCreator(context: Context) : WidgetRemoteViewCreator( ) views.setCharSequence( R.id.clock_panel, "setFormat24Hour", - context.getText(R.string.clock_24_hours_format).applySpan(textClockAppearanceSpan) + context.getText(sharedRes.string.clock_24_hours_format) + .applySpan(textClockAppearanceSpan) ) views.setTextViewTextSize( @@ -315,7 +320,7 @@ class WeatherWidget4x2HuaweiCreator(context: Context) : WidgetRemoteViewCreator( val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textClockAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowText) + TextAppearanceSpan(context, sharedRes.style.ShadowText) } else { null } diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2TomorrowCreator.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2TomorrowCreator.kt index ecf341a1..0585965e 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2TomorrowCreator.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x2TomorrowCreator.kt @@ -15,6 +15,7 @@ import com.thewizrd.common.controls.WeatherDetailsType import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.helpers.ColorsUtils import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.icons.WeatherIcons @@ -127,7 +128,7 @@ class WeatherWidget4x2TomorrowCreator(context: Context, loadBackground: Boolean val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowText) + TextAppearanceSpan(context, sharedRes.style.ShadowText) } else { null } @@ -279,7 +280,8 @@ class WeatherWidget4x2TomorrowCreator(context: Context, loadBackground: Boolean updateViews.setTextViewText( R.id.aqi_label, - context.getString(R.string.label_airquality_short).applySpan(textAppearanceSpan) + context.getString(sharedRes.string.label_airquality_short) + .applySpan(textAppearanceSpan) ) updateViews.setTextViewText( R.id.aqi_level, @@ -315,7 +317,9 @@ class WeatherWidget4x2TomorrowCreator(context: Context, loadBackground: Boolean } updateViews.setTextViewText( R.id.label_updatetime, - "${context.getString(R.string.update_prefix)} $dateStr".applySpan(textAppearanceSpan) + "${context.getString(sharedRes.string.update_prefix)} $dateStr".applySpan( + textAppearanceSpan + ) ) updateViews.setTextViewTextSize( R.id.label_updatetime, @@ -336,7 +340,7 @@ class WeatherWidget4x2TomorrowCreator(context: Context, loadBackground: Boolean updateViews.setInt(R.id.refresh_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.refresh_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.refresh_button, R.drawable.ic_refresh) + updateViews.setImageViewResource(R.id.refresh_button, sharedRes.drawable.ic_refresh) // Setting icon updateViews.setImageViewBitmap(R.id.settings_button, null) @@ -344,7 +348,10 @@ class WeatherWidget4x2TomorrowCreator(context: Context, loadBackground: Boolean updateViews.setInt(R.id.settings_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.settings_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.settings_button, R.drawable.ic_outline_settings_24) + updateViews.setImageViewResource( + R.id.settings_button, + sharedRes.drawable.ic_outline_settings_24 + ) // Location Name updateViews.setTextViewText( @@ -737,13 +744,14 @@ class WeatherWidget4x2TomorrowCreator(context: Context, loadBackground: Boolean val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textClockAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowTextClock) + TextAppearanceSpan(context, sharedRes.style.ShadowTextClock) } else { null } // Update clock widgets - val timeStr12hr = SpannableString(context.getText(R.string.clock_12_hours_ampm_format)) + val timeStr12hr = + SpannableString(context.getText(sharedRes.string.clock_12_hours_ampm_format)) val start12hr = timeStr12hr.length - 2 timeStr12hr.setSpan( RelativeSizeSpan(0.875f), @@ -758,7 +766,8 @@ class WeatherWidget4x2TomorrowCreator(context: Context, loadBackground: Boolean ) views.setCharSequence( R.id.clock_panel, "setFormat24Hour", - context.getText(R.string.clock_24_hours_format).applySpan(textClockAppearanceSpan) + context.getText(sharedRes.string.clock_24_hours_format) + .applySpan(textClockAppearanceSpan) ) var clockTextSize = 32f @@ -783,7 +792,7 @@ class WeatherWidget4x2TomorrowCreator(context: Context, loadBackground: Boolean val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textClockAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowTextClock) + TextAppearanceSpan(context, sharedRes.style.ShadowTextClock) } else { null } diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x3LocationsCreator.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x3LocationsCreator.kt index 3bde3297..7e4a5c2e 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x3LocationsCreator.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget4x3LocationsCreator.kt @@ -14,6 +14,7 @@ import androidx.core.graphics.alpha import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.helpers.ColorsUtils import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.locationdata.LocationData @@ -101,7 +102,7 @@ class WeatherWidget4x3LocationsCreator(context: Context) : ColorsUtils.isSuperLight(backgroundColor) ) val textAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(viewCtx, R.style.ShadowText) + TextAppearanceSpan(viewCtx, sharedRes.style.ShadowText) } else { null } @@ -254,7 +255,7 @@ class WeatherWidget4x3LocationsCreator(context: Context) : updateViews.setInt(R.id.refresh_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.refresh_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.refresh_button, R.drawable.ic_refresh) + updateViews.setImageViewResource(R.id.refresh_button, sharedRes.drawable.ic_refresh) // Setting icon updateViews.setImageViewBitmap(R.id.settings_button, null) @@ -262,7 +263,10 @@ class WeatherWidget4x3LocationsCreator(context: Context) : updateViews.setInt(R.id.settings_button, "setMaxWidth", scaledIconSize) updateViews.setInt(R.id.settings_button, "setMaxHeight", scaledIconSize) - updateViews.setImageViewResource(R.id.settings_button, R.drawable.ic_outline_settings_24) + updateViews.setImageViewResource( + R.id.settings_button, + sharedRes.drawable.ic_outline_settings_24 + ) updateViews.setViewVisibility( R.id.settings_button, @@ -387,20 +391,21 @@ class WeatherWidget4x3LocationsCreator(context: Context) : val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textClockAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowTextHeavy) + TextAppearanceSpan(context, sharedRes.style.ShadowTextHeavy) } else { null } // Update clock widgets - val timeStr12hr = SpannableString(context.getText(R.string.clock_12_hours_format)) + val timeStr12hr = SpannableString(context.getText(sharedRes.string.clock_12_hours_format)) views.setCharSequence( R.id.clock_panel, "setFormat12Hour", timeStr12hr.applySpan(textClockAppearanceSpan) ) views.setCharSequence( R.id.clock_panel, "setFormat24Hour", - context.getText(R.string.clock_24_hours_format).applySpan(textClockAppearanceSpan) + context.getText(sharedRes.string.clock_24_hours_format) + .applySpan(textClockAppearanceSpan) ) views.setTextViewTextSize( @@ -421,7 +426,7 @@ class WeatherWidget4x3LocationsCreator(context: Context) : val useTextShadow = newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) val textClockAppearanceSpan = if (useTextShadow) { - TextAppearanceSpan(context, R.style.ShadowText) + TextAppearanceSpan(context, sharedRes.style.ShadowText) } else { null } diff --git a/common/src/fullgms/java/com/thewizrd/common/location/LocationProvider.kt b/common/src/fullgms/java/com/thewizrd/common/location/LocationProvider.kt index 793a51e2..5769ebab 100644 --- a/common/src/fullgms/java/com/thewizrd/common/location/LocationProvider.kt +++ b/common/src/fullgms/java/com/thewizrd/common/location/LocationProvider.kt @@ -16,10 +16,10 @@ import com.google.android.gms.tasks.CancellationTokenSource import com.google.android.gms.tasks.Task import com.google.android.gms.tasks.Tasks import com.google.android.gms.wearable.Wearable -import com.thewizrd.common.R import com.thewizrd.common.helpers.locationPermissionEnabled import com.thewizrd.common.utils.ErrorMessage import com.thewizrd.common.wearable.WearableHelper +import com.thewizrd.shared_resources.R import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.exceptions.WeatherException import com.thewizrd.shared_resources.locationdata.LocationData diff --git a/common/src/main/java/com/thewizrd/common/controls/WeatherAlertPanel.java b/common/src/main/java/com/thewizrd/common/controls/WeatherAlertPanel.java index b36e64c9..61405cd3 100644 --- a/common/src/main/java/com/thewizrd/common/controls/WeatherAlertPanel.java +++ b/common/src/main/java/com/thewizrd/common/controls/WeatherAlertPanel.java @@ -17,7 +17,7 @@ import androidx.transition.TransitionManager; import androidx.transition.TransitionSet; -import com.thewizrd.common.R; +import com.thewizrd.shared_resources.R; import com.thewizrd.common.databinding.WeatherAlertPanelBinding; public class WeatherAlertPanel extends FrameLayout { diff --git a/common/src/main/java/com/thewizrd/common/preferences/KeyEntryPreferenceDialogFragment.kt b/common/src/main/java/com/thewizrd/common/preferences/KeyEntryPreferenceDialogFragment.kt index c94686ba..80b3dec9 100644 --- a/common/src/main/java/com/thewizrd/common/preferences/KeyEntryPreferenceDialogFragment.kt +++ b/common/src/main/java/com/thewizrd/common/preferences/KeyEntryPreferenceDialogFragment.kt @@ -17,6 +17,7 @@ import androidx.preference.EditTextPreference import androidx.preference.PreferenceDialogFragmentCompat import com.google.android.material.textfield.TextInputLayout import com.thewizrd.common.R +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.shared_resources.weatherdata.auth.AuthType @@ -143,7 +144,7 @@ class KeyEntryPreferenceDialogFragment : PreferenceDialogFragmentCompat() { if (apiProvider == WeatherAPI.HERE) { this.hint = "Access Key ID" } else { - this.setHint(R.string.hint_appid) + this.setHint(sharedRes.string.hint_appid) } editText?.let { editText -> editText.requestFocus() @@ -159,7 +160,7 @@ class KeyEntryPreferenceDialogFragment : PreferenceDialogFragmentCompat() { if (apiProvider == WeatherAPI.HERE) { this.hint = "Access Key Secret" } else { - this.setHint(R.string.hint_appcode) + this.setHint(sharedRes.string.hint_appcode) } editText?.let { editText -> editText.setText(credentials?.appCode ?: "") @@ -174,7 +175,7 @@ class KeyEntryPreferenceDialogFragment : PreferenceDialogFragmentCompat() { val credentials = providerKey as? BasicAuthProviderKey view.findViewById(R.id.keyentry1_layout)?.apply { - this.setHint(R.string.hint_username) + this.setHint(sharedRes.string.hint_username) editText?.let { editText -> editText.requestFocus() editText.setText(credentials?.username ?: "") @@ -186,7 +187,7 @@ class KeyEntryPreferenceDialogFragment : PreferenceDialogFragmentCompat() { } } view.findViewById(R.id.keyentry2_layout)?.apply { - this.setHint(R.string.hint_password) + this.setHint(sharedRes.string.hint_password) endIconMode = TextInputLayout.END_ICON_PASSWORD_TOGGLE passwordVisibilityToggleRequested(true) @@ -201,7 +202,7 @@ class KeyEntryPreferenceDialogFragment : PreferenceDialogFragmentCompat() { } else -> { view.findViewById(R.id.keyentry1_layout)?.apply { - this.setHint(R.string.key_hint) + this.setHint(sharedRes.string.key_hint) editText?.let { editText -> editText.requestFocus() editText.setText(key ?: "") diff --git a/common/src/main/java/com/thewizrd/common/preferences/SliderPreference.kt b/common/src/main/java/com/thewizrd/common/preferences/SliderPreference.kt index 0439bc28..0d640df1 100644 --- a/common/src/main/java/com/thewizrd/common/preferences/SliderPreference.kt +++ b/common/src/main/java/com/thewizrd/common/preferences/SliderPreference.kt @@ -12,6 +12,7 @@ import androidx.core.view.isVisible import androidx.preference.Preference import androidx.preference.PreferenceViewHolder import com.google.android.material.slider.Slider +import com.thewizrd.common.R as commonRes import com.thewizrd.shared_resources.R import java.math.BigDecimal import java.math.MathContext @@ -99,8 +100,8 @@ class SliderPreference : Preference { override fun onBindViewHolder(holder: PreferenceViewHolder) { super.onBindViewHolder(holder) - mSlider = holder.findViewById(R.id.seekbar) as Slider? - mSliderValueTextView = holder.findViewById(R.id.seekbar_value) as TextView? + mSlider = holder.findViewById(commonRes.id.seekbar) as Slider? + mSliderValueTextView = holder.findViewById(commonRes.id.seekbar_value) as TextView? val summaryView = holder.findViewById(android.R.id.summary) as TextView? if (mShowSliderValue) { diff --git a/common/src/main/java/com/thewizrd/common/viewmodels/LocationSearchViewModel.kt b/common/src/main/java/com/thewizrd/common/viewmodels/LocationSearchViewModel.kt index 7689051b..7feaeeba 100644 --- a/common/src/main/java/com/thewizrd/common/viewmodels/LocationSearchViewModel.kt +++ b/common/src/main/java/com/thewizrd/common/viewmodels/LocationSearchViewModel.kt @@ -5,10 +5,10 @@ import androidx.annotation.StringRes import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import com.thewizrd.common.BuildConfig -import com.thewizrd.common.R import com.thewizrd.common.location.LocationProvider import com.thewizrd.common.location.LocationResult import com.thewizrd.common.utils.ErrorMessage +import com.thewizrd.shared_resources.R import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.exceptions.WeatherException import com.thewizrd.shared_resources.locationdata.LocationData diff --git a/wearapp/src/fullgms/java/com/thewizrd/simpleweather/FirebaseConfigurator.kt b/wearapp/src/fullgms/java/com/thewizrd/simpleweather/FirebaseConfigurator.kt index bfc8a745..be295f67 100644 --- a/wearapp/src/fullgms/java/com/thewizrd/simpleweather/FirebaseConfigurator.kt +++ b/wearapp/src/fullgms/java/com/thewizrd/simpleweather/FirebaseConfigurator.kt @@ -8,6 +8,7 @@ import com.google.firebase.remoteconfig.ConfigUpdate import com.google.firebase.remoteconfig.ConfigUpdateListener import com.google.firebase.remoteconfig.FirebaseRemoteConfig import com.google.firebase.remoteconfig.FirebaseRemoteConfigException +import com.thewizrd.shared_resources.R import com.thewizrd.shared_resources.remoteconfig.remoteConfigService import com.thewizrd.shared_resources.utils.AnalyticsProps import com.thewizrd.shared_resources.utils.CrashlyticsLoggingTree diff --git a/wearapp/src/fullgms/java/com/thewizrd/simpleweather/extras/Extras.kt b/wearapp/src/fullgms/java/com/thewizrd/simpleweather/extras/Extras.kt index c7d6e930..e9e34372 100644 --- a/wearapp/src/fullgms/java/com/thewizrd/simpleweather/extras/Extras.kt +++ b/wearapp/src/fullgms/java/com/thewizrd/simpleweather/extras/Extras.kt @@ -6,10 +6,10 @@ package com.thewizrd.simpleweather.extras import android.content.Context import android.content.Intent import android.widget.Toast +import com.thewizrd.extras.R import com.thewizrd.extras.extrasModule import com.thewizrd.shared_resources.di.localBroadcastManager import com.thewizrd.simpleweather.FirebaseConfigurator -import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.preferences.SettingsActivity import com.thewizrd.simpleweather.wearable.WearableListenerActions diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/main/MainActivity.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/main/MainActivity.kt index 22d7372c..a14903f7 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/main/MainActivity.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/main/MainActivity.kt @@ -16,6 +16,7 @@ import com.thewizrd.common.helpers.locationPermissionEnabled import com.thewizrd.common.location.LocationResult import com.thewizrd.common.utils.ActivityUtils.showToast import com.thewizrd.common.utils.ErrorMessage +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.preferences.SettingsManager @@ -79,7 +80,7 @@ class MainActivity : UserLocaleActivity() { // permission denied, boo! Disable the // functionality that depends on this permission. settingsManager.setFollowGPS(false) - showToast(R.string.error_location_denied, Toast.LENGTH_SHORT) + showToast(sharedRes.string.error_location_denied, Toast.LENGTH_SHORT) } } ) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/preferences/KeyEntryPreferenceDialogFragment.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/preferences/KeyEntryPreferenceDialogFragment.kt index 56675b0e..ba9b6ea7 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/preferences/KeyEntryPreferenceDialogFragment.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/preferences/KeyEntryPreferenceDialogFragment.kt @@ -7,6 +7,8 @@ import android.view.View import android.widget.TextView import androidx.core.widget.doAfterTextChanged import com.google.android.material.textfield.TextInputLayout +import com.thewizrd.common.R as commonRes +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.weatherdata.auth.* import com.thewizrd.simpleweather.R @@ -107,10 +109,10 @@ class KeyEntryPreferenceDialogFragment : WearPreferenceDialogFragment() { when (authType) { AuthType.APPID_APPCODE, AuthType.BASIC -> { - inflate(R.layout.layout_keyentry2_dialog, null) + inflate(commonRes.layout.layout_keyentry2_dialog, null) } else -> { - inflate(R.layout.layout_keyentry_dialog, null) + inflate(commonRes.layout.layout_keyentry_dialog, null) } } } @@ -125,8 +127,8 @@ class KeyEntryPreferenceDialogFragment : WearPreferenceDialogFragment() { AuthType.APPID_APPCODE -> { val credentials = providerKey as? ProviderAppKey - view.findViewById(R.id.keyentry1_layout)?.apply { - this.setHint(R.string.hint_appid) + view.findViewById(commonRes.id.keyentry1_layout)?.apply { + this.setHint(sharedRes.string.hint_appid) editText?.let { editText -> editText.requestFocus() editText.setText(credentials?.appId ?: "") @@ -137,8 +139,8 @@ class KeyEntryPreferenceDialogFragment : WearPreferenceDialogFragment() { } } } - view.findViewById(R.id.keyentry2_layout)?.apply { - this.setHint(R.string.hint_appcode) + view.findViewById(commonRes.id.keyentry2_layout)?.apply { + this.setHint(sharedRes.string.hint_appcode) editText?.let { editText -> editText.setText(credentials?.appCode ?: "") @@ -151,8 +153,8 @@ class KeyEntryPreferenceDialogFragment : WearPreferenceDialogFragment() { AuthType.BASIC -> { val credentials = providerKey as? BasicAuthProviderKey - view.findViewById(R.id.keyentry1_layout)?.apply { - this.setHint(R.string.hint_username) + view.findViewById(commonRes.id.keyentry1_layout)?.apply { + this.setHint(sharedRes.string.hint_username) editText?.let { editText -> editText.requestFocus() editText.setText(credentials?.username ?: "") @@ -163,8 +165,8 @@ class KeyEntryPreferenceDialogFragment : WearPreferenceDialogFragment() { } } } - view.findViewById(R.id.keyentry2_layout)?.apply { - this.setHint(R.string.hint_password) + view.findViewById(commonRes.id.keyentry2_layout)?.apply { + this.setHint(sharedRes.string.hint_password) endIconMode = TextInputLayout.END_ICON_PASSWORD_TOGGLE passwordVisibilityToggleRequested(true) @@ -178,8 +180,8 @@ class KeyEntryPreferenceDialogFragment : WearPreferenceDialogFragment() { } } else -> { - view.findViewById(R.id.keyentry1_layout)?.apply { - this.setHint(R.string.key_hint) + view.findViewById(commonRes.id.keyentry1_layout)?.apply { + this.setHint(sharedRes.string.key_hint) editText?.let { editText -> editText.requestFocus() editText.setText(key ?: "") diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/preferences/SettingsActivity.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/preferences/SettingsActivity.kt index 8f800989..58e6d8b8 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/preferences/SettingsActivity.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/preferences/SettingsActivity.kt @@ -43,6 +43,7 @@ import com.thewizrd.common.helpers.getBackgroundLocationRationale import com.thewizrd.common.helpers.locationPermissionEnabled import com.thewizrd.common.utils.ErrorMessage import com.thewizrd.common.wearable.WearConnectionStatus +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.controls.ProviderEntry import com.thewizrd.shared_resources.di.localBroadcastManager @@ -178,7 +179,7 @@ class SettingsActivity : UserLocaleActivity() { private lateinit var onBackPressedCallback: OnBackPressedCallback override val titleResId: Int - get() = R.string.title_activity_settings + get() = sharedRes.string.title_activity_settings override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -196,7 +197,7 @@ class SettingsActivity : UserLocaleActivity() { // functionality that depends on this permission. followGps.isChecked = false settingsManager.setFollowGPS(false) - showToast(R.string.error_location_denied, Toast.LENGTH_SHORT) + showToast(sharedRes.string.error_location_denied, Toast.LENGTH_SHORT) } } ) @@ -205,7 +206,7 @@ class SettingsActivity : UserLocaleActivity() { override fun handleOnBackPressed() { if (isProviderAndKeyInvalid()) { // Set keyentrypref color to red - showToast(R.string.message_enter_apikey, Toast.LENGTH_SHORT) + showToast(sharedRes.string.message_enter_apikey, Toast.LENGTH_SHORT) } } } @@ -427,7 +428,7 @@ class SettingsActivity : UserLocaleActivity() { ) ) { showToast( - R.string.error_enable_location_services, + sharedRes.string.error_enable_location_services, Toast.LENGTH_SHORT ) settingsManager.setFollowGPS(false) @@ -457,11 +458,11 @@ class SettingsActivity : UserLocaleActivity() { } intervalPref = findPreference(SettingsManager.KEY_REFRESHINTERVAL)!! if (enableAdditionalRefreshIntervals()) { - intervalPref.setEntries(R.array.premium_refreshinterval_entries) - intervalPref.setEntryValues(R.array.premium_refreshinterval_values) + intervalPref.setEntries(sharedRes.array.premium_refreshinterval_entries) + intervalPref.setEntryValues(sharedRes.array.premium_refreshinterval_values) } else { - intervalPref.setEntries(R.array.refreshinterval_entries) - intervalPref.setEntryValues(R.array.refreshinterval_values) + intervalPref.setEntries(sharedRes.array.refreshinterval_entries) + intervalPref.setEntryValues(sharedRes.array.refreshinterval_values) } bgLocationPref = findPreference(KEY_BGLOCATIONACCESS)!! @@ -497,7 +498,7 @@ class SettingsActivity : UserLocaleActivity() { for (i in langCodes.indices) { val code = langCodes[i] if (TextUtils.isEmpty(code)) { - langEntries[i] = getString(R.string.summary_default) + langEntries[i] = getString(sharedRes.string.summary_default) } else { val localeCode = code.toString() val locale = LocaleUtils.getLocaleForTag(localeCode) @@ -765,7 +766,7 @@ class SettingsActivity : UserLocaleActivity() { dialog.dismiss() } else { - showToast(R.string.message_keyinvalid, Toast.LENGTH_SHORT) + showToast(sharedRes.string.message_keyinvalid, Toast.LENGTH_SHORT) } } catch (e: WeatherException) { Logger.writeLine(Log.ERROR, e) @@ -790,7 +791,7 @@ class SettingsActivity : UserLocaleActivity() { private val localeSummaryFunc: Function = Function { input -> if (input.isNullOrBlank()) { - getString(R.string.summary_default) + getString(sharedRes.string.summary_default) } else { LocaleUtils.getLocaleDisplayName() } @@ -833,13 +834,18 @@ class SettingsActivity : UserLocaleActivity() { val colorSpan = ForegroundColorSpan(if (keyVerified) Color.GREEN else Color.RED) val summary: Spannable = SpannableString( - if (keyVerified) getString(R.string.message_keyverified) else getString(R.string.message_keyinvalid) + if (keyVerified) getString(sharedRes.string.message_keyverified) else getString( + sharedRes.string.message_keyinvalid + ) ) summary.setSpan(colorSpan, 0, summary.length, 0) keyEntry.summary = summary } else { keyEntry.summary = - getString(R.string.pref_summary_apikey, providerAPI ?: WeatherIcons.EM_DASH) + getString( + sharedRes.string.pref_summary_apikey, + providerAPI ?: WeatherIcons.EM_DASH + ) } } @@ -914,12 +920,12 @@ class SettingsActivity : UserLocaleActivity() { private lateinit var pressureUnitPref: ListPreference override val titleResId: Int - get() = R.string.pref_title_units + get() = sharedRes.string.pref_title_units override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.pref_units, rootKey) - preferenceScreen.setTitle(R.string.pref_title_units) + preferenceScreen.setTitle(sharedRes.string.pref_title_units) tempUnitPref = findPreference(SettingsManager.KEY_TEMPUNIT)!! speedUnitPref = findPreference(SettingsManager.KEY_SPEEDUNIT)!! @@ -931,8 +937,8 @@ class SettingsActivity : UserLocaleActivity() { Preference.OnPreferenceClickListener { activity?.let { val params = WearDialogParams.Builder(it) - .setTitle(R.string.pref_title_units) - .setItems(R.array.default_units) { dialog, which -> + .setTitle(sharedRes.string.pref_title_units) + .setItems(sharedRes.array.default_units) { dialog, which -> val isFahrenheit = which == 0 tempUnitPref.value = if (isFahrenheit) Units.FAHRENHEIT else Units.CELSIUS @@ -960,7 +966,7 @@ class SettingsActivity : UserLocaleActivity() { class IconsFragment : WearIconProviderPickerFragment() { override val titleResId: Int - get() = R.string.pref_title_icons + get() = sharedRes.string.pref_title_icons override fun getDefaultKey(): String { return settingsManager.getIconsProvider() @@ -1012,7 +1018,7 @@ class SettingsActivity : UserLocaleActivity() { } override val titleResId: Int - get() = R.string.pref_title_about + get() = sharedRes.string.pref_title_about override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.pref_aboutapp, rootKey) @@ -1049,7 +1055,7 @@ class SettingsActivity : UserLocaleActivity() { private val confirmationViewModel: ConfirmationViewModel by viewModels() override val titleResId: Int - get() = R.string.pref_title_credits + get() = sharedRes.string.pref_title_credits override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -1118,7 +1124,7 @@ class SettingsActivity : UserLocaleActivity() { class OSSCreditsFragment : SwipeDismissPreferenceFragment() { override val titleResId: Int - get() = R.string.pref_title_oslibs + get() = sharedRes.string.pref_title_oslibs override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.pref_oslibs, rootKey) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/services/ServiceNotificationHelper.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/services/ServiceNotificationHelper.kt index b0bf359f..8be96454 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/services/ServiceNotificationHelper.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/services/ServiceNotificationHelper.kt @@ -8,6 +8,7 @@ import android.os.Build import androidx.annotation.RequiresApi import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.simpleweather.R internal object ServiceNotificationHelper { @@ -19,7 +20,7 @@ internal object ServiceNotificationHelper { // Gets an instance of the NotificationManager service val mNotifyMgr = context.getSystemService(NotificationManager::class.java) var mChannel = mNotifyMgr.getNotificationChannel(NOT_CHANNEL_ID) - val notchannel_name = context.resources.getString(R.string.not_channel_name_general) + val notchannel_name = context.resources.getString(sharedRes.string.not_channel_name_general) if (mChannel == null) { mChannel = NotificationChannel( NOT_CHANNEL_ID, @@ -39,9 +40,9 @@ internal object ServiceNotificationHelper { @RequiresApi(Build.VERSION_CODES.O) internal fun getForegroundNotification(context: Context): Notification { return NotificationCompat.Builder(context, NOT_CHANNEL_ID) - .setSmallIcon(R.drawable.ic_launcher_monochrome) - .setContentTitle(context.getString(R.string.not_title_weather_update)) - .setColor(ContextCompat.getColor(context, R.color.colorPrimary)) + .setSmallIcon(sharedRes.drawable.ic_launcher_monochrome) + .setContentTitle(context.getString(sharedRes.string.not_title_weather_update)) + .setColor(ContextCompat.getColor(context, sharedRes.color.colorPrimary)) .setOnlyAlertOnce(true) .setNotificationSilent() .setPriority(NotificationCompat.PRIORITY_LOW) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/services/WeatherUpdaterWorker.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/services/WeatherUpdaterWorker.kt index 7c2ce068..3925e7a1 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/services/WeatherUpdaterWorker.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/services/WeatherUpdaterWorker.kt @@ -13,6 +13,7 @@ import com.thewizrd.common.utils.LiveDataUtils.awaitWithTimeout import com.thewizrd.common.weatherdata.WeatherDataLoader import com.thewizrd.common.weatherdata.WeatherRequest import com.thewizrd.common.weatherdata.WeatherResult +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.preferences.SettingsManager @@ -235,7 +236,7 @@ class WeatherUpdaterWorker(context: Context, workerParams: WorkerParameters) : C val locMan = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager? if (locMan == null || !LocationManagerCompat.isLocationEnabled(locMan)) { - return LocationResult.Error(errorMessage = ErrorMessage.Resource(R.string.error_retrieve_location)) + return LocationResult.Error(errorMessage = ErrorMessage.Resource(sharedRes.string.error_retrieve_location)) } return locationProvider.getLatestLocationData(settingsManager.getLastGPSLocData()) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/ConfirmationOverlay.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/ConfirmationOverlay.kt index 6ef2c659..94a126cc 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/ConfirmationOverlay.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/ConfirmationOverlay.kt @@ -13,6 +13,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.wear.R as wearRes import androidx.wear.compose.material3.ConfirmationDialog import androidx.wear.compose.material3.ConfirmationDialogDefaults import androidx.wear.compose.material3.FailureConfirmationDialog @@ -90,7 +91,7 @@ fun ConfirmationOverlay( }, content = { val image = - AnimatedImageVector.animatedVectorResource(R.drawable.open_on_phone_animation) + AnimatedImageVector.animatedVectorResource(wearRes.drawable.open_on_phone_animation) var atEnd by remember { mutableStateOf(false) } Icon( @@ -102,7 +103,7 @@ fun ConfirmationOverlay( } ), painter = rememberAnimatedVectorPainter(image, atEnd), - contentDescription = stringResource(R.string.common_open_on_phone) + contentDescription = stringResource(com.google.android.gms.base.R.string.common_open_on_phone) ) LaunchedEffect(Unit) { diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherAlertPanel.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherAlertPanel.kt index 34ec863b..e26eefd4 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherAlertPanel.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherAlertPanel.kt @@ -34,6 +34,7 @@ import androidx.wear.compose.material3.Text import androidx.wear.compose.ui.tooling.preview.WearPreviewFontScales import com.google.android.horologist.annotations.ExperimentalHorologistApi import com.thewizrd.common.controls.WeatherAlertViewModel +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.utils.getColorFromAlertSeverity import com.thewizrd.shared_resources.utils.getDrawableFromAlertType import com.thewizrd.shared_resources.weatherdata.model.WeatherAlertSeverity @@ -59,7 +60,7 @@ private fun WeatherAlertPanel( title: String, alertBodyMessage: CharSequence, @ColorInt alertSeverityColor: Int, - @DrawableRes alertDrawable: Int = R.drawable.ic_error + @DrawableRes alertDrawable: Int = sharedRes.drawable.ic_error ) { var showDialog by remember { mutableStateOf(false) } val severityColor = remember(alertSeverityColor) { Color(alertSeverityColor) } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherDetailItem.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherDetailItem.kt index 72da1d01..2e7ba5dc 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherDetailItem.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherDetailItem.kt @@ -20,6 +20,7 @@ import androidx.wear.compose.material3.Text import androidx.wear.compose.ui.tooling.preview.WearPreviewFontScales import com.thewizrd.common.controls.DetailItemViewModel import com.thewizrd.common.controls.WeatherDetailsType +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.ui.compose.tools.WearPreviewDevices import com.thewizrd.simpleweather.ui.text.spannableStringToAnnotatedString @@ -53,7 +54,7 @@ fun WeatherDetailItem( modifier = Modifier .size(ButtonDefaults.IconSize) .wrapContentSize(align = Alignment.Center), - painter = painterResource(id = R.drawable.ic_error), + painter = painterResource(id = sharedRes.drawable.ic_error), contentDescription = "", colorFilter = ColorFilter.tint(LocalContentColor.current) ) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherForecastPanel.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherForecastPanel.kt index fba50b82..1468c9dc 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherForecastPanel.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherForecastPanel.kt @@ -33,6 +33,7 @@ import androidx.wear.tooling.preview.devices.WearDevices import com.thewizrd.common.controls.DetailItemViewModel import com.thewizrd.common.controls.ForecastItemViewModel import com.thewizrd.common.controls.WeatherDetailsType +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.designer.initializeDependencies import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.simpleweather.R @@ -100,7 +101,7 @@ fun WeatherForecastPanel( ) Icon( modifier = Modifier.size(28.dp), - painter = painterResource(id = R.drawable.wi_direction_up), + painter = painterResource(id = sharedRes.drawable.wi_direction_up), tint = Color(0xFFFF4500), contentDescription = null ) @@ -118,7 +119,7 @@ fun WeatherForecastPanel( ) Icon( modifier = Modifier.size(28.dp), - painter = painterResource(id = R.drawable.wi_direction_down), + painter = painterResource(id = sharedRes.drawable.wi_direction_down), tint = Color(0xFF87CEFA), contentDescription = null ) @@ -136,8 +137,8 @@ fun WeatherForecastPanel( modifier = Modifier .size(20.dp) .padding(end = 2.dp), - painter = painterResource(R.drawable.wi_umbrella), - tint = colorResource(R.color.colorPrimaryLight), + painter = painterResource(sharedRes.drawable.wi_umbrella), + tint = colorResource(sharedRes.color.colorPrimaryLight), contentDescription = null ) Text( @@ -145,7 +146,7 @@ fun WeatherForecastPanel( style = MaterialTheme.typography.bodyLarge.copy(fontSize = 14.sp), textAlign = TextAlign.End, maxLines = 1, - color = colorResource(R.color.colorPrimaryLight) + color = colorResource(sharedRes.color.colorPrimaryLight) ) } } @@ -168,7 +169,7 @@ fun WeatherForecastPanel( .padding(end = 2.dp) .rotate(windData.iconRotation.toFloat()) .align(Alignment.CenterVertically), - painter = painterResource(R.drawable.wi_wind_direction), + painter = painterResource(sharedRes.drawable.wi_wind_direction), tint = Color(0xFF20B2AA), contentDescription = null ) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherHourlyForecastPanel.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherHourlyForecastPanel.kt index ace487be..f5348ba3 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherHourlyForecastPanel.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherHourlyForecastPanel.kt @@ -41,6 +41,7 @@ import androidx.wear.tooling.preview.devices.WearDevices import com.thewizrd.common.controls.DetailItemViewModel import com.thewizrd.common.controls.HourlyForecastItemViewModel import com.thewizrd.common.controls.WeatherDetailsType +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.designer.initializeDependencies import com.thewizrd.shared_resources.icons.WeatherIcons @@ -151,8 +152,8 @@ fun WeatherHourlyForecastPanel( .size(20.dp) .padding(end = 2.dp) .align(Alignment.CenterVertically), - painter = painterResource(R.drawable.wi_umbrella), - tint = colorResource(R.color.colorPrimaryLight), + painter = painterResource(sharedRes.drawable.wi_umbrella), + tint = colorResource(sharedRes.color.colorPrimaryLight), contentDescription = null ) Text( @@ -161,7 +162,7 @@ fun WeatherHourlyForecastPanel( style = MaterialTheme.typography.bodyLarge.copy(fontSize = 14.sp), textAlign = TextAlign.End, maxLines = 1, - color = colorResource(R.color.colorPrimaryLight) + color = colorResource(sharedRes.color.colorPrimaryLight) ) } } @@ -184,7 +185,7 @@ fun WeatherHourlyForecastPanel( .padding(end = 2.dp) .rotate(windData.iconRotation.toFloat()) .align(Alignment.CenterVertically), - painter = painterResource(R.drawable.wi_wind_direction), + painter = painterResource(sharedRes.drawable.wi_wind_direction), tint = Color(0xFF20B2AA), contentDescription = null ) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherMinutelyForecastPanel.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherMinutelyForecastPanel.kt index 8ea9373d..4df48348 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherMinutelyForecastPanel.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherMinutelyForecastPanel.kt @@ -24,6 +24,7 @@ import androidx.wear.compose.material3.Icon import androidx.wear.compose.material3.MaterialTheme import androidx.wear.compose.material3.Text import androidx.wear.tooling.preview.devices.WearDevices +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.viewmodels.MinutelyForecastViewModel @@ -79,9 +80,9 @@ private fun WeatherMinutelyForecastPanel( modifier = Modifier .weight(1f, false) .size(20.dp), - painter = painterResource(R.drawable.wi_raindrop), + painter = painterResource(sharedRes.drawable.wi_raindrop), contentDescription = null, - tint = colorResource(id = R.color.colorSecondaryDark) + tint = colorResource(id = sharedRes.color.colorSecondaryDark) ) } } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/preferences/WearEditTextPreference.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/preferences/WearEditTextPreference.kt index e6f82822..2dc2474e 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/preferences/WearEditTextPreference.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/preferences/WearEditTextPreference.kt @@ -39,6 +39,7 @@ import androidx.wear.compose.material3.ButtonDefaults import androidx.wear.compose.material3.Icon import androidx.wear.compose.material3.MaterialTheme import androidx.wear.compose.material3.Text +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.helpers.SimpleActionModeCallback @@ -123,7 +124,7 @@ fun WearEditTextPreference( modifier = Modifier .size(24.dp) .wrapContentSize(align = Alignment.Center), - painter = painterResource(id = R.drawable.ic_close_white_24dp), + painter = painterResource(id = sharedRes.drawable.ic_close_white_24dp), contentDescription = stringResource(id = android.R.string.cancel) ) } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/preferences/WearListPreference.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/preferences/WearListPreference.kt index 972da086..f0cecb91 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/preferences/WearListPreference.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/preferences/WearListPreference.kt @@ -28,6 +28,7 @@ import androidx.wear.compose.material3.ButtonDefaults import androidx.wear.compose.material3.Icon import androidx.wear.compose.material3.RadioButton import androidx.wear.compose.material3.Text +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.ui.compose.tools.WearPreviewDevices @@ -100,7 +101,7 @@ fun WearListPreference( modifier = Modifier .size(24.dp) .wrapContentSize(align = Alignment.Center), - painter = painterResource(id = R.drawable.ic_close_white_24dp), + painter = painterResource(id = sharedRes.drawable.ic_close_white_24dp), contentDescription = stringResource(id = android.R.string.cancel) ) } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/preferences/DetailsWeatherTileConfigScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/preferences/DetailsWeatherTileConfigScreen.kt index dab0b2aa..4e983b5e 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/preferences/DetailsWeatherTileConfigScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/preferences/DetailsWeatherTileConfigScreen.kt @@ -71,6 +71,7 @@ import androidx.wear.compose.material3.LocalContentColor import androidx.wear.compose.material3.ScreenScaffold import androidx.wear.compose.material3.Text import com.thewizrd.common.controls.WeatherDetailsType +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.designer.initializeDependencies import com.thewizrd.shared_resources.icons.WeatherIcons @@ -315,7 +316,7 @@ private fun DetailsWeatherTileConfigScreen( ) { Icon( modifier = Modifier.size(ButtonDefaults.IconSize), - painter = painterResource(id = R.drawable.ic_close_white_24dp), + painter = painterResource(id = sharedRes.drawable.ic_close_white_24dp), contentDescription = null, ) } @@ -396,7 +397,7 @@ private fun DetailsWeatherTileConfigScreen( Icon( modifier = Modifier.size(ButtonDefaults.IconSize), painter = painterResource(id = R.drawable.ic_restart_alt_24dp), - contentDescription = stringResource(R.string.action_reset), + contentDescription = stringResource(sharedRes.string.action_reset), ) } IconButton( @@ -458,14 +459,14 @@ private fun DetailsWeatherTileConfigScreen( modifier = Modifier.fillMaxSize(), visible = showAddTileDialog, onDismissRequest = { showAddTileDialog = false }, - title = { Text(text = stringResource(id = R.string.label_details)) }, + title = { Text(text = stringResource(id = sharedRes.string.label_details)) }, edgeButton = { EdgeButton( onClick = { showAddTileDialog = false } ) { Icon( modifier = Modifier.size(ButtonDefaults.IconSize), - painter = painterResource(id = R.drawable.ic_close_white_24dp), + painter = painterResource(id = sharedRes.drawable.ic_close_white_24dp), contentDescription = stringResource(android.R.string.cancel) ) } @@ -558,26 +559,26 @@ private fun WeatherDetailsType.toWeatherIcon(): String = when (this) { } private fun WeatherDetailsType.toLabelStringResId(): Int = when (this) { - WeatherDetailsType.SUNRISE -> R.string.label_sunrise - WeatherDetailsType.SUNSET -> R.string.label_sunset - WeatherDetailsType.FEELSLIKE -> R.string.label_feelslike - WeatherDetailsType.WINDSPEED -> R.string.label_wind - WeatherDetailsType.WINDGUST -> R.string.label_windgust - WeatherDetailsType.HUMIDITY -> R.string.label_humidity - WeatherDetailsType.PRESSURE -> R.string.label_pressure - WeatherDetailsType.VISIBILITY -> R.string.label_visibility - WeatherDetailsType.POPCHANCE -> R.string.label_chance - WeatherDetailsType.POPCLOUDINESS -> R.string.label_cloudiness - WeatherDetailsType.POPRAIN -> R.string.label_qpf_rain - WeatherDetailsType.POPSNOW -> R.string.label_qpf_snow - WeatherDetailsType.DEWPOINT -> R.string.label_dewpoint - WeatherDetailsType.MOONRISE -> R.string.label_moonrise - WeatherDetailsType.MOONSET -> R.string.label_moonset - WeatherDetailsType.MOONPHASE -> R.string.label_moonphase - WeatherDetailsType.BEAUFORT -> R.string.label_beaufort - WeatherDetailsType.UV -> R.string.label_uv - WeatherDetailsType.AIRQUALITY -> R.string.label_airquality - WeatherDetailsType.TREEPOLLEN -> R.string.label_tree_pollen - WeatherDetailsType.GRASSPOLLEN -> R.string.label_grass_pollen - WeatherDetailsType.RAGWEEDPOLLEN -> R.string.label_ragweed_pollen + WeatherDetailsType.SUNRISE -> sharedRes.string.label_sunrise + WeatherDetailsType.SUNSET -> sharedRes.string.label_sunset + WeatherDetailsType.FEELSLIKE -> sharedRes.string.label_feelslike + WeatherDetailsType.WINDSPEED -> sharedRes.string.label_wind + WeatherDetailsType.WINDGUST -> sharedRes.string.label_windgust + WeatherDetailsType.HUMIDITY -> sharedRes.string.label_humidity + WeatherDetailsType.PRESSURE -> sharedRes.string.label_pressure + WeatherDetailsType.VISIBILITY -> sharedRes.string.label_visibility + WeatherDetailsType.POPCHANCE -> sharedRes.string.label_chance + WeatherDetailsType.POPCLOUDINESS -> sharedRes.string.label_cloudiness + WeatherDetailsType.POPRAIN -> sharedRes.string.label_qpf_rain + WeatherDetailsType.POPSNOW -> sharedRes.string.label_qpf_snow + WeatherDetailsType.DEWPOINT -> sharedRes.string.label_dewpoint + WeatherDetailsType.MOONRISE -> sharedRes.string.label_moonrise + WeatherDetailsType.MOONSET -> sharedRes.string.label_moonset + WeatherDetailsType.MOONPHASE -> sharedRes.string.label_moonphase + WeatherDetailsType.BEAUFORT -> sharedRes.string.label_beaufort + WeatherDetailsType.UV -> sharedRes.string.label_uv + WeatherDetailsType.AIRQUALITY -> sharedRes.string.label_airquality + WeatherDetailsType.TREEPOLLEN -> sharedRes.string.label_tree_pollen + WeatherDetailsType.GRASSPOLLEN -> sharedRes.string.label_grass_pollen + WeatherDetailsType.RAGWEEDPOLLEN -> sharedRes.string.label_ragweed_pollen } \ No newline at end of file diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupLocationListScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupLocationListScreen.kt index 92756c4c..6adbac27 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupLocationListScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupLocationListScreen.kt @@ -38,6 +38,7 @@ import androidx.wear.compose.material3.Text import androidx.wear.compose.material3.lazy.rememberTransformationSpec import androidx.wear.compose.material3.lazy.transformedHeight import com.thewizrd.common.viewmodels.LocationSearchViewModel +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.locationdata.LocationQuery @@ -129,7 +130,7 @@ private fun SetupLocationListScreen( .animateItem(), transformation = SurfaceTransformation(transformationSpec), ) { - Text(text = stringResource(id = R.string.label_nav_locations)) + Text(text = stringResource(id = sharedRes.string.label_nav_locations)) } } @@ -157,7 +158,7 @@ private fun SetupLocationListScreen( } else { { Icon( - painter = painterResource(id = R.drawable.ic_place_white_24dp), + painter = painterResource(id = sharedRes.drawable.ic_place_white_24dp), contentDescription = null ) } @@ -172,9 +173,10 @@ private fun SetupLocationListScreen( .animateItem(), transformation = SurfaceTransformation(transformationSpec), ) { + val creditPrefix = stringResource(sharedRes.string.credit_prefix) Text(text = remember(context, locationSource) { buildString { - append(context.getString(R.string.credit_prefix)) + append(creditPrefix) append(" ") append(locationSource) } @@ -192,7 +194,7 @@ private fun SetupLocationListScreen( verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically) ) { Text( - text = stringResource(id = R.string.werror_querynotfound), + text = stringResource(id = sharedRes.string.werror_querynotfound), textAlign = TextAlign.Center ) CompactButton( diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupLocationSearchScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupLocationSearchScreen.kt index 7dc8df96..f4e3c50d 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupLocationSearchScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupLocationSearchScreen.kt @@ -42,6 +42,7 @@ import androidx.wear.compose.material3.IconButtonDefaults import androidx.wear.compose.material3.ListHeader import androidx.wear.compose.material3.ScreenScaffold import androidx.wear.compose.material3.Text +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.simpleweather.R @@ -71,6 +72,8 @@ fun SetupLocationSearchScreen(navController: NavController) { } } + val searchHintPrompt = stringResource(sharedRes.string.location_search_hint) + SetupLocationSearchScreen( onVoiceSearch = { val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply { @@ -80,7 +83,7 @@ fun SetupLocationSearchScreen(navController: NavController) { ) putExtra( RecognizerIntent.EXTRA_PROMPT, - context.getString(R.string.location_search_hint) + searchHintPrompt ) } @@ -148,7 +151,7 @@ private fun SetupLocationSearchScreen( top = 26.dp, bottom = 16.dp ) ) { - Text(text = stringResource(id = R.string.location_search_hint)) + Text(text = stringResource(id = sharedRes.string.location_search_hint)) } Box( @@ -171,7 +174,7 @@ private fun SetupLocationSearchScreen( ) { Icon( painter = painterResource(R.drawable.ic_keyboard_voice_black_24dp), - contentDescription = stringResource(R.string.abc_searchview_description_voice) + contentDescription = stringResource(androidx.appcompat.R.string.abc_searchview_description_voice) ) } @@ -189,7 +192,7 @@ private fun SetupLocationSearchScreen( ) { Icon( painter = painterResource(R.drawable.ic_keyboard_black_24dp), - contentDescription = stringResource(R.string.abc_searchview_description_search) + contentDescription = stringResource(androidx.appcompat.R.string.abc_searchview_description_search) ) } } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupScreen.kt index cbf5552b..ae262160 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupScreen.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.navigation.NavController +import androidx.wear.R as wearRes import androidx.wear.compose.foundation.lazy.TransformingLazyColumn import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState import androidx.wear.compose.foundation.rotary.RotaryScrollableDefaults @@ -44,6 +45,7 @@ import androidx.wear.compose.navigation.rememberSwipeDismissableNavController import com.thewizrd.common.helpers.locationPermissionEnabled import com.thewizrd.common.utils.ErrorMessage import com.thewizrd.common.viewmodels.LocationSearchViewModel +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.simpleweather.BuildConfig import com.thewizrd.simpleweather.R @@ -146,7 +148,7 @@ private fun SetupScreen( ) { item { ListHeader { - Text(text = stringResource(id = R.string.app_name)) + Text(text = stringResource(id = sharedRes.string.app_name)) } } item { @@ -161,7 +163,7 @@ private fun SetupScreen( }, label = { Text( - text = stringResource(id = R.string.location_search_hint), + text = stringResource(id = sharedRes.string.location_search_hint), color = LocalContentColor.current ) }, @@ -184,12 +186,12 @@ private fun SetupScreen( fetchGeoLocation() }, label = { - Text(text = stringResource(id = R.string.label_gpsfollow)) + Text(text = stringResource(id = sharedRes.string.label_gpsfollow)) }, icon = { Icon( - painter = painterResource(id = R.drawable.ic_my_location_white_24dp), - contentDescription = stringResource(id = R.string.label_gpsfollow) + painter = painterResource(id = sharedRes.drawable.ic_my_location_white_24dp), + contentDescription = stringResource(id = sharedRes.string.label_gpsfollow) ) } ) @@ -211,7 +213,7 @@ private fun SetupScreen( icon = { Icon( modifier = Modifier.size(ButtonDefaults.IconSize), - painter = painterResource(id = R.drawable.common_full_open_on_phone), + painter = painterResource(id = com.google.android.gms.base.R.drawable.common_full_open_on_phone), contentDescription = stringResource(id = R.string.action_setupfromphone) ) } @@ -230,7 +232,7 @@ private fun SetupScreen( }, text = { Text( - text = stringResource(id = R.string.error_location_denied), + text = stringResource(id = sharedRes.string.error_location_denied), overflow = TextOverflow.Ellipsis, ) }, @@ -238,7 +240,7 @@ private fun SetupScreen( content = { Icon( modifier = Modifier.size(ConfirmationDialogDefaults.SmallIconSize), - painter = painterResource(id = R.drawable.ic_location_off_24dp), + painter = painterResource(id = sharedRes.drawable.ic_location_off_24dp), contentDescription = null ) } @@ -264,7 +266,7 @@ private fun SetupScreen( errorMessage.exception.message } - else -> stringResource(R.string.werror_unknown) + else -> stringResource(sharedRes.string.werror_unknown) }, overflow = TextOverflow.Ellipsis, ) @@ -273,7 +275,7 @@ private fun SetupScreen( content = { Icon( modifier = Modifier.size(ConfirmationDialogDefaults.SmallIconSize), - painter = painterResource(id = R.drawable.ic_error_white), + painter = painterResource(id = sharedRes.drawable.ic_error_white), contentDescription = null ) } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupSyncScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupSyncScreen.kt index 4bc702b1..9b844be2 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupSyncScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupSyncScreen.kt @@ -1,5 +1,6 @@ package com.thewizrd.simpleweather.ui.setup +import android.annotation.SuppressLint import android.content.Intent import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.animateFloat @@ -43,6 +44,7 @@ import androidx.wear.compose.material3.Text import androidx.wear.compose.material3.touchTargetAwareSize import androidx.wear.compose.navigation.rememberSwipeDismissableNavController import com.thewizrd.common.utils.ErrorMessage +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.utils.ContextUtils.isLargeWatch import com.thewizrd.shared_resources.wearable.WearableDataSync @@ -61,6 +63,7 @@ import com.thewizrd.simpleweather.wearable.WearableListenerActions.EXTRA_SUCCESS import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +@SuppressLint("LocalContextGetResourceValueCall") @Composable fun SetupSyncScreen( navController: NavController, @@ -196,7 +199,7 @@ private fun SetupSyncScreen( }, ) { Icon( - painter = painterResource(R.drawable.ic_close_white_24dp), + painter = painterResource(sharedRes.drawable.ic_close_white_24dp), contentDescription = stringResource(android.R.string.cancel) ) } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/theme/ViewModelExtras.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/theme/ViewModelExtras.kt index 17ee4093..ec85d534 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/theme/ViewModelExtras.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/theme/ViewModelExtras.kt @@ -10,21 +10,23 @@ import androidx.lifecycle.viewmodel.compose.viewModel /** Try to fetch a viewModel in [store] */ @Composable -inline fun viewModelInStore(store: S): Result = - runCatching { - var result: Result? = null - CompositionLocalProvider(LocalViewModelStoreOwner provides store) { - result = runCatching { viewModel(T::class.java) } - } - result!!.getOrThrow() +inline fun viewModelInStore(store: S): T { + var result: T? = null + CompositionLocalProvider(LocalViewModelStoreOwner provides store) { + result = viewModel(T::class.java) } + return result!! +} /** Try to fetch a viewModel with current context (i.e. activity) */ @Composable -inline fun safeActivityViewModel(): Result = runCatching { - val activity = LocalContext.current as? ViewModelStoreOwner - ?: throw IllegalStateException("Current context is not a viewModelStoreOwner.") - return viewModelInStore(activity) +inline fun safeActivityViewModel(): Result { + val context = LocalContext.current + return if (context is ViewModelStoreOwner) { + Result.success(viewModelInStore(context)) + } else { + Result.failure(IllegalStateException("Current context is not a viewModelStoreOwner.")) + } } /** Force fetch a viewModel inside context's viewModelStore */ diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt index 01bfdb8a..6a06f04b 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt @@ -1,5 +1,6 @@ package com.thewizrd.simpleweather.ui.weather +import android.annotation.SuppressLint import android.app.Activity import android.content.Intent import android.content.res.Configuration @@ -83,6 +84,7 @@ import com.thewizrd.common.controls.WeatherDetailsType import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.controls.toUiModel import com.thewizrd.common.utils.ErrorMessage +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.designer.initializeDependencies import com.thewizrd.shared_resources.icons.WeatherIcons @@ -123,6 +125,7 @@ import com.thewizrd.simpleweather.viewmodels.WeatherNowViewModel import com.thewizrd.simpleweather.wearable.WearableListenerActions import kotlinx.coroutines.launch +@SuppressLint("LocalContextGetResourceValueCall") @Composable fun WeatherNowScreen( navController: NavHostController, @@ -376,12 +379,12 @@ private fun NoLocationsPrompt( ) { Spacer(modifier = Modifier.height(8.dp)) Icon( - painter = painterResource(R.drawable.ic_location_off_24dp), + painter = painterResource(sharedRes.drawable.ic_location_off_24dp), contentDescription = null, ) Spacer(modifier = Modifier.height(8.dp)) Text( - text = stringResource(id = R.string.prompt_location_not_set), + text = stringResource(id = sharedRes.string.prompt_location_not_set), textAlign = TextAlign.Center, style = MaterialTheme.typography.bodyLarge ) @@ -431,7 +434,7 @@ private fun AlertsBox(navController: NavHostController) { ) { Icon( modifier = Modifier.size(IconButtonDefaults.SmallIconSize), - painter = painterResource(id = R.drawable.ic_error_white), + painter = painterResource(id = sharedRes.drawable.ic_error_white), tint = MaterialTheme.colorScheme.onErrorContainer, contentDescription = null ) @@ -463,7 +466,7 @@ private fun ColumnScope.WeatherLocation( modifier = Modifier .size(18.dp) .align(Alignment.CenterVertically), - painter = painterResource(id = R.drawable.ic_place_white_24dp), + painter = painterResource(id = sharedRes.drawable.ic_place_white_24dp), contentDescription = null ) } @@ -568,7 +571,7 @@ private fun HiLoLayout( modifier = Modifier .size(30.dp) .offset(x = (-4).dp), - painter = painterResource(id = R.drawable.wi_direction_up), + painter = painterResource(id = sharedRes.drawable.wi_direction_up), tint = Color(0xFFFF4500), contentDescription = null ) @@ -594,7 +597,7 @@ private fun HiLoLayout( modifier = Modifier .size(30.dp) .offset(x = (-4).dp), - painter = painterResource(id = R.drawable.wi_direction_down), + painter = painterResource(id = sharedRes.drawable.wi_direction_down), tint = Color(0xFF87CEFA), contentDescription = null ) @@ -638,8 +641,8 @@ private fun ConditionDetails( .size(20.dp) .padding(end = 4.dp) .align(Alignment.CenterVertically), - painter = painterResource(id = R.drawable.wi_umbrella), - tint = colorResource(R.color.colorPrimaryLight), + painter = painterResource(id = sharedRes.drawable.wi_umbrella), + tint = colorResource(sharedRes.color.colorPrimaryLight), contentDescription = null ) Text( @@ -648,7 +651,7 @@ private fun ConditionDetails( style = MaterialTheme.typography.bodySmall, textAlign = TextAlign.End, maxLines = 1, - color = colorResource(R.color.colorPrimaryLight) + color = colorResource(sharedRes.color.colorPrimaryLight) ) } } @@ -665,7 +668,7 @@ private fun ConditionDetails( .padding(end = 4.dp) .rotate(windData.iconRotation.toFloat()) .align(Alignment.CenterVertically), - painter = painterResource(id = R.drawable.wi_wind_direction), + painter = painterResource(id = sharedRes.drawable.wi_wind_direction), tint = Color(0xFF20B2AA), contentDescription = null ) @@ -825,7 +828,7 @@ private fun ForecastsButton( navController: NavHostController ) { NavigationButton( - label = stringResource(id = R.string.label_forecast), + label = stringResource(id = sharedRes.string.label_forecast), iconDrawableId = R.drawable.ic_date_range_black_24dp ) { navController.navigate(Screen.Forecast.route) @@ -837,7 +840,7 @@ private fun HourlyForecastsButton( navController: NavHostController ) { NavigationButton( - label = stringResource(id = R.string.label_hourlyforecast), + label = stringResource(id = sharedRes.string.label_hourlyforecast), iconDrawableId = R.drawable.ic_access_time_black_24dp ) { navController.navigate(Screen.HourlyForecast.route) @@ -849,8 +852,8 @@ private fun MinutelyForecastsButton( navController: NavHostController ) { NavigationButton( - label = stringResource(id = R.string.label_precipitation), - iconDrawableId = R.drawable.wi_raindrops + label = stringResource(id = sharedRes.string.label_precipitation), + iconDrawableId = sharedRes.drawable.wi_raindrops ) { navController.navigate(Screen.Precipitation.route) } @@ -861,7 +864,7 @@ private fun DetailsButton( navController: NavHostController ) { NavigationButton( - label = stringResource(id = R.string.label_details), + label = stringResource(id = sharedRes.string.label_details), iconDrawableId = R.drawable.ic_list_black_24dp ) { navController.navigate(Screen.Details.route) @@ -874,7 +877,7 @@ private fun DetailsTileEditorButton( ) { NavigationButton( label = stringResource(id = R.string.pref_title_detailstileeditor), - iconDrawableId = R.drawable.ic_mode_edit_white_24dp + iconDrawableId = sharedRes.drawable.ic_mode_edit_white_24dp ) { navController.navigate(Screen.DetailsTileEditor.route) } @@ -897,8 +900,8 @@ private fun SettingsButton( activity: Activity ) { NavigationButton( - label = stringResource(id = R.string.action_settings), - iconDrawableId = R.drawable.ic_settings_black_24dp + label = stringResource(id = sharedRes.string.action_settings), + iconDrawableId = sharedRes.drawable.ic_settings_black_24dp ) { activity.startActivity(Intent(activity, SettingsActivity::class.java)) } @@ -910,7 +913,7 @@ private fun OpenOnPhoneButton( ) { NavigationButton( label = stringResource(id = R.string.action_openonphone), - iconDrawableId = R.drawable.common_full_open_on_phone, + iconDrawableId = com.google.android.gms.base.R.drawable.common_full_open_on_phone, onClick = onOpenOnPhone ) } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ConfirmationViewModel.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ConfirmationViewModel.kt index 13671e88..1f4483e4 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ConfirmationViewModel.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ConfirmationViewModel.kt @@ -4,12 +4,12 @@ import androidx.annotation.DrawableRes import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.wear.compose.material3.ConfirmationDialogDefaults -import com.thewizrd.simpleweather.R import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update +import androidx.wear.R as wearRes class ConfirmationViewModel : ViewModel() { private val _confirmationEventsFlow = MutableStateFlow(null) @@ -29,7 +29,7 @@ class ConfirmationViewModel : ViewModel() { fun showSuccess(message: String? = null) { _confirmationEventsFlow.update { ConfirmationData( - animatedVectorResId = R.drawable.confirmation_animation, + animatedVectorResId = wearRes.drawable.confirmation_animation, confirmationType = ConfirmationType.Success, message = message ) @@ -39,7 +39,7 @@ class ConfirmationViewModel : ViewModel() { fun showFailure(message: String? = null) { _confirmationEventsFlow.update { ConfirmationData( - animatedVectorResId = R.drawable.failure_animation, + animatedVectorResId = wearRes.drawable.failure_animation, confirmationType = ConfirmationType.Failure, message = message ) @@ -49,7 +49,7 @@ class ConfirmationViewModel : ViewModel() { fun showOpenOnPhone(message: String? = null) { _confirmationEventsFlow.update { ConfirmationData( - animatedVectorResId = R.drawable.open_on_phone_animation, + animatedVectorResId = wearRes.drawable.open_on_phone_animation, confirmationType = ConfirmationType.OpenOnPhone, message = message ) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/AQIComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/AQIComplicationService.kt index c79d9011..8859fa31 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/AQIComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/AQIComplicationService.kt @@ -18,13 +18,13 @@ import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.AirQualityUtils.getIndexFromData import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.weatherdata.model.AirQuality -import com.thewizrd.simpleweather.R import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.withContext import timber.log.Timber import java.time.LocalDate import kotlin.math.max +import com.thewizrd.shared_resources.R as sharedRes class AQIComplicationService : BaseWeatherComplicationService() { companion object { @@ -37,7 +37,7 @@ class AQIComplicationService : BaseWeatherComplicationService() { ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT ) - private val complicationIconResId = R.drawable.wi_cloud + private val complicationIconResId = sharedRes.drawable.wi_cloud override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData { if (!supportedComplicationTypes.contains(request.complicationType)) { @@ -158,7 +158,7 @@ class AQIComplicationService : BaseWeatherComplicationService() { RangedValueComplicationData.Builder( aqiProgress, 0f, aqiProgressMax, PlainComplicationText.Builder( - "${getString(R.string.label_airquality_short)}: $aqiStr" + "${getString(sharedRes.string.label_airquality_short)}: $aqiStr" ).build() ).setMonochromaticImage( MonochromaticImage.Builder( @@ -177,7 +177,7 @@ class AQIComplicationService : BaseWeatherComplicationService() { ShortTextComplicationData.Builder( PlainComplicationText.Builder(aqiShortStr).build(), PlainComplicationText.Builder( - "${getString(R.string.label_airquality_short)}: $aqiStr" + "${getString(sharedRes.string.label_airquality_short)}: $aqiStr" ).build() ).setMonochromaticImage( MonochromaticImage.Builder( @@ -190,10 +190,10 @@ class AQIComplicationService : BaseWeatherComplicationService() { } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_airquality_short)) + PlainComplicationText.Builder(getString(sharedRes.string.label_airquality_short)) .build(), PlainComplicationText.Builder( - "${getString(R.string.label_airquality_short)}: $aqiStr" + "${getString(sharedRes.string.label_airquality_short)}: $aqiStr" ).build() ).setTitle( PlainComplicationText.Builder(aqiStr).build() diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/BeaufortComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/BeaufortComplicationService.kt index 886391d5..83806f89 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/BeaufortComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/BeaufortComplicationService.kt @@ -15,6 +15,7 @@ import androidx.wear.watchface.complications.data.SmallImageComplicationData import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.controls.BeaufortViewModel import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.icons.WeatherIconsEFProvider import com.thewizrd.shared_resources.sharedDeps @@ -39,7 +40,7 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.MONOCHROMATIC_IMAGE, ComplicationType.SMALL_IMAGE ) - private val complicationIconResId = R.drawable.wi_strong_wind + private val complicationIconResId = sharedRes.drawable.wi_strong_wind override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { @@ -89,7 +90,7 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.MONOCHROMATIC_IMAGE -> { MonochromaticImageComplicationData.Builder( MonochromaticImage.Builder( - Icon.createWithResource(this, R.drawable.wi_wind_beaufort_3) + Icon.createWithResource(this, sharedRes.drawable.wi_wind_beaufort_3) .setTint(Colors.WHITESMOKE) ).build(), PlainComplicationText.Builder("Beaufort: 3, Gentle Breeze").build() @@ -101,12 +102,12 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { Icon.createWithBitmap( ImageUtils.bitmapFromDrawable( getThemeContextOverride(false), - R.drawable.wi_wind_beaufort_3 + sharedRes.drawable.wi_wind_beaufort_3 ) ), SmallImageType.ICON ).setAmbientImage( - Icon.createWithResource(this, R.drawable.wi_wind_beaufort_3) + Icon.createWithResource(this, sharedRes.drawable.wi_wind_beaufort_3) .setTint(Colors.WHITESMOKE) ).build(), PlainComplicationText.Builder("Beaufort: 3, Gentle Breeze").build() @@ -137,7 +138,7 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { val contentDescription = PlainComplicationText.Builder( beaufortModel?.let { "${beaufortModel.beaufort.label}: ${beaufortModel.progress}, ${beaufortModel.beaufort.value}" } - ?: "${getString(R.string.label_beaufort)}: ${getString(R.string.weather_notavailable)}" + ?: "${getString(sharedRes.string.label_beaufort)}: ${getString(sharedRes.string.weather_notavailable)}" ).build() val progressShortStr = beaufortModel?.progress?.toString() ?: WeatherIcons.EM_DASH @@ -180,7 +181,8 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_beaufort)).build(), + PlainComplicationText.Builder(getString(sharedRes.string.label_beaufort)) + .build(), contentDescription ).setTitle( PlainComplicationText.Builder( diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationFeelsLikeWeatherComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationFeelsLikeWeatherComplicationService.kt index 4937d55e..d779ca1f 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationFeelsLikeWeatherComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationFeelsLikeWeatherComplicationService.kt @@ -13,6 +13,7 @@ import androidx.wear.watchface.complications.data.SmallImage import androidx.wear.watchface.complications.data.SmallImageComplicationData import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.icons.WeatherIconsEFProvider @@ -25,6 +26,7 @@ import com.thewizrd.shared_resources.weatherdata.model.Forecast import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.simpleweather.R import com.thewizrd.weather_api.weatherModule +import kotlin.math.roundToInt class CurrentLocationFeelsLikeWeatherComplicationService : WeatherForecastComplicationService() { companion object { @@ -38,7 +40,7 @@ class CurrentLocationFeelsLikeWeatherComplicationService : WeatherForecastCompli ComplicationType.MONOCHROMATIC_IMAGE, ComplicationType.SMALL_IMAGE ) - private val complicationIconResId = R.drawable.wi_day_sunny + private val complicationIconResId = sharedRes.drawable.wi_day_sunny override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { @@ -122,14 +124,12 @@ class CurrentLocationFeelsLikeWeatherComplicationService : WeatherForecastCompli val feelsLike = if (weather.condition?.feelslikeF != null && weather.condition!!.feelslikeF != weather.condition!!.feelslikeC) { val temp = - if (isFahrenheit) Math.round(weather.condition!!.feelslikeF) else Math.round( - weather.condition!!.feelslikeC - ) + if (isFahrenheit) weather.condition!!.feelslikeF.roundToInt() else weather.condition!!.feelslikeC.roundToInt() String.format(LocaleUtils.getLocale(), "%d°", temp) } else { WeatherIcons.EM_DASH } - val feelsLikeLabel = getString(R.string.label_feelslike) + val feelsLikeLabel = getString(sharedRes.string.label_feelslike) val tempUnit = if (isFahrenheit) Units.FAHRENHEIT else Units.CELSIUS diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationWeatherComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationWeatherComplicationService.kt index 3c6a63be..1ba4c1e0 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationWeatherComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationWeatherComplicationService.kt @@ -13,6 +13,7 @@ import androidx.wear.watchface.complications.data.SmallImage import androidx.wear.watchface.complications.data.SmallImageComplicationData import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.icons.WeatherIconsEFProvider @@ -38,7 +39,7 @@ class CurrentLocationWeatherComplicationService : WeatherForecastComplicationSer ComplicationType.MONOCHROMATIC_IMAGE, ComplicationType.SMALL_IMAGE ) - private val complicationIconResId = R.drawable.wi_day_sunny + private val complicationIconResId = sharedRes.drawable.wi_day_sunny override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/DewPointComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/DewPointComplicationService.kt index afcbcee3..ef3eba04 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/DewPointComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/DewPointComplicationService.kt @@ -8,6 +8,7 @@ import androidx.wear.watchface.complications.data.MonochromaticImage import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.ShortTextComplicationData +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors @@ -24,7 +25,7 @@ class DewPointComplicationService : WeatherHourlyForecastComplicationService() { override val supportedComplicationTypes = setOf(ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT) - private val complicationIconResId = R.drawable.wi_thermometer + private val complicationIconResId = sharedRes.drawable.wi_thermometer override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { @@ -45,7 +46,8 @@ class DewPointComplicationService : WeatherHourlyForecastComplicationService() { } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_dewpoint)).build(), + PlainComplicationText.Builder(getString(sharedRes.string.label_dewpoint)) + .build(), PlainComplicationText.Builder("Dew Point: 38°").build() ).setTitle( PlainComplicationText.Builder("38°").build() @@ -88,7 +90,7 @@ class DewPointComplicationService : WeatherHourlyForecastComplicationService() { ShortTextComplicationData.Builder( PlainComplicationText.Builder(tempStr).build(), PlainComplicationText.Builder( - String.format("%s: %s", getString(R.string.label_dewpoint), tempStr) + String.format("%s: %s", getString(sharedRes.string.label_dewpoint), tempStr) ).build() ).setMonochromaticImage( MonochromaticImage.Builder( @@ -101,9 +103,10 @@ class DewPointComplicationService : WeatherHourlyForecastComplicationService() { } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_dewpoint)).build(), + PlainComplicationText.Builder(getString(sharedRes.string.label_dewpoint)) + .build(), PlainComplicationText.Builder( - String.format("%s: %s", getString(R.string.label_dewpoint), tempStr) + String.format("%s: %s", getString(sharedRes.string.label_dewpoint), tempStr) ).build() ).setTitle( PlainComplicationText.Builder(tempStr).build() diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/FeelsLikeComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/FeelsLikeComplicationService.kt index f1c241f1..c6ebae07 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/FeelsLikeComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/FeelsLikeComplicationService.kt @@ -8,6 +8,7 @@ import androidx.wear.watchface.complications.data.MonochromaticImage import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.ShortTextComplicationData +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors @@ -24,7 +25,7 @@ class FeelsLikeComplicationService : WeatherHourlyForecastComplicationService() override val supportedComplicationTypes = setOf(ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT) - private val complicationIconResId = R.drawable.wi_thermometer + private val complicationIconResId = sharedRes.drawable.wi_thermometer override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { @@ -45,7 +46,8 @@ class FeelsLikeComplicationService : WeatherHourlyForecastComplicationService() } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_feelslike)).build(), + PlainComplicationText.Builder(getString(sharedRes.string.label_feelslike)) + .build(), PlainComplicationText.Builder("Feels like: 75°").build() ).setTitle( PlainComplicationText.Builder("75°").build() @@ -88,7 +90,11 @@ class FeelsLikeComplicationService : WeatherHourlyForecastComplicationService() ShortTextComplicationData.Builder( PlainComplicationText.Builder(tempStr).build(), PlainComplicationText.Builder( - String.format("%s: %s", getString(R.string.label_feelslike), tempStr) + String.format( + "%s: %s", + getString(sharedRes.string.label_feelslike), + tempStr + ) ).build() ).setMonochromaticImage( MonochromaticImage.Builder( @@ -101,9 +107,14 @@ class FeelsLikeComplicationService : WeatherHourlyForecastComplicationService() } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_feelslike)).build(), + PlainComplicationText.Builder(getString(sharedRes.string.label_feelslike)) + .build(), PlainComplicationText.Builder( - String.format("%s: %s", getString(R.string.label_feelslike), tempStr) + String.format( + "%s: %s", + getString(sharedRes.string.label_feelslike), + tempStr + ) ).build() ).setTitle( PlainComplicationText.Builder(tempStr).build() diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/HumidityComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/HumidityComplicationService.kt index 31a1db92..9c8f1198 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/HumidityComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/HumidityComplicationService.kt @@ -9,6 +9,7 @@ import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.RangedValueComplicationData import androidx.wear.watchface.complications.data.ShortTextComplicationData +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast @@ -26,7 +27,7 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT ) - private val complicationIconResId = R.drawable.wi_humidity + private val complicationIconResId = sharedRes.drawable.wi_humidity override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { @@ -37,7 +38,7 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( 75f, 0f, 100f, - PlainComplicationText.Builder("${getString(R.string.label_humidity)}: 75%") + PlainComplicationText.Builder("${getString(sharedRes.string.label_humidity)}: 75%") .build() ).setMonochromaticImage( MonochromaticImage.Builder( @@ -53,7 +54,7 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.SHORT_TEXT -> { ShortTextComplicationData.Builder( PlainComplicationText.Builder("75%").build(), - PlainComplicationText.Builder("${getString(R.string.label_humidity)}: 75%") + PlainComplicationText.Builder("${getString(sharedRes.string.label_humidity)}: 75%") .build() ).setMonochromaticImage( MonochromaticImage.Builder( @@ -64,8 +65,9 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_humidity)).build(), - PlainComplicationText.Builder("${getString(R.string.label_humidity)}: 75%") + PlainComplicationText.Builder(getString(sharedRes.string.label_humidity)) + .build(), + PlainComplicationText.Builder("${getString(sharedRes.string.label_humidity)}: 75%") .build() ).setTitle( PlainComplicationText.Builder("75%").build() @@ -99,7 +101,7 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { RangedValueComplicationData.Builder( humidityPct?.toFloat() ?: 0f, 0f, 100f, PlainComplicationText.Builder( - "${getString(R.string.label_humidity)}: $humidityStr" + "${getString(sharedRes.string.label_humidity)}: $humidityStr" ).build() ).setMonochromaticImage( MonochromaticImage.Builder( @@ -118,7 +120,7 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { ShortTextComplicationData.Builder( PlainComplicationText.Builder(humidityStr).build(), PlainComplicationText.Builder( - "${getString(R.string.label_humidity)}: $humidityStr" + "${getString(sharedRes.string.label_humidity)}: $humidityStr" ).build() ).setMonochromaticImage( MonochromaticImage.Builder( @@ -131,9 +133,10 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_humidity)).build(), + PlainComplicationText.Builder(getString(sharedRes.string.label_humidity)) + .build(), PlainComplicationText.Builder( - "${getString(R.string.label_humidity)}: $humidityStr" + "${getString(sharedRes.string.label_humidity)}: $humidityStr" ).build() ).setTitle( PlainComplicationText.Builder(humidityStr).build() diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PrecipitationComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PrecipitationComplicationService.kt index 82312746..6a0259c3 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PrecipitationComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PrecipitationComplicationService.kt @@ -9,6 +9,7 @@ import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.RangedValueComplicationData import androidx.wear.watchface.complications.data.ShortTextComplicationData +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast @@ -26,7 +27,7 @@ class PrecipitationComplicationService : WeatherHourlyForecastComplicationServic ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT ) - private val complicationIconResId = R.drawable.wi_umbrella + private val complicationIconResId = sharedRes.drawable.wi_umbrella override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { @@ -95,7 +96,7 @@ class PrecipitationComplicationService : WeatherHourlyForecastComplicationServic ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( popChance?.toFloat() ?: 0f, 0f, 100f, - PlainComplicationText.Builder(getString(R.string.label_chance)).build() + PlainComplicationText.Builder(getString(sharedRes.string.label_chance)).build() ).setMonochromaticImage( MonochromaticImage.Builder( Icon.createWithResource(this, complicationIconResId) @@ -113,7 +114,7 @@ class PrecipitationComplicationService : WeatherHourlyForecastComplicationServic ShortTextComplicationData.Builder( PlainComplicationText.Builder(popChanceStr).build(), PlainComplicationText.Builder( - "${getString(R.string.label_chance)}: $popChanceStr" + "${getString(sharedRes.string.label_chance)}: $popChanceStr" ).build() ).setMonochromaticImage( MonochromaticImage.Builder( @@ -126,9 +127,9 @@ class PrecipitationComplicationService : WeatherHourlyForecastComplicationServic } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_chance)).build(), + PlainComplicationText.Builder(getString(sharedRes.string.label_chance)).build(), PlainComplicationText.Builder( - "${getString(R.string.label_chance)}: $popChanceStr" + "${getString(sharedRes.string.label_chance)}: $popChanceStr" ).build() ).setTitle( PlainComplicationText.Builder(popChanceStr).build() diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PressureComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PressureComplicationService.kt index a9fd2d52..8191b65a 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PressureComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PressureComplicationService.kt @@ -9,6 +9,7 @@ import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.RangedValueComplicationData import androidx.wear.watchface.complications.data.ShortTextComplicationData +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors @@ -31,7 +32,7 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT ) - private val complicationIconResId = R.drawable.wi_barometer + private val complicationIconResId = sharedRes.drawable.wi_barometer override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { @@ -67,7 +68,8 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_pressure)).build(), + PlainComplicationText.Builder(getString(sharedRes.string.label_pressure)) + .build(), PlainComplicationText.Builder("Pressure: 30.3 inHg").build() ).setTitle( PlainComplicationText.Builder("30.3 inHg").build() @@ -114,25 +116,25 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { when (unit) { Units.INHG -> { pressureVal = df.format(pressureIn) - pressureUnit = getString(R.string.unit_inHg) - pressureUnitShort = getString(R.string.unit_in) + pressureUnit = getString(sharedRes.string.unit_inHg) + pressureUnitShort = getString(sharedRes.string.unit_in) } Units.MILLIBAR -> { pressureVal = df.format(pressureMb) - pressureUnit = getString(R.string.unit_mBar).also { pressureUnitShort = it } + pressureUnit = getString(sharedRes.string.unit_mBar).also { pressureUnitShort = it } } Units.MMHG -> { pressureVal = df.format(ConversionMethods.inHgToMmHg(pressureIn)) - pressureUnit = getString(R.string.unit_mmHg) - pressureUnitShort = getString(R.string.unit_mm) + pressureUnit = getString(sharedRes.string.unit_mmHg) + pressureUnitShort = getString(sharedRes.string.unit_mm) } else -> { pressureVal = df.format(pressureIn) - pressureUnit = getString(R.string.unit_inHg) - pressureUnitShort = getString(R.string.unit_in) + pressureUnit = getString(sharedRes.string.unit_inHg) + pressureUnitShort = getString(sharedRes.string.unit_in) } } @@ -154,8 +156,8 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { PlainComplicationText.Builder( String.format( "%s: %s", - getString(R.string.label_pressure), - pressureStr ?: getString(R.string.weather_notavailable) + getString(sharedRes.string.label_pressure), + pressureStr ?: getString(sharedRes.string.weather_notavailable) ) ).build() ).setMonochromaticImage( @@ -178,8 +180,8 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { PlainComplicationText.Builder( String.format( "%s: %s", - getString(R.string.label_pressure), - pressureStr ?: getString(R.string.weather_notavailable) + getString(sharedRes.string.label_pressure), + pressureStr ?: getString(sharedRes.string.weather_notavailable) ) ).build() ).setMonochromaticImage( @@ -194,12 +196,13 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_pressure)).build(), + PlainComplicationText.Builder(getString(sharedRes.string.label_pressure)) + .build(), PlainComplicationText.Builder( String.format( "%s: %s", - getString(R.string.label_pressure), - pressureStr ?: getString(R.string.weather_notavailable) + getString(sharedRes.string.label_pressure), + pressureStr ?: getString(sharedRes.string.weather_notavailable) ) ).build() ).setTitle( diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/SunriseSunsetComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/SunriseSunsetComplicationService.kt index 3ccd6948..660e9903 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/SunriseSunsetComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/SunriseSunsetComplicationService.kt @@ -9,6 +9,7 @@ import androidx.wear.watchface.complications.data.MonochromaticImage import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.ShortTextComplicationData +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors @@ -39,7 +40,7 @@ class SunriseSunsetComplicationService : WeatherHourlyForecastComplicationServic PlainComplicationText.Builder("Sunset: 6:05 PM").build() ).setMonochromaticImage( MonochromaticImage.Builder( - Icon.createWithResource(this, R.drawable.wi_sunset) + Icon.createWithResource(this, sharedRes.drawable.wi_sunset) .setTint(Colors.WHITESMOKE) ).build() ).build() @@ -53,7 +54,7 @@ class SunriseSunsetComplicationService : WeatherHourlyForecastComplicationServic PlainComplicationText.Builder("6:05 PM").build() ).setMonochromaticImage( MonochromaticImage.Builder( - Icon.createWithResource(this, R.drawable.wi_sunset) + Icon.createWithResource(this, sharedRes.drawable.wi_sunset) .setTint(Colors.WHITESMOKE) ).build() ).build() @@ -97,21 +98,21 @@ class SunriseSunsetComplicationService : WeatherHourlyForecastComplicationServic if (sunset != null && sunrise != null) { if (now.toLocalTime() > sunrise.toLocalTime()) { text = sunset.format(fmt) - complicationIconResId = R.drawable.wi_sunset - desc = getString(R.string.label_sunset) + complicationIconResId = sharedRes.drawable.wi_sunset + desc = getString(sharedRes.string.label_sunset) } else { text = sunrise.format(fmt) - complicationIconResId = R.drawable.wi_sunrise - desc = getString(R.string.label_sunrise) + complicationIconResId = sharedRes.drawable.wi_sunrise + desc = getString(sharedRes.string.label_sunrise) } } else if (sunset != null) { text = sunset.format(fmt) - complicationIconResId = R.drawable.wi_sunset - desc = getString(R.string.label_sunset) + complicationIconResId = sharedRes.drawable.wi_sunset + desc = getString(sharedRes.string.label_sunset) } else { text = sunrise?.format(fmt) ?: WeatherIcons.EM_DASH - complicationIconResId = R.drawable.wi_sunrise - desc = getString(R.string.label_sunrise) + complicationIconResId = sharedRes.drawable.wi_sunrise + desc = getString(sharedRes.string.label_sunrise) } return when (dataType) { diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/UVComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/UVComplicationService.kt index 8286fdbd..0f829a5c 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/UVComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/UVComplicationService.kt @@ -10,6 +10,7 @@ import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.RangedValueComplicationData import androidx.wear.watchface.complications.data.ShortTextComplicationData import com.thewizrd.common.controls.UVIndexViewModel +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast @@ -29,7 +30,7 @@ class UVComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT ) - private val complicationIconResId = R.drawable.wi_day_sunny + private val complicationIconResId = sharedRes.drawable.wi_day_sunny override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { @@ -67,7 +68,7 @@ class UVComplicationService : WeatherHourlyForecastComplicationService() { } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_uv)).build(), + PlainComplicationText.Builder(getString(sharedRes.string.label_uv)).build(), PlainComplicationText.Builder("UV Index: 3, Moderate").build() ).setTitle( PlainComplicationText.Builder("3, Moderate").build() @@ -100,7 +101,7 @@ class UVComplicationService : WeatherHourlyForecastComplicationService() { val uvIdxStr = uvModel?.index?.toString() ?: WeatherIcons.EM_DASH val uvProgress = uvModel?.progress?.toFloat() ?: 0f val uvProgressMax = uvModel?.let { max(it.progressMax, it.progress).toFloat() } ?: 11f - val contentDescription = "${getString(R.string.label_uv)}: $uvStr" + val contentDescription = "${getString(sharedRes.string.label_uv)}: $uvStr" return when (dataType) { ComplicationType.RANGED_VALUE -> { @@ -141,7 +142,7 @@ class UVComplicationService : WeatherHourlyForecastComplicationService() { } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_uv)).build(), + PlainComplicationText.Builder(getString(sharedRes.string.label_uv)).build(), PlainComplicationText.Builder( contentDescription ).build() diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherComplicationService.kt index d8d61521..0d5cd26c 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherComplicationService.kt @@ -13,6 +13,7 @@ import androidx.wear.watchface.complications.data.SmallImage import androidx.wear.watchface.complications.data.SmallImageComplicationData import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.icons.WeatherIconsEFProvider @@ -38,7 +39,7 @@ class WeatherComplicationService : WeatherForecastComplicationService() { ComplicationType.MONOCHROMATIC_IMAGE, ComplicationType.SMALL_IMAGE ) - private val complicationIconResId = R.drawable.wi_day_sunny + private val complicationIconResId = sharedRes.drawable.wi_day_sunny override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { @@ -126,7 +127,7 @@ class WeatherComplicationService : WeatherForecastComplicationService() { weather.condition!!.weather } else { provider.getWeatherCondition(weather.condition!!.icon) - } ?: getString(R.string.weather_notavailable) + } ?: getString(sharedRes.string.weather_notavailable) val wim = sharedDeps.weatherIconsManager val weatherIcon = wim.getWeatherIconResource(weather.condition!!.icon) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherHiLoComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherHiLoComplicationService.kt index e11d400b..faf9d86d 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherHiLoComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherHiLoComplicationService.kt @@ -13,6 +13,7 @@ import androidx.wear.watchface.complications.data.SmallImage import androidx.wear.watchface.complications.data.SmallImageComplicationData import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.icons.WeatherIconsEFProvider @@ -38,7 +39,7 @@ class WeatherHiLoComplicationService : WeatherForecastComplicationService() { ComplicationType.MONOCHROMATIC_IMAGE, ComplicationType.SMALL_IMAGE ) - private val complicationIconResId = R.drawable.wi_day_sunny + private val complicationIconResId = sharedRes.drawable.wi_day_sunny override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { @@ -152,7 +153,11 @@ class WeatherHiLoComplicationService : WeatherForecastComplicationService() { ) val contentDescription = PlainComplicationText.Builder( - "$temp - $condition; ${getString(R.string.label_high)}: $hiTemp, ${getString(R.string.label_low)}: $loTemp" + "$temp - $condition; ${getString(sharedRes.string.label_high)}: $hiTemp, ${ + getString( + sharedRes.string.label_low + ) + }: $loTemp" ).build() when (dataType) { diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WindComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WindComplicationService.kt index 584ca5a0..cc49e248 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WindComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WindComplicationService.kt @@ -13,6 +13,7 @@ import androidx.wear.watchface.complications.data.SmallImage import androidx.wear.watchface.complications.data.SmallImageComplicationData import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors @@ -38,7 +39,7 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.MONOCHROMATIC_IMAGE, ComplicationType.SMALL_IMAGE ) - private val complicationIconResId = R.drawable.wi_strong_wind + private val complicationIconResId = sharedRes.drawable.wi_strong_wind override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { @@ -56,7 +57,7 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ImageUtils.rotateBitmap( ImageUtils.bitmapFromDrawable( getThemeContextOverride(false), - R.drawable.wi_wind_direction_white + sharedRes.drawable.wi_wind_direction_white ), 330.0f // 150° + 180 ) ) @@ -84,7 +85,7 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ImageUtils.rotateBitmap( ImageUtils.bitmapFromDrawable( getThemeContextOverride(false), - R.drawable.wi_wind_direction_white + sharedRes.drawable.wi_wind_direction_white ), 330.0f // 150° + 180 ) ) @@ -100,7 +101,7 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ImageUtils.rotateBitmap( ImageUtils.bitmapFromDrawable( getThemeContextOverride(false), - R.drawable.wi_wind_direction_white + sharedRes.drawable.wi_wind_direction_white ), 330.0f // 150° + 180 ) ), @@ -110,7 +111,7 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ImageUtils.rotateBitmap( ImageUtils.bitmapFromDrawable( getThemeContextOverride(false), - R.drawable.wi_wind_direction_white + sharedRes.drawable.wi_wind_direction_white ), 330.0f // 150° + 180 ) ) @@ -150,26 +151,26 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { when (unit) { Units.MILES_PER_HOUR -> { speedVal = windMph.roundToInt() - speedUnit = getString(R.string.unit_mph).also { speedUnitShort = it } + speedUnit = getString(sharedRes.string.unit_mph).also { speedUnitShort = it } } Units.KILOMETERS_PER_HOUR -> { speedVal = windKph.roundToInt() - speedUnit = getString(R.string.unit_kph).also { speedUnitShort = it } + speedUnit = getString(sharedRes.string.unit_kph).also { speedUnitShort = it } } Units.METERS_PER_SECOND -> { speedVal = ConversionMethods.kphToMsec(windKph).roundToInt() - speedUnit = getString(R.string.unit_msec).also { speedUnitShort = it } + speedUnit = getString(sharedRes.string.unit_msec).also { speedUnitShort = it } } Units.KNOTS -> { speedVal = ConversionMethods.mphToKts(windMph).roundToInt() - speedUnit = getString(R.string.unit_knots) + speedUnit = getString(sharedRes.string.unit_knots) speedUnitShort = "kn" } else -> { speedVal = windMph.roundToInt() - speedUnit = getString(R.string.unit_mph).also { speedUnitShort = it } + speedUnit = getString(sharedRes.string.unit_mph).also { speedUnitShort = it } } } @@ -197,7 +198,7 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { .build(), PlainComplicationText.Builder( windSpeedLong - ?: "${getString(R.string.label_wind)}: ${getString(R.string.weather_notavailable)}" + ?: "${getString(sharedRes.string.label_wind)}: ${getString(sharedRes.string.weather_notavailable)}" ).build() ).setMonochromaticImage( MonochromaticImage.Builder( @@ -205,7 +206,7 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ImageUtils.rotateBitmap( ImageUtils.bitmapFromDrawable( getThemeContextOverride(false), - R.drawable.wi_wind_direction_white + sharedRes.drawable.wi_wind_direction_white ), windDirection.toFloat() + 180 ) ) @@ -216,10 +217,10 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( - PlainComplicationText.Builder(getString(R.string.label_wind)).build(), + PlainComplicationText.Builder(getString(sharedRes.string.label_wind)).build(), PlainComplicationText.Builder( windSpeedLong - ?: "${getString(R.string.label_wind)}: ${getString(R.string.weather_notavailable)}" + ?: "${getString(sharedRes.string.label_wind)}: ${getString(sharedRes.string.weather_notavailable)}" ).build() ).setTitle( PlainComplicationText.Builder(windSpeedLong ?: WeatherIcons.EM_DASH).build() @@ -240,13 +241,13 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ImageUtils.rotateBitmap( ImageUtils.bitmapFromDrawable( getThemeContextOverride(false), - R.drawable.wi_wind_direction_white + sharedRes.drawable.wi_wind_direction_white ), windDirection.toFloat() + 180 ) ) .setTint(Colors.WHITESMOKE) ).build(), - PlainComplicationText.Builder("${getString(R.string.label_wind)}: $windSpeedLong") + PlainComplicationText.Builder("${getString(sharedRes.string.label_wind)}: $windSpeedLong") .build() ).build() } @@ -258,7 +259,7 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ImageUtils.rotateBitmap( ImageUtils.bitmapFromDrawable( getThemeContextOverride(false), - R.drawable.wi_wind_direction_white + sharedRes.drawable.wi_wind_direction_white ), windDirection.toFloat() + 180 ) ), @@ -268,16 +269,16 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ImageUtils.rotateBitmap( ImageUtils.bitmapFromDrawable( getThemeContextOverride(false), - R.drawable.wi_wind_direction_white + sharedRes.drawable.wi_wind_direction_white ), windDirection.toFloat() + 180 ) ) .setTint(Colors.WHITESMOKE) ).build(), PlainComplicationText.Builder( - "${getString(R.string.label_wind)}: ${ + "${getString(sharedRes.string.label_wind)}: ${ windSpeedLong ?: getString( - R.string.weather_notavailable + sharedRes.string.weather_notavailable ) }" ) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/ForecastWeatherTileProviderService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/ForecastWeatherTileProviderService.kt index 26803157..420f11f6 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/ForecastWeatherTileProviderService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/ForecastWeatherTileProviderService.kt @@ -5,6 +5,7 @@ import androidx.wear.protolayout.LayoutElementBuilders import androidx.wear.protolayout.ResourceBuilders import androidx.wear.tiles.RequestBuilders import com.google.android.horologist.tiles.images.drawableResToImageResource +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.weatherdata.model.Weather @@ -46,21 +47,21 @@ class ForecastWeatherTileProviderService : WeatherCoroutinesTileService() { ID_WEATHER_CHANCE_ICON -> { addIdToImageMapping( ID_WEATHER_CHANCE_ICON, - drawableResToImageResource(R.drawable.wi_umbrella) + drawableResToImageResource(sharedRes.drawable.wi_umbrella) ) } ID_WEATHER_CLOUDINESS_ICON -> { addIdToImageMapping( ID_WEATHER_CLOUDINESS_ICON, - drawableResToImageResource(R.drawable.wi_cloudy) + drawableResToImageResource(sharedRes.drawable.wi_cloudy) ) } ID_WEATHER_WINDSPEED_ICON -> { addIdToImageMapping( ID_WEATHER_WINDSPEED_ICON, - drawableResToImageResource(R.drawable.wi_strong_wind) + drawableResToImageResource(sharedRes.drawable.wi_strong_wind) ) } } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/HourlyForecastWeatherTileProviderService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/HourlyForecastWeatherTileProviderService.kt index 40b03bac..c7d0d577 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/HourlyForecastWeatherTileProviderService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/HourlyForecastWeatherTileProviderService.kt @@ -5,6 +5,7 @@ import androidx.wear.protolayout.LayoutElementBuilders import androidx.wear.protolayout.ResourceBuilders import androidx.wear.tiles.RequestBuilders import com.google.android.horologist.tiles.images.drawableResToImageResource +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.weatherdata.model.Weather @@ -49,21 +50,21 @@ class HourlyForecastWeatherTileProviderService : WeatherCoroutinesTileService() ID_WEATHER_CHANCE_ICON -> { addIdToImageMapping( ID_WEATHER_CHANCE_ICON, - drawableResToImageResource(R.drawable.wi_umbrella) + drawableResToImageResource(sharedRes.drawable.wi_umbrella) ) } ID_WEATHER_CLOUDINESS_ICON -> { addIdToImageMapping( ID_WEATHER_CLOUDINESS_ICON, - drawableResToImageResource(R.drawable.wi_cloudy) + drawableResToImageResource(sharedRes.drawable.wi_cloudy) ) } ID_WEATHER_WINDSPEED_ICON -> { addIdToImageMapping( ID_WEATHER_WINDSPEED_ICON, - drawableResToImageResource(R.drawable.wi_strong_wind) + drawableResToImageResource(sharedRes.drawable.wi_strong_wind) ) } } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/CurrentWeatherGoogleTileLayout.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/CurrentWeatherGoogleTileLayout.kt index dc861401..8a28ccf3 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/CurrentWeatherGoogleTileLayout.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/CurrentWeatherGoogleTileLayout.kt @@ -32,6 +32,7 @@ import com.google.android.horologist.tiles.images.drawableResToImageResource import com.google.android.horologist.tiles.images.toImageResource import com.thewizrd.common.controls.toUiModel import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.getColorFromTempF @@ -217,7 +218,7 @@ private fun currentWeatherGoogleTilePreview(context: Context) = TilePreviewData( "$ID_WEATHER_ICON_PREFIX${WeatherIcons.DAY_SUNNY}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_day_sunny, + sharedRes.drawable.wi_day_sunny, Colors.WHITE ).toImageResource() ) @@ -225,7 +226,7 @@ private fun currentWeatherGoogleTilePreview(context: Context) = TilePreviewData( "$ID_WEATHER_ICON_PREFIX${WeatherIcons.NA}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_na, + sharedRes.drawable.wi_na, Colors.WHITE ).toImageResource() ) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/CurrentWeatherTileLayout.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/CurrentWeatherTileLayout.kt index 9f2971f4..51e249dc 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/CurrentWeatherTileLayout.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/CurrentWeatherTileLayout.kt @@ -28,6 +28,7 @@ import androidx.wear.tiles.tooling.preview.TilePreviewHelper import com.google.android.horologist.tiles.images.toImageResource import com.thewizrd.common.controls.toUiModel import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.getColorFromTempF @@ -170,7 +171,7 @@ private fun currentWeatherTilePreview(context: Context) = TilePreviewData( "$ID_WEATHER_ICON_PREFIX${WeatherIcons.DAY_SUNNY}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_day_sunny, + sharedRes.drawable.wi_day_sunny, Colors.WHITE ).toImageResource() ) @@ -178,7 +179,7 @@ private fun currentWeatherTilePreview(context: Context) = TilePreviewData( "$ID_WEATHER_ICON_PREFIX${WeatherIcons.NA}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_na, + sharedRes.drawable.wi_na, Colors.WHITE ).toImageResource() ) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/DetailsWeatherTileLayout.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/DetailsWeatherTileLayout.kt index 623da33d..b7a8dcea 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/DetailsWeatherTileLayout.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/DetailsWeatherTileLayout.kt @@ -62,6 +62,7 @@ import com.thewizrd.common.controls.WeatherDetailsType import com.thewizrd.common.controls.toUiModel import com.thewizrd.common.utils.ImageUtils import com.thewizrd.common.utils.ImageUtils.rotate +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.designer.initializeDependencies import com.thewizrd.shared_resources.designer.isInEditMode @@ -152,7 +153,7 @@ internal fun detailsWeatherTileLayout( when (detailItems.size) { 0 -> { text( - text = context.getString(R.string.label_nodata).layoutString, + text = context.getString(sharedRes.string.label_nodata).layoutString, typography = androidx.wear.protolayout.material3.Typography.LABEL_LARGE ) } @@ -192,14 +193,14 @@ internal fun detailsWeatherTileLayout( textEdgeButton( onClick = clickable(getLaunchAction(context)), labelContent = { - text(context.getString(R.string.label_nav_weathernow).layoutString) + text(context.getString(sharedRes.string.label_nav_weathernow).layoutString) } ) } else { compactButton( onClick = clickable(getLaunchAction(context)), labelContent = { - text(context.getString(R.string.label_nav_weathernow).layoutString) + text(context.getString(sharedRes.string.label_nav_weathernow).layoutString) } ) } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/ForecastWeatherTileLayout.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/ForecastWeatherTileLayout.kt index 635a9c7c..54c43ade 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/ForecastWeatherTileLayout.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/ForecastWeatherTileLayout.kt @@ -30,6 +30,7 @@ import com.google.android.horologist.tiles.images.drawableResToImageResource import com.google.android.horologist.tiles.images.toImageResource import com.thewizrd.common.controls.toUiModel import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.preferences.SettingsManager @@ -275,7 +276,7 @@ private fun forecastWeatherTilePreview(context: Context): TilePreviewData { "$ID_WEATHER_ICON_PREFIX${WeatherIcons.DAY_SUNNY}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_day_sunny, + sharedRes.drawable.wi_day_sunny, Colors.WHITE ).toImageResource() ) @@ -283,21 +284,21 @@ private fun forecastWeatherTilePreview(context: Context): TilePreviewData { "$ID_WEATHER_ICON_PREFIX${WeatherIcons.NA}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_na, + sharedRes.drawable.wi_na, Colors.WHITE ).toImageResource() ) .addIdToImageMapping( ID_WEATHER_CHANCE_ICON, - drawableResToImageResource(R.drawable.wi_umbrella_white) + drawableResToImageResource(sharedRes.drawable.wi_umbrella_white) ) .addIdToImageMapping( ID_WEATHER_CLOUDINESS_ICON, - drawableResToImageResource(R.drawable.wi_cloudy) + drawableResToImageResource(sharedRes.drawable.wi_cloudy) ) .addIdToImageMapping( ID_WEATHER_WINDSPEED_ICON, - drawableResToImageResource(R.drawable.wi_strong_wind) + drawableResToImageResource(sharedRes.drawable.wi_strong_wind) ) .apply { forecasts.forEach { item -> @@ -305,7 +306,7 @@ private fun forecastWeatherTilePreview(context: Context): TilePreviewData { "${ID_WEATHER_ICON_PREFIX}${item.icon}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_cloudy, + sharedRes.drawable.wi_cloudy, Colors.WHITE ).toImageResource() ) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/HourlyForecastCardTileLayout.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/HourlyForecastCardTileLayout.kt index d25c52a6..7f6ad6bf 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/HourlyForecastCardTileLayout.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/HourlyForecastCardTileLayout.kt @@ -39,6 +39,7 @@ import androidx.wear.tiles.tooling.preview.TilePreviewHelper import com.google.android.horologist.tiles.images.toImageResource import com.thewizrd.common.controls.toUiModel import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ConversionMethods @@ -106,7 +107,7 @@ internal fun hourlyForecastCardTileLayout( mainSlot = { if (forecasts.isNullOrEmpty()) { text( - text = context.getString(R.string.label_nodata).layoutString, + text = context.getString(sharedRes.string.label_nodata).layoutString, alignment = TEXT_ALIGN_CENTER ) } else { @@ -306,7 +307,7 @@ private fun hourlyForecastCardTileLayout(context: Context): TilePreviewData { "$ID_WEATHER_ICON_PREFIX${WeatherIcons.DAY_SUNNY}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_day_sunny, + sharedRes.drawable.wi_day_sunny, Colors.WHITE ).toImageResource() ) @@ -314,7 +315,7 @@ private fun hourlyForecastCardTileLayout(context: Context): TilePreviewData { "$ID_WEATHER_ICON_PREFIX${WeatherIcons.NA}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_na, + sharedRes.drawable.wi_na, Colors.WHITE ).toImageResource() ) @@ -324,7 +325,7 @@ private fun hourlyForecastCardTileLayout(context: Context): TilePreviewData { "${ID_WEATHER_ICON_PREFIX}${item.icon}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_cloudy, + sharedRes.drawable.wi_cloudy, Colors.WHITE ).toImageResource() ) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/HourlyForecastPillsTileLayout.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/HourlyForecastPillsTileLayout.kt index 4f6198f9..67c66ca0 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/HourlyForecastPillsTileLayout.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/HourlyForecastPillsTileLayout.kt @@ -31,6 +31,7 @@ import androidx.wear.tiles.tooling.preview.TilePreviewHelper import com.google.android.horologist.tiles.images.toImageResource import com.thewizrd.common.controls.toUiModel import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ConversionMethods @@ -92,7 +93,7 @@ internal fun hourlyForecastPillsTileLayout( mainSlot = { if (forecasts.isNullOrEmpty()) { text( - text = context.getString(R.string.label_nodata).layoutString, + text = context.getString(sharedRes.string.label_nodata).layoutString, alignment = TEXT_ALIGN_CENTER ) } else { @@ -195,7 +196,7 @@ private fun hourlyForecastPillsTileLayout(context: Context): TilePreviewData { "$ID_WEATHER_ICON_PREFIX${WeatherIcons.DAY_SUNNY}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_day_sunny, + sharedRes.drawable.wi_day_sunny, Colors.WHITE ).toImageResource() ) @@ -203,7 +204,7 @@ private fun hourlyForecastPillsTileLayout(context: Context): TilePreviewData { "$ID_WEATHER_ICON_PREFIX${WeatherIcons.NA}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_na, + sharedRes.drawable.wi_na, Colors.WHITE ).toImageResource() ) @@ -213,7 +214,7 @@ private fun hourlyForecastPillsTileLayout(context: Context): TilePreviewData { "${ID_WEATHER_ICON_PREFIX}${item.icon}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_cloudy, + sharedRes.drawable.wi_cloudy, Colors.WHITE ).toImageResource() ) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/HourlyForecastWeatherTileLayout.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/HourlyForecastWeatherTileLayout.kt index 2d632375..6a6f27d3 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/HourlyForecastWeatherTileLayout.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/HourlyForecastWeatherTileLayout.kt @@ -28,6 +28,7 @@ import com.google.android.horologist.tiles.images.drawableResToImageResource import com.google.android.horologist.tiles.images.toImageResource import com.thewizrd.common.controls.toUiModel import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.preferences.SettingsManager @@ -198,7 +199,7 @@ private fun hourlyForecastWeatherTilePreview(context: Context): TilePreviewData "$ID_WEATHER_ICON_PREFIX${WeatherIcons.DAY_SUNNY}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_day_sunny, + sharedRes.drawable.wi_day_sunny, Colors.WHITE ).toImageResource() ) @@ -206,21 +207,21 @@ private fun hourlyForecastWeatherTilePreview(context: Context): TilePreviewData "$ID_WEATHER_ICON_PREFIX${WeatherIcons.NA}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_na, + sharedRes.drawable.wi_na, Colors.WHITE ).toImageResource() ) .addIdToImageMapping( ID_WEATHER_CHANCE_ICON, - drawableResToImageResource(R.drawable.wi_umbrella_white) + drawableResToImageResource(sharedRes.drawable.wi_umbrella_white) ) .addIdToImageMapping( ID_WEATHER_CLOUDINESS_ICON, - drawableResToImageResource(R.drawable.wi_cloudy) + drawableResToImageResource(sharedRes.drawable.wi_cloudy) ) .addIdToImageMapping( ID_WEATHER_WINDSPEED_ICON, - drawableResToImageResource(R.drawable.wi_strong_wind) + drawableResToImageResource(sharedRes.drawable.wi_strong_wind) ) .apply { forecasts.forEach { item -> @@ -228,7 +229,7 @@ private fun hourlyForecastWeatherTilePreview(context: Context): TilePreviewData "${ID_WEATHER_ICON_PREFIX}${item.icon}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_cloudy, + sharedRes.drawable.wi_cloudy, Colors.WHITE ).toImageResource() ) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/M3ForecastWeatherTileLayout.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/M3ForecastWeatherTileLayout.kt index ccfea18e..15c4e1b9 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/M3ForecastWeatherTileLayout.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/M3ForecastWeatherTileLayout.kt @@ -39,6 +39,7 @@ import androidx.wear.tiles.tooling.preview.TilePreviewHelper import com.google.android.horologist.tiles.images.toImageResource import com.thewizrd.common.controls.toUiModel import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ConversionMethods @@ -169,7 +170,7 @@ private fun m3ForecastWeatherTileLayout( if (forecasts.isNullOrEmpty()) { addContent( text( - text = context.getString(R.string.label_nodata).layoutString, + text = context.getString(sharedRes.string.label_nodata).layoutString, alignment = TEXT_ALIGN_CENTER ) ) @@ -398,7 +399,7 @@ private fun forecastWeatherTilePreview(context: Context): TilePreviewData { "$ID_WEATHER_ICON_PREFIX${WeatherIcons.DAY_SUNNY}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_day_sunny, + sharedRes.drawable.wi_day_sunny, Colors.WHITE ).toImageResource() ) @@ -406,7 +407,7 @@ private fun forecastWeatherTilePreview(context: Context): TilePreviewData { "$ID_WEATHER_ICON_PREFIX${WeatherIcons.NA}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_na, + sharedRes.drawable.wi_na, Colors.WHITE ).toImageResource() ) @@ -416,7 +417,7 @@ private fun forecastWeatherTilePreview(context: Context): TilePreviewData { "${ID_WEATHER_ICON_PREFIX}${item.icon}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_cloudy, + sharedRes.drawable.wi_cloudy, Colors.WHITE ).toImageResource() ) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/M3HourlyForecastWeatherTileLayout.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/M3HourlyForecastWeatherTileLayout.kt index f378b427..44d9a01e 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/M3HourlyForecastWeatherTileLayout.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/M3HourlyForecastWeatherTileLayout.kt @@ -39,6 +39,7 @@ import androidx.wear.tiles.tooling.preview.TilePreviewHelper import com.google.android.horologist.tiles.images.toImageResource import com.thewizrd.common.controls.toUiModel import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ConversionMethods @@ -169,7 +170,7 @@ private fun m3HourlyForecastWeatherTileLayout( if (forecasts.isNullOrEmpty()) { addContent( text( - text = context.getString(R.string.label_nodata).layoutString, + text = context.getString(sharedRes.string.label_nodata).layoutString, alignment = TEXT_ALIGN_CENTER ) ) @@ -390,7 +391,7 @@ private fun hourlyForecastWeatherTilePreview(context: Context): TilePreviewData "$ID_WEATHER_ICON_PREFIX${WeatherIcons.DAY_SUNNY}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_day_sunny, + sharedRes.drawable.wi_day_sunny, Colors.WHITE ).toImageResource() ) @@ -398,7 +399,7 @@ private fun hourlyForecastWeatherTilePreview(context: Context): TilePreviewData "$ID_WEATHER_ICON_PREFIX${WeatherIcons.NA}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_na, + sharedRes.drawable.wi_na, Colors.WHITE ).toImageResource() ) @@ -408,7 +409,7 @@ private fun hourlyForecastWeatherTilePreview(context: Context): TilePreviewData "${ID_WEATHER_ICON_PREFIX}${item.icon}", ImageUtils.tintedBitmapFromDrawable( context, - R.drawable.wi_cloudy, + sharedRes.drawable.wi_cloudy, Colors.WHITE ).toImageResource() ) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/eccc/ECCCWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/eccc/ECCCWeatherProvider.kt index e20b55e7..1963dd28 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/eccc/ECCCWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/eccc/ECCCWeatherProvider.kt @@ -16,7 +16,7 @@ import com.thewizrd.shared_resources.utils.* import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.shared_resources.weatherdata.model.isNullOrInvalid -import com.thewizrd.weather_api.R +import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.extras.cacheRequestIfNeeded import com.thewizrd.weather_api.locationiq.LocationIQProvider import com.thewizrd.weather_api.nws.SolCalcAstroProvider diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherData.kt index b3b11426..288e3319 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherData.kt @@ -18,7 +18,7 @@ import com.thewizrd.shared_resources.weatherdata.model.MoonPhase.MoonPhaseType import com.thewizrd.shared_resources.weatherdata.model.TextForecast import com.thewizrd.shared_resources.weatherdata.model.UV import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.weather_api.R +import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.weatherModule import java.time.LocalDateTime import java.time.ZonedDateTime diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/meteomatics/weather/MeteomaticsWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/meteomatics/weather/MeteomaticsWeatherProvider.kt index ddb4add4..7029cc5b 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/meteomatics/weather/MeteomaticsWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/meteomatics/weather/MeteomaticsWeatherProvider.kt @@ -20,7 +20,7 @@ import com.thewizrd.shared_resources.weatherdata.auth.AuthType import com.thewizrd.shared_resources.weatherdata.auth.BasicAuthProviderKey import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.shared_resources.weatherdata.model.isNullOrInvalid -import com.thewizrd.weather_api.R +import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.extras.cacheRequestIfNeeded import com.thewizrd.weather_api.locationiq.LocationIQProvider import com.thewizrd.weather_api.smc.SunMoonCalcProvider diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt index f496b6f1..2805babb 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt @@ -21,7 +21,7 @@ import com.thewizrd.shared_resources.weatherdata.auth.AuthType import com.thewizrd.shared_resources.weatherdata.model.Pollen import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.shared_resources.weatherdata.model.isNullOrInvalid -import com.thewizrd.weather_api.R +import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.extras.cacheRequestIfNeeded import com.thewizrd.weather_api.keys.Keys import com.thewizrd.weather_api.locationiq.LocationIQProvider diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/WeatherData.kt index a670ce81..c1efeb52 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/WeatherData.kt @@ -27,7 +27,7 @@ import com.thewizrd.shared_resources.weatherdata.model.Pollen import com.thewizrd.shared_resources.weatherdata.model.Precipitation import com.thewizrd.shared_resources.weatherdata.model.TextForecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.weather_api.R +import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.weatherModule import java.time.LocalDateTime import java.time.ZoneOffset diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherData.kt index fa22fc4d..ad331404 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherData.kt @@ -9,7 +9,7 @@ import com.thewizrd.shared_resources.weatherdata.model.* import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.MoonPhase.MoonPhaseType import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.weather_api.R +import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.weatherModule import java.time.LocalDateTime import java.time.ZonedDateTime diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherKitProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherKitProvider.kt index d6bc19c2..d0c75489 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherKitProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherKitProvider.kt @@ -20,7 +20,7 @@ import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.shared_resources.weatherdata.auth.AuthType import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.shared_resources.weatherdata.model.isNullOrInvalid -import com.thewizrd.weather_api.R +import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.extras.cacheRequestIfNeeded import com.thewizrd.weather_api.google.location.getGoogleLocationProvider import com.thewizrd.weather_api.nws.SolCalcAstroProvider From 217cebed1b99e876633d7104ed3348987c5bb0be Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Wed, 20 May 2026 20:41:40 -0400 Subject: [PATCH 04/67] nongms: fix build --- .../com/thewizrd/common/location/LocationProvider.kt | 5 +++-- .../ui/components/ConfirmationOverlay.kt | 4 ++-- .../thewizrd/simpleweather/ui/setup/SetupScreen.kt | 5 ++--- .../simpleweather/ui/weather/WeatherNowScreen.kt | 4 ++-- .../src/main/res/drawable/ic_mobile_arrow_right.xml | 11 +++++++++++ 5 files changed, 20 insertions(+), 9 deletions(-) create mode 100644 wearapp/src/main/res/drawable/ic_mobile_arrow_right.xml diff --git a/common/src/nongms/java/com/thewizrd/common/location/LocationProvider.kt b/common/src/nongms/java/com/thewizrd/common/location/LocationProvider.kt index db648a88..3932c5ad 100644 --- a/common/src/nongms/java/com/thewizrd/common/location/LocationProvider.kt +++ b/common/src/nongms/java/com/thewizrd/common/location/LocationProvider.kt @@ -11,6 +11,7 @@ import androidx.core.os.CancellationSignal import com.thewizrd.common.R import com.thewizrd.common.helpers.locationPermissionEnabled import com.thewizrd.common.utils.ErrorMessage +import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.exceptions.WeatherException import com.thewizrd.shared_resources.locationdata.LocationData @@ -106,7 +107,7 @@ class LocationProvider(private val context: Context) { suspend fun getLatestLocationData(previousLocation: LocationData? = null): LocationResult { if (!LocationManagerCompat.isLocationEnabled(mLocationMgr)) { return LocationResult.Error( - errorMessage = ErrorMessage.Resource(R.string.error_enable_location_services) + errorMessage = ErrorMessage.Resource(sharedRes.string.error_enable_location_services) ) } if (!context.locationPermissionEnabled()) return LocationResult.PermissionDenied() @@ -164,7 +165,7 @@ class LocationProvider(private val context: Context) { if (view == null || view.locationQuery.isNullOrBlank()) { // Stop since there is no valid query - return LocationResult.Error(errorMessage = ErrorMessage.Resource(R.string.error_retrieve_location)) + return LocationResult.Error(errorMessage = ErrorMessage.Resource(sharedRes.string.error_retrieve_location)) } else if (view.locationTZLong.isNullOrBlank() && view.locationLat != 0.0 && view.locationLong != 0.0) { val tzId = weatherModule.tzdbService.getTimeZone(view.locationLat, view.locationLong) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/ConfirmationOverlay.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/ConfirmationOverlay.kt index 94a126cc..6357a817 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/ConfirmationOverlay.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/ConfirmationOverlay.kt @@ -13,7 +13,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.wear.R as wearRes import androidx.wear.compose.material3.ConfirmationDialog import androidx.wear.compose.material3.ConfirmationDialogDefaults import androidx.wear.compose.material3.FailureConfirmationDialog @@ -23,6 +22,7 @@ import androidx.wear.compose.material3.Text import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.viewmodels.ConfirmationData import com.thewizrd.simpleweather.viewmodels.ConfirmationType +import androidx.wear.R as wearRes @Composable fun ConfirmationOverlay( @@ -103,7 +103,7 @@ fun ConfirmationOverlay( } ), painter = rememberAnimatedVectorPainter(image, atEnd), - contentDescription = stringResource(com.google.android.gms.base.R.string.common_open_on_phone) + contentDescription = stringResource(R.string.action_openonphone) ) LaunchedEffect(Unit) { diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupScreen.kt index ae262160..bf385fa5 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/setup/SetupScreen.kt @@ -22,7 +22,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.navigation.NavController -import androidx.wear.R as wearRes import androidx.wear.compose.foundation.lazy.TransformingLazyColumn import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState import androidx.wear.compose.foundation.rotary.RotaryScrollableDefaults @@ -45,7 +44,6 @@ import androidx.wear.compose.navigation.rememberSwipeDismissableNavController import com.thewizrd.common.helpers.locationPermissionEnabled import com.thewizrd.common.utils.ErrorMessage import com.thewizrd.common.viewmodels.LocationSearchViewModel -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.simpleweather.BuildConfig import com.thewizrd.simpleweather.R @@ -55,6 +53,7 @@ import com.thewizrd.simpleweather.ui.helpers.rememberLocationPermissionLauncher import com.thewizrd.simpleweather.ui.navigation.Screen import com.thewizrd.simpleweather.ui.theme.activityViewModel import com.thewizrd.simpleweather.ui.utils.rememberFocusRequester +import com.thewizrd.shared_resources.R as sharedRes @Composable fun SetupScreen( @@ -213,7 +212,7 @@ private fun SetupScreen( icon = { Icon( modifier = Modifier.size(ButtonDefaults.IconSize), - painter = painterResource(id = com.google.android.gms.base.R.drawable.common_full_open_on_phone), + painter = painterResource(id = R.drawable.ic_mobile_arrow_right), contentDescription = stringResource(id = R.string.action_setupfromphone) ) } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt index 6a06f04b..06e0e3a1 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt @@ -84,7 +84,6 @@ import com.thewizrd.common.controls.WeatherDetailsType import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.controls.toUiModel import com.thewizrd.common.utils.ErrorMessage -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.designer.initializeDependencies import com.thewizrd.shared_resources.icons.WeatherIcons @@ -124,6 +123,7 @@ import com.thewizrd.simpleweather.viewmodels.WeatherNowStateModel import com.thewizrd.simpleweather.viewmodels.WeatherNowViewModel import com.thewizrd.simpleweather.wearable.WearableListenerActions import kotlinx.coroutines.launch +import com.thewizrd.shared_resources.R as sharedRes @SuppressLint("LocalContextGetResourceValueCall") @Composable @@ -913,7 +913,7 @@ private fun OpenOnPhoneButton( ) { NavigationButton( label = stringResource(id = R.string.action_openonphone), - iconDrawableId = com.google.android.gms.base.R.drawable.common_full_open_on_phone, + iconDrawableId = R.drawable.ic_mobile_arrow_right, onClick = onOpenOnPhone ) } diff --git a/wearapp/src/main/res/drawable/ic_mobile_arrow_right.xml b/wearapp/src/main/res/drawable/ic_mobile_arrow_right.xml new file mode 100644 index 00000000..60769569 --- /dev/null +++ b/wearapp/src/main/res/drawable/ic_mobile_arrow_right.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file From 88f91261c7ab60bedd72339417dcf700824331fc Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Wed, 20 May 2026 20:43:33 -0400 Subject: [PATCH 05/67] SimpleWeather: v5.13.0-build15 --- app/build.gradle | 2 +- wearapp/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f2701d4d..a42a8929 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get().toInteger() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code (Android: 0, WearOS: 1) // ex) 345100131 = (34, 5.10, 013, 0) - versionCode 365130140 + versionCode 365130150 versionName "5.13.0" vectorDrawables { diff --git a/wearapp/build.gradle b/wearapp/build.gradle index 467a6fd4..d90eb272 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -16,7 +16,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code [Android: 0, WearOS: 1]) // ex) 345100131 = (34, 5.10, 013, 1) - versionCode 365130141 + versionCode 365130151 versionName "5.13.0" vectorDrawables { From 01235bb4dd470b94225cb62a5ce3477c6993d60a Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Wed, 20 May 2026 22:56:06 -0400 Subject: [PATCH 06/67] wearapp: enable all refresh intervals for nongms --- .../src/nongms/java/com/thewizrd/simpleweather/extras/Extras.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wearapp/src/nongms/java/com/thewizrd/simpleweather/extras/Extras.kt b/wearapp/src/nongms/java/com/thewizrd/simpleweather/extras/Extras.kt index 8816efee..cd45e05c 100644 --- a/wearapp/src/nongms/java/com/thewizrd/simpleweather/extras/Extras.kt +++ b/wearapp/src/nongms/java/com/thewizrd/simpleweather/extras/Extras.kt @@ -39,7 +39,7 @@ fun SettingsActivity.IconsFragment.navigateUnsupportedIconPack() { } fun enableAdditionalRefreshIntervals(): Boolean { - return false + return true } fun checkPremiumStatus() { From 4742a7311f77aa5f4b4a21acecc64dd7b562facc Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Wed, 20 May 2026 22:58:16 -0400 Subject: [PATCH 07/67] weather-api: calculate dewpoint and feels like temp if data unavailable * #30 --- .../shared_resources/utils/WeatherUtils.kt | 92 ++++++++++++++++--- .../weather/AccuWeatherProvider.kt | 2 +- .../brightsky/BrightSkyProvider.kt | 10 +- .../weather_api/eccc/ECCCWeatherProvider.kt | 13 ++- .../google/weather/GoogleWeatherProvider.kt | 2 + .../here/weather/HEREWeatherProvider.kt | 2 + .../weather/MeteoFranceProvider.kt | 11 ++- .../weather/MeteomaticsWeatherProvider.kt | 4 +- .../weather_api/metno/MetnoWeatherProvider.kt | 9 +- .../weather_api/nws/NWSWeatherProvider.kt | 5 +- .../weather/OpenWeatherMapProvider.kt | 4 +- .../onecall/OWMOneCallWeatherProvider.kt | 10 +- .../tomorrow/TomorrowIOWeatherProvider.kt | 6 +- .../weatherapi/weather/WeatherApiProvider.kt | 4 +- .../weatherbit/WeatherBitIOProvider.kt | 4 +- .../weatherdata/WeatherProviderImpl.kt | 18 +++- .../weatherkit/WeatherKitProvider.kt | 6 +- .../WeatherUnlockedProvider.kt | 4 +- 18 files changed, 170 insertions(+), 36 deletions(-) diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/WeatherUtils.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/WeatherUtils.kt index 4170b54d..c3deaf55 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/WeatherUtils.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/WeatherUtils.kt @@ -1,5 +1,5 @@ -@file:kotlin.jvm.JvmMultifileClass -@file:kotlin.jvm.JvmName("WeatherUtils") +@file:JvmMultifileClass +@file:JvmName("WeatherUtils") package com.thewizrd.shared_resources.utils @@ -9,8 +9,13 @@ import androidx.annotation.ColorInt import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.R import com.thewizrd.shared_resources.sharedDeps +import com.thewizrd.shared_resources.weatherdata.model.BaseForecast import com.thewizrd.shared_resources.weatherdata.model.Weather import java.time.ZonedDateTime +import kotlin.math.abs +import kotlin.math.ln +import kotlin.math.pow +import kotlin.math.sqrt fun getLastBuildDate(weather: Weather): String { val context = sharedDeps.context @@ -71,7 +76,9 @@ fun getFeelsLikeTemp(temp_f: Float, wind_mph: Float, humidity_percent: Int): Flo fun calculateWindChill(temp_f: Float, wind_mph: Float): Float { return if (temp_f < 50) { - (35.74f + 0.6215f * temp_f - 35.75f * Math.pow(wind_mph.toDouble(), 0.16) + 0.4275f * temp_f * Math.pow(wind_mph.toDouble(), 0.16)).toFloat() + (35.74f + 0.6215f * temp_f - 35.75f * wind_mph.pow(0.16f) + 0.4275f * temp_f * wind_mph.pow( + 0.16f + )) } else { temp_f } @@ -83,17 +90,17 @@ fun calculateHeatIndex(temp_f: Float, humidity: Int): Float { + (2.04901523 * temp_f) + (10.14333127 * humidity) - (0.22475541 * temp_f * humidity) - - (0.00683783 * Math.pow(temp_f.toDouble(), 2.0)) - - (0.05481717 * Math.pow(humidity.toDouble(), 2.0)) - + (0.00122874 * Math.pow(temp_f.toDouble(), 2.0) * humidity) - + (0.00085282 * temp_f * Math.pow(humidity.toDouble(), 2.0)) - - (0.00000199 * Math.pow(temp_f.toDouble(), 2.0) * Math.pow(humidity.toDouble(), 2.0))) + - (0.00683783 * temp_f.pow(2.0f)) + - (0.05481717 * humidity.toFloat().pow(2.0f)) + + (0.00122874 * temp_f.pow(2.0f) * humidity) + + (0.00085282 * temp_f * humidity.toFloat().pow(2.0f)) + - (0.00000199 * temp_f.pow(2.0f) * humidity.toFloat().pow(2.0f))) if (humidity < 13 && temp_f > 80 && temp_f < 112) { - val adj = (13 - humidity) / 4f * Math.sqrt(((17 - Math.abs(temp_f - 95)) / 17).toDouble()) + val adj = (13 - humidity) / 4f * sqrt(((17 - abs(temp_f - 95)) / 17)) HI -= adj } else if (humidity > 85 && temp_f > 80 && temp_f < 87) { - val adj = ((humidity - 85) / 10f * ((87 - temp_f) / 5)).toDouble() + val adj = ((humidity - 85) / 10f * ((87 - temp_f) / 5)) HI += adj } @@ -107,12 +114,75 @@ fun calculateHeatIndex(temp_f: Float, humidity: Int): Float { } } +fun Weather.calculateFeelsLikeTemp() { + if (this.condition == null) return + if (this.atmosphere == null) return + + val currentTempF = this.condition?.tempF ?: return + val currentHumidity = this.atmosphere?.humidity ?: return + val currentWindMph = this.condition?.windMph ?: return + val currentFeelsLikeF = this.condition?.feelslikeF + + if (currentFeelsLikeF == null) { + val feelsLikeF = getFeelsLikeTemp(currentTempF, currentWindMph, currentHumidity) + this.condition?.feelslikeF = feelsLikeF + this.condition?.feelslikeC = ConversionMethods.FtoC(feelsLikeF) + } +} + +fun BaseForecast.calculateFeelsLikeTemp() { + if (this.extras == null) return + + val tempF = this.highF ?: return + val humidity = this.extras?.humidity ?: return + val windMph = this.extras?.windMph ?: return + val currentFeelsLikeF = this.extras?.feelslikeF + + if (currentFeelsLikeF == null) { + val feelsLikeF = getFeelsLikeTemp(tempF, windMph, humidity) + this.extras?.feelslikeF = feelsLikeF + this.extras?.feelslikeC = ConversionMethods.FtoC(feelsLikeF) + } +} + fun calculateDewpointF(temp_f: Float, humidity: Int): Float { return ConversionMethods.CtoF(calculateDewpointC(ConversionMethods.FtoC(temp_f), humidity)) } fun calculateDewpointC(temp_c: Float, humidity: Int): Float { - return (243.04f * (Math.log((humidity / 100f).toDouble()) + ((17.625f * temp_c) / (243.04f + temp_c))) / (17.625f - Math.log((humidity / 100f).toDouble()) - ((17.625f * temp_c) / (243.04f + temp_c)))).toFloat() + return (243.04f * (ln((humidity / 100f)) + ((17.625f * temp_c) / (243.04f + temp_c))) / (17.625f - ln( + (humidity / 100f) + ) - ((17.625f * temp_c) / (243.04f + temp_c)))) +} + +fun Weather.calculateDewpoint() { + if (this.atmosphere == null) return + + val currentTempC = this.condition?.tempC ?: return + val currentTempF = this.condition?.tempF ?: return + val currentHumidity = this.atmosphere?.humidity ?: return + val currentDewPointC = this.atmosphere?.dewpointC + val currentDewPointF = this.atmosphere?.dewpointF + + if (currentDewPointC == null || currentDewPointF == null) { + this.atmosphere?.dewpointC = calculateDewpointC(currentTempC, currentHumidity) + this.atmosphere?.dewpointF = calculateDewpointF(currentTempF, currentHumidity) + } +} + +fun BaseForecast.calculateDewpoint() { + if (this.extras == null) return + + val tempC = this.highC ?: return + val tempF = this.highF ?: return + val humidity = this.extras?.humidity ?: return + val dewPointC = this.extras?.dewpointC + val dewPointF = this.extras?.dewpointF + + if (dewPointC == null || dewPointF == null) { + this.extras?.dewpointC = calculateDewpointC(tempC, humidity) + this.extras?.dewpointF = calculateDewpointF(tempF, humidity) + } } @ColorInt diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/accuweather/weather/AccuWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/accuweather/weather/AccuWeatherProvider.kt index 8c9aea4b..a7d271fa 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/accuweather/weather/AccuWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/accuweather/weather/AccuWeatherProvider.kt @@ -329,7 +329,7 @@ class AccuWeatherProvider : WeatherProviderImpl(), PollenProvider { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { - // no-op + super.updateWeatherData(location, weather) } override suspend fun updateLocationQuery(weather: Weather): String { diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/brightsky/BrightSkyProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/brightsky/BrightSkyProvider.kt index a663491c..e80cb7e8 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/brightsky/BrightSkyProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/brightsky/BrightSkyProvider.kt @@ -11,7 +11,11 @@ import com.thewizrd.shared_resources.okhttp3.OkHttp3Utils.await import com.thewizrd.shared_resources.okhttp3.OkHttp3Utils.getStream import com.thewizrd.shared_resources.remoteconfig.remoteConfigService import com.thewizrd.shared_resources.sharedDeps -import com.thewizrd.shared_resources.utils.* +import com.thewizrd.shared_resources.utils.JSONParser +import com.thewizrd.shared_resources.utils.LocationUtils +import com.thewizrd.shared_resources.utils.Logger +import com.thewizrd.shared_resources.utils.ZoneIdCompat +import com.thewizrd.shared_resources.utils.createUnsupportedLocationException import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.shared_resources.weatherdata.model.isNullOrInvalid @@ -36,7 +40,7 @@ import java.time.LocalTime import java.time.ZoneOffset import java.time.ZonedDateTime import java.time.format.DateTimeFormatter -import java.util.* +import java.util.Locale import java.util.concurrent.TimeUnit class BrightSkyProvider : WeatherProviderImpl() { @@ -228,6 +232,8 @@ class BrightSkyProvider : WeatherProviderImpl() { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + // DWD reports datetime in UTC; add location tz_offset val offset = location.tzOffset weather.updateTime = weather.updateTime!!.withZoneSameInstant(offset) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/eccc/ECCCWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/eccc/ECCCWeatherProvider.kt index 1963dd28..fad1de8c 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/eccc/ECCCWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/eccc/ECCCWeatherProvider.kt @@ -2,6 +2,7 @@ package com.thewizrd.weather_api.eccc import android.util.Log import com.ibm.icu.util.ULocale +import com.thewizrd.shared_resources.R import com.thewizrd.shared_resources.exceptions.ErrorStatus import com.thewizrd.shared_resources.exceptions.WeatherException import com.thewizrd.shared_resources.icons.WeatherIcons @@ -12,11 +13,15 @@ import com.thewizrd.shared_resources.okhttp3.OkHttp3Utils.await import com.thewizrd.shared_resources.okhttp3.OkHttp3Utils.getStream import com.thewizrd.shared_resources.remoteconfig.remoteConfigService import com.thewizrd.shared_resources.sharedDeps -import com.thewizrd.shared_resources.utils.* +import com.thewizrd.shared_resources.utils.JSONParser +import com.thewizrd.shared_resources.utils.LocaleUtils +import com.thewizrd.shared_resources.utils.LocationUtils +import com.thewizrd.shared_resources.utils.Logger +import com.thewizrd.shared_resources.utils.ZoneIdCompat +import com.thewizrd.shared_resources.utils.createUnsupportedLocationException import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.shared_resources.weatherdata.model.isNullOrInvalid -import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.extras.cacheRequestIfNeeded import com.thewizrd.weather_api.locationiq.LocationIQProvider import com.thewizrd.weather_api.nws.SolCalcAstroProvider @@ -37,7 +42,7 @@ import java.time.Instant import java.time.LocalTime import java.time.ZoneOffset import java.time.ZonedDateTime -import java.util.* +import java.util.Locale import java.util.concurrent.TimeUnit class ECCCWeatherProvider : WeatherProviderImpl() { @@ -175,6 +180,8 @@ class ECCCWeatherProvider : WeatherProviderImpl() { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + val offset = location.tzOffset weather.updateTime = weather.updateTime!!.withZoneSameInstant(offset) weather.condition!!.observationTime = diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/GoogleWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/GoogleWeatherProvider.kt index 4f50def1..ce91f6a2 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/GoogleWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/GoogleWeatherProvider.kt @@ -344,6 +344,8 @@ class GoogleWeatherProvider : WeatherProviderImpl() { } override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + // Update forecast, hourly, sunrise/sunset, moonrise/moonset val offset = location.tzOffset diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/here/weather/HEREWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/here/weather/HEREWeatherProvider.kt index 90c34716..294cedf8 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/here/weather/HEREWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/here/weather/HEREWeatherProvider.kt @@ -214,6 +214,8 @@ class HEREWeatherProvider : WeatherProviderImpl() { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + val offset = location.tzOffset weather.weatherAlerts?.forEach { alert -> diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt index b8263006..df115798 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt @@ -11,7 +11,12 @@ import com.thewizrd.shared_resources.okhttp3.OkHttp3Utils.await import com.thewizrd.shared_resources.okhttp3.OkHttp3Utils.getStream import com.thewizrd.shared_resources.remoteconfig.remoteConfigService import com.thewizrd.shared_resources.sharedDeps -import com.thewizrd.shared_resources.utils.* +import com.thewizrd.shared_resources.utils.JSONParser +import com.thewizrd.shared_resources.utils.LocaleUtils +import com.thewizrd.shared_resources.utils.LocationUtils +import com.thewizrd.shared_resources.utils.Logger +import com.thewizrd.shared_resources.utils.ZoneIdCompat +import com.thewizrd.shared_resources.utils.createUnsupportedLocationException import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.shared_resources.weatherdata.auth.AuthType import com.thewizrd.shared_resources.weatherdata.model.Weather @@ -38,7 +43,7 @@ import java.time.Instant import java.time.LocalTime import java.time.ZoneOffset import java.time.ZonedDateTime -import java.util.* +import java.util.Locale import java.util.concurrent.TimeUnit class MeteoFranceProvider : WeatherProviderImpl() { @@ -227,6 +232,8 @@ class MeteoFranceProvider : WeatherProviderImpl() { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + // MeteoFrance reports datetime in UTC; add location tz_offset val offset = location.tzOffset weather.updateTime = weather.updateTime!!.withZoneSameInstant(offset) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/meteomatics/weather/MeteomaticsWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/meteomatics/weather/MeteomaticsWeatherProvider.kt index 7029cc5b..9b0f41c1 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/meteomatics/weather/MeteomaticsWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/meteomatics/weather/MeteomaticsWeatherProvider.kt @@ -3,6 +3,7 @@ package com.thewizrd.weather_api.meteomatics.weather import android.net.Uri import android.util.Log import androidx.core.net.toUri +import com.thewizrd.shared_resources.R import com.thewizrd.shared_resources.exceptions.ErrorStatus import com.thewizrd.shared_resources.exceptions.WeatherException import com.thewizrd.shared_resources.icons.WeatherIcons @@ -20,7 +21,6 @@ import com.thewizrd.shared_resources.weatherdata.auth.AuthType import com.thewizrd.shared_resources.weatherdata.auth.BasicAuthProviderKey import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.shared_resources.weatherdata.model.isNullOrInvalid -import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.extras.cacheRequestIfNeeded import com.thewizrd.weather_api.locationiq.LocationIQProvider import com.thewizrd.weather_api.smc.SunMoonCalcProvider @@ -309,6 +309,8 @@ class MeteomaticsWeatherProvider : WeatherProviderImpl() { } override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + val offset = location.tzOffset weather.updateTime = weather.updateTime!!.withZoneSameInstant(offset) weather.condition!!.observationTime = diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/metno/MetnoWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/metno/MetnoWeatherProvider.kt index 565970c3..32ee584f 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/metno/MetnoWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/metno/MetnoWeatherProvider.kt @@ -30,10 +30,13 @@ import okhttp3.Request import okhttp3.internal.closeQuietly import java.io.IOException import java.text.DecimalFormat -import java.time.* import java.time.Instant +import java.time.LocalDateTime +import java.time.LocalTime +import java.time.ZoneOffset +import java.time.ZonedDateTime import java.time.format.DateTimeFormatter -import java.util.* +import java.util.Locale import java.util.concurrent.TimeUnit class MetnoWeatherProvider : WeatherProviderImpl() { @@ -187,6 +190,8 @@ class MetnoWeatherProvider : WeatherProviderImpl() { } override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + // OWM reports datetime in UTC; add location tz_offset val offset = location.tzOffset weather.updateTime = weather.updateTime!!.withZoneSameInstant(offset) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/nws/NWSWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/nws/NWSWeatherProvider.kt index 5c7da403..3280925c 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/nws/NWSWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/nws/NWSWeatherProvider.kt @@ -56,7 +56,8 @@ import java.time.Instant import java.time.LocalTime import java.time.ZoneOffset import java.time.ZonedDateTime -import java.util.* +import java.util.Collections +import java.util.Locale import java.util.concurrent.TimeUnit class NWSWeatherProvider : WeatherProviderImpl() { @@ -417,6 +418,8 @@ class NWSWeatherProvider : WeatherProviderImpl() { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + val offset = location.tzOffset weather.updateTime = weather.updateTime!!.withZoneSameInstant(offset) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/OpenWeatherMapProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/OpenWeatherMapProvider.kt index 4bbc4a09..c3a2710f 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/OpenWeatherMapProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/OpenWeatherMapProvider.kt @@ -42,7 +42,7 @@ import java.time.Instant import java.time.LocalTime import java.time.ZoneOffset import java.time.ZonedDateTime -import java.util.* +import java.util.Locale import java.util.concurrent.TimeUnit class OpenWeatherMapProvider : WeatherProviderImpl { @@ -250,6 +250,8 @@ class OpenWeatherMapProvider : WeatherProviderImpl { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + // OWM reports datetime in UTC; add location tz_offset val offset = location.tzOffset weather.updateTime = weather.updateTime!!.withZoneSameInstant(offset) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/onecall/OWMOneCallWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/onecall/OWMOneCallWeatherProvider.kt index 94d00c6c..eaf2f78b 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/onecall/OWMOneCallWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/onecall/OWMOneCallWeatherProvider.kt @@ -11,7 +11,11 @@ import com.thewizrd.shared_resources.okhttp3.OkHttp3Utils.await import com.thewizrd.shared_resources.okhttp3.OkHttp3Utils.getStream import com.thewizrd.shared_resources.remoteconfig.remoteConfigService import com.thewizrd.shared_resources.sharedDeps -import com.thewizrd.shared_resources.utils.* +import com.thewizrd.shared_resources.utils.DateTimeUtils +import com.thewizrd.shared_resources.utils.JSONParser +import com.thewizrd.shared_resources.utils.LocaleUtils +import com.thewizrd.shared_resources.utils.Logger +import com.thewizrd.shared_resources.utils.ZoneIdCompat import com.thewizrd.shared_resources.weatherdata.AirQualityProvider import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.shared_resources.weatherdata.auth.AuthType @@ -40,7 +44,7 @@ import java.time.Instant import java.time.LocalTime import java.time.ZoneOffset import java.time.ZonedDateTime -import java.util.* +import java.util.Locale import java.util.concurrent.TimeUnit import com.thewizrd.weather_api.openweather.weather.onecall.Rootobject as OneCallRootobject import com.thewizrd.weather_api.openweather.weather.onecall.createWeatherData as createOneCallWeatherData @@ -243,6 +247,8 @@ class OWMOneCallWeatherProvider : WeatherProviderImpl, AirQualityProvider { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + // OWM reports datetime in UTC; add location tz_offset val offset = location.tzOffset weather.updateTime = weather.updateTime!!.withZoneSameInstant(offset) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt index 2805babb..15e31d84 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt @@ -3,6 +3,7 @@ package com.thewizrd.weather_api.tomorrow import android.util.Log import androidx.core.net.toUri import com.ibm.icu.util.ULocale +import com.thewizrd.shared_resources.R import com.thewizrd.shared_resources.exceptions.ErrorStatus import com.thewizrd.shared_resources.exceptions.WeatherException import com.thewizrd.shared_resources.icons.WeatherIcons @@ -21,7 +22,6 @@ import com.thewizrd.shared_resources.weatherdata.auth.AuthType import com.thewizrd.shared_resources.weatherdata.model.Pollen import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.shared_resources.weatherdata.model.isNullOrInvalid -import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.extras.cacheRequestIfNeeded import com.thewizrd.weather_api.keys.Keys import com.thewizrd.weather_api.locationiq.LocationIQProvider @@ -46,7 +46,7 @@ import java.time.Instant import java.time.LocalTime import java.time.ZoneOffset import java.time.ZonedDateTime -import java.util.* +import java.util.Locale import java.util.concurrent.TimeUnit class TomorrowIOWeatherProvider : WeatherProviderImpl(), PollenProvider { @@ -396,6 +396,8 @@ class TomorrowIOWeatherProvider : WeatherProviderImpl(), PollenProvider { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + val offset = location.tzOffset // Update tz for weather properties diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt index 86dc344e..54a7a780 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt @@ -42,7 +42,7 @@ import java.time.Instant import java.time.LocalTime import java.time.ZoneOffset import java.time.ZonedDateTime -import java.util.* +import java.util.Locale import java.util.concurrent.TimeUnit class WeatherApiProvider : WeatherProviderImpl(), WeatherAlertProvider { @@ -295,7 +295,7 @@ class WeatherApiProvider : WeatherProviderImpl(), WeatherAlertProvider { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { - // no-op + super.updateWeatherData(location, weather) } override suspend fun updateLocationQuery(weather: Weather): String { diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherbit/WeatherBitIOProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherbit/WeatherBitIOProvider.kt index 016045da..98372e50 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherbit/WeatherBitIOProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherbit/WeatherBitIOProvider.kt @@ -42,7 +42,7 @@ import java.time.Instant import java.time.LocalTime import java.time.ZoneOffset import java.time.ZonedDateTime -import java.util.* +import java.util.Locale import java.util.concurrent.TimeUnit class WeatherBitIOProvider : WeatherProviderImpl(), WeatherAlertProvider { @@ -329,7 +329,7 @@ class WeatherBitIOProvider : WeatherProviderImpl(), WeatherAlertProvider { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { - // no-op + super.updateWeatherData(location, weather) } override suspend fun updateLocationQuery(weather: Weather): String { diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt index 209d61a5..7844fc39 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt @@ -2,6 +2,7 @@ package com.thewizrd.weather_api.weatherdata import android.location.Location import android.util.Log +import androidx.annotation.CallSuper import com.thewizrd.shared_resources.BuildConfig import com.thewizrd.shared_resources.R import com.thewizrd.shared_resources.appLib @@ -16,6 +17,8 @@ import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Coordinate import com.thewizrd.shared_resources.utils.LocationUtils import com.thewizrd.shared_resources.utils.Logger +import com.thewizrd.shared_resources.utils.calculateDewpoint +import com.thewizrd.shared_resources.utils.calculateFeelsLikeTemp import com.thewizrd.shared_resources.weatherdata.AirQualityProvider import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.shared_resources.weatherdata.WeatherProvider @@ -215,7 +218,20 @@ abstract class WeatherProviderImpl : WeatherProvider, RateLimitedRequest { * @param weather The weather data to update */ @Throws(WeatherException::class) - protected abstract suspend fun updateWeatherData(location: LocationData, weather: Weather) + @CallSuper + protected open suspend fun updateWeatherData(location: LocationData, weather: Weather) { + weather.calculateDewpoint() + weather.calculateFeelsLikeTemp() + + weather.forecast?.forEach { + it.calculateDewpoint() + it.calculateFeelsLikeTemp() + } + weather.hrForecast?.forEach { + it.calculateDewpoint() + it.calculateFeelsLikeTemp() + } + } private suspend fun updateAQIData(location: LocationData, weather: Weather) { val aqicnData = AQICNProvider().getAirQualityData(location) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherKitProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherKitProvider.kt index d0c75489..748ac0f8 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherKitProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherKitProvider.kt @@ -3,6 +3,7 @@ package com.thewizrd.weather_api.weatherkit import android.util.Log import androidx.core.net.toUri import com.ibm.icu.util.ULocale +import com.thewizrd.shared_resources.R import com.thewizrd.shared_resources.exceptions.ErrorStatus import com.thewizrd.shared_resources.exceptions.WeatherException import com.thewizrd.shared_resources.icons.WeatherIcons @@ -20,7 +21,6 @@ import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.shared_resources.weatherdata.auth.AuthType import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.shared_resources.weatherdata.model.isNullOrInvalid -import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.extras.cacheRequestIfNeeded import com.thewizrd.weather_api.google.location.getGoogleLocationProvider import com.thewizrd.weather_api.nws.SolCalcAstroProvider @@ -42,7 +42,7 @@ import java.time.Instant import java.time.LocalTime import java.time.ZoneOffset import java.time.ZonedDateTime -import java.util.* +import java.util.Locale import java.util.concurrent.TimeUnit class WeatherKitProvider : WeatherProviderImpl() { @@ -189,6 +189,8 @@ class WeatherKitProvider : WeatherProviderImpl() { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + val offset = location.tzOffset // Update tz for weather properties diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherunlocked/WeatherUnlockedProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherunlocked/WeatherUnlockedProvider.kt index 616b28f0..4a8bd9fb 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherunlocked/WeatherUnlockedProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherunlocked/WeatherUnlockedProvider.kt @@ -39,7 +39,7 @@ import java.time.Instant import java.time.LocalTime import java.time.ZoneOffset import java.time.ZonedDateTime -import java.util.* +import java.util.Locale import java.util.concurrent.TimeUnit class WeatherUnlockedProvider : WeatherProviderImpl() { @@ -187,6 +187,8 @@ class WeatherUnlockedProvider : WeatherProviderImpl() { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + val offset = location.tzOffset weather.updateTime = weather.updateTime!!.withZoneSameInstant(offset) weather.condition!!.observationTime = From 6cf3b4b6fbec61e7dd1289e4ced89694ab72e9ce Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Tue, 26 May 2026 10:29:43 -0400 Subject: [PATCH 08/67] widgets: add new 1x1 for any WeatherDetailsType --- app/src/main/AndroidManifest.xml | 13 + .../widgets/WeatherWidgetProvider1x1Custom.kt | 28 ++ .../simpleweather/widgets/WidgetGraphType.kt | 2 +- .../simpleweather/widgets/WidgetType.java | 3 +- .../simpleweather/widgets/WidgetUtils.kt | 35 +- ...AbstractWeatherWidgetPreferenceFragment.kt | 22 +- .../WeatherWidgetPreferenceFragment.kt | 36 +- .../preferences/WidgetPreferenceKeys.kt | 1 + .../WeatherWidget1x1CustomCreator.kt | 359 ++++++++++++++++++ .../appwidget_preview_1x1_custom.png | Bin 0 -> 7683 bytes .../main/res/layout/app_widget_1x1_custom.xml | 116 ++++++ .../layout/app_widget_1x1_custom_preview.xml | 81 ++++ .../res/xml/app_widget_1x1_custom_info.xml | 16 + app/src/main/res/xml/pref_widgetconfig.xml | 25 +- 14 files changed, 722 insertions(+), 15 deletions(-) create mode 100644 app/src/main/java/com/thewizrd/simpleweather/widgets/WeatherWidgetProvider1x1Custom.kt create mode 100644 app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget1x1CustomCreator.kt create mode 100644 app/src/main/res/drawable-nodpi/appwidget_preview_1x1_custom.png create mode 100644 app/src/main/res/layout/app_widget_1x1_custom.xml create mode 100644 app/src/main/res/layout/app_widget_1x1_custom_preview.xml create mode 100644 app/src/main/res/xml/app_widget_1x1_custom_info.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fdf4957a..f2316884 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -117,6 +117,19 @@ android:name="android.appwidget.provider" android:resource="@xml/app_widget_1x1_info" /> + + + + + + + + () init { - for (type in values()) { + for (type in entries) { map.put(type.value, type) } } diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/WidgetType.java b/app/src/main/java/com/thewizrd/simpleweather/widgets/WidgetType.java index 9540b0e4..eb841b49 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/WidgetType.java +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/WidgetType.java @@ -22,7 +22,8 @@ public enum WidgetType { Widget4x2Tomorrow(15), Widget2x2M3(16), Widget4x4M3(17), - Widget4x2M3(18); + Widget4x2M3(18), + Widget1x1Custom(19); private final int value; diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/WidgetUtils.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/WidgetUtils.kt index ef5d3e90..0c4c3873 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/WidgetUtils.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/WidgetUtils.kt @@ -10,6 +10,7 @@ import android.util.Log import android.util.SparseArray import androidx.annotation.ColorInt import androidx.core.content.edit +import com.thewizrd.common.controls.WeatherDetailsType import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.di.settingsManager @@ -20,8 +21,10 @@ import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.verifyActivityInfo import com.thewizrd.shared_resources.utils.JSONParser import com.thewizrd.shared_resources.utils.Logger +import com.thewizrd.simpleweather.widgets.preferences.KEY_WEATHERDETAILSTYPEOPTION import com.thewizrd.simpleweather.widgets.remoteviews.AbstractWidgetRemoteViewCreator import com.thewizrd.simpleweather.widgets.remoteviews.WeatherWidget1x1Creator +import com.thewizrd.simpleweather.widgets.remoteviews.WeatherWidget1x1CustomCreator import com.thewizrd.simpleweather.widgets.remoteviews.WeatherWidget2x2Creator import com.thewizrd.simpleweather.widgets.remoteviews.WeatherWidget2x2M3Creator import com.thewizrd.simpleweather.widgets.remoteviews.WeatherWidget2x2MaterialYouCreator @@ -258,6 +261,9 @@ object WidgetUtils { WidgetType.Widget1x1 -> { mAppWidgetManager.getAppWidgetIds(WeatherWidgetProvider1x1.Info.getInstance().componentName) } + WidgetType.Widget1x1Custom -> { + mAppWidgetManager.getAppWidgetIds(WeatherWidgetProvider1x1Custom.Info.getInstance().componentName) + } WidgetType.Widget2x2 -> { mAppWidgetManager.getAppWidgetIds(WeatherWidgetProvider2x2.Info.getInstance().componentName) } @@ -306,11 +312,9 @@ object WidgetUtils { WidgetType.Widget2x2M3 -> mAppWidgetManager.getAppWidgetIds( WeatherWidgetProvider2x2M3.Info.getInstance().componentName ) - WidgetType.Widget4x4M3 -> mAppWidgetManager.getAppWidgetIds( WeatherWidgetProvider4x4M3.Info.getInstance().componentName ) - WidgetType.Widget4x2M3 -> mAppWidgetManager.getAppWidgetIds( WeatherWidgetProvider4x2M3.Info.getInstance().componentName ) @@ -321,6 +325,7 @@ object WidgetUtils { return when (widgetType) { WidgetType.Unknown -> null WidgetType.Widget1x1 -> WeatherWidgetProvider1x1.Info.getInstance() + WidgetType.Widget1x1Custom -> WeatherWidgetProvider1x1Custom.Info.getInstance() WidgetType.Widget2x2 -> WeatherWidgetProvider2x2.Info.getInstance() WidgetType.Widget4x1 -> WeatherWidgetProvider4x1.Info.getInstance() WidgetType.Widget4x2 -> WeatherWidgetProvider4x2.Info.getInstance() @@ -663,7 +668,8 @@ object WidgetUtils { val widgetWidth = getMinSizeForCell( when (widgetType) { WidgetType.Unknown -> 0 - WidgetType.Widget1x1 -> 1 + WidgetType.Widget1x1, + WidgetType.Widget1x1Custom -> 1 WidgetType.Widget2x2 -> 2 WidgetType.Widget4x1 -> 4 WidgetType.Widget4x2 -> 4 @@ -688,7 +694,8 @@ object WidgetUtils { val widgetHeight = getMinSizeForCell( when (widgetType) { WidgetType.Unknown -> 0 - WidgetType.Widget1x1 -> 1 + WidgetType.Widget1x1, + WidgetType.Widget1x1Custom -> 1 WidgetType.Widget2x2 -> 2 WidgetType.Widget4x1 -> 1 WidgetType.Widget4x2 -> 2 @@ -769,6 +776,9 @@ object WidgetUtils { WeatherWidgetProvider1x1.Info.getInstance().widgetLayoutId -> { return WidgetType.Widget1x1 } + WeatherWidgetProvider1x1Custom.Info.getInstance().widgetLayoutId -> { + return WidgetType.Widget1x1Custom + } WeatherWidgetProvider2x2.Info.getInstance().widgetLayoutId -> { return WidgetType.Widget2x2 } @@ -835,6 +845,7 @@ object WidgetUtils { return when (getWidgetTypeFromID(appWidgetId)) { WidgetType.Unknown -> throw IllegalArgumentException("Unknown widget type") WidgetType.Widget1x1 -> WeatherWidget1x1Creator(context) + WidgetType.Widget1x1Custom -> WeatherWidget1x1CustomCreator(context) WidgetType.Widget2x2 -> WeatherWidget2x2Creator(context) WidgetType.Widget4x1 -> WeatherWidget4x1Creator(context) WidgetType.Widget4x2 -> WeatherWidget4x2Creator(context) @@ -922,7 +933,7 @@ object WidgetUtils { } fun isLocationNameOptionalWidget(widgetType: WidgetType): Boolean { - return widgetType == WidgetType.Widget1x1 || widgetType == WidgetType.Widget4x1 || widgetType == WidgetType.Widget4x1Google || widgetType == WidgetType.Widget4x2Clock || widgetType == WidgetType.Widget4x2Graph + return widgetType == WidgetType.Widget1x1 || widgetType == WidgetType.Widget1x1Custom || widgetType == WidgetType.Widget4x1 || widgetType == WidgetType.Widget4x1Google || widgetType == WidgetType.Widget4x2Clock || widgetType == WidgetType.Widget4x2Graph } fun isSettingsButtonOptional(widgetType: WidgetType): Boolean { @@ -1185,6 +1196,20 @@ object WidgetUtils { } } + fun getWidgetDetailsType(widgetId: Int): WeatherDetailsType { + val prefs = getPreferences(widgetId) + + val value = prefs.getInt(KEY_WEATHERDETAILSTYPEOPTION, 0) + + return WeatherDetailsType.valueOf(value) + } + + fun setWidgetDetailsType(widgetId: Int, value: Int) { + getPreferences(widgetId).edit(true) { + putInt(KEY_WEATHERDETAILSTYPEOPTION, value) + } + } + fun getCustomTextSizeMultiplier(widgetId: Int): Float { val prefs = getPreferences(widgetId) return prefs.getFloat(KEY_CUSTOMTXTMULTIPLIER, 1f) diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/AbstractWeatherWidgetPreferenceFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/AbstractWeatherWidgetPreferenceFragment.kt index 267fcd0e..58bef469 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/AbstractWeatherWidgetPreferenceFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/AbstractWeatherWidgetPreferenceFragment.kt @@ -43,7 +43,6 @@ import com.thewizrd.common.location.LocationProvider import com.thewizrd.common.location.LocationResult import com.thewizrd.common.utils.ErrorMessage import com.thewizrd.common.viewmodels.LocationSearchResult -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.locationdata.LocationData @@ -56,6 +55,7 @@ import com.thewizrd.shared_resources.utils.ContextUtils.isNightMode import com.thewizrd.shared_resources.utils.ContextUtils.isSmallestWidth import com.thewizrd.shared_resources.utils.Logger import com.thewizrd.shared_resources.weatherdata.model.AirQuality +import com.thewizrd.shared_resources.weatherdata.model.Astronomy import com.thewizrd.shared_resources.weatherdata.model.Atmosphere import com.thewizrd.shared_resources.weatherdata.model.Beaufort import com.thewizrd.shared_resources.weatherdata.model.Condition @@ -65,6 +65,7 @@ import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.Location import com.thewizrd.shared_resources.weatherdata.model.LocationType import com.thewizrd.shared_resources.weatherdata.model.MinutelyForecast +import com.thewizrd.shared_resources.weatherdata.model.MoonPhase import com.thewizrd.shared_resources.weatherdata.model.Pollen import com.thewizrd.shared_resources.weatherdata.model.Precipitation import com.thewizrd.shared_resources.weatherdata.model.UV @@ -91,6 +92,7 @@ import kotlin.math.min import kotlin.math.roundToInt import kotlin.properties.Delegates import kotlin.random.Random +import com.thewizrd.shared_resources.R as sharedRes abstract class AbstractWeatherWidgetPreferenceFragment : ToolbarPreferenceFragmentCompat() { // Widget id for ConfigurationActivity @@ -484,6 +486,7 @@ abstract class AbstractWeatherWidgetPreferenceFragment : ToolbarPreferenceFragme } } + @SuppressLint("RestrictedApi") protected fun updateMockLocation(locationName: String, locationQuery: String) { mockLocationData.name = locationName mockLocationData.query = locationQuery @@ -623,7 +626,22 @@ abstract class AbstractWeatherWidgetPreferenceFragment : ToolbarPreferenceFragme ragweedPollenCount = Pollen.PollenCount.MODERATE } } - atmosphere = Atmosphere() + atmosphere = Atmosphere().apply { + humidity = 80 + pressureIn = 30.06f + pressureMb = 1018f + visibilityMi = 10f + visibilityKm = 16f + dewpointF = 62f + dewpointC = 16.6f + } + astronomy = Astronomy().apply { + sunrise = LocalDate.now().atTime(5, 30) + sunset = LocalDate.now().atTime(20, 0) + moonrise = LocalDate.now().atTime(15, 0) + moonset = LocalDate.now().atTime(3, 0) + moonPhase = MoonPhase(MoonPhase.MoonPhaseType.WAXING_GIBBOUS) + } precipitation = Precipitation().apply { pop = 15 cloudiness = 25 diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WeatherWidgetPreferenceFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WeatherWidgetPreferenceFragment.kt index a8dabfb5..c0433802 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WeatherWidgetPreferenceFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WeatherWidgetPreferenceFragment.kt @@ -25,12 +25,13 @@ import androidx.preference.ListPreference import androidx.preference.Preference import androidx.preference.SwitchPreference import com.google.android.material.snackbar.BaseTransientBottomBar +import com.thewizrd.common.controls.DetailItemViewModel +import com.thewizrd.common.controls.WeatherDetailsType import com.thewizrd.common.helpers.backgroundLocationPermissionEnabled import com.thewizrd.common.helpers.getBackgroundLocationRationale import com.thewizrd.common.helpers.locationPermissionEnabled import com.thewizrd.common.location.LocationResult import com.thewizrd.common.viewmodels.LocationSearchResult -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.controls.ComboBoxItem import com.thewizrd.shared_resources.di.localBroadcastManager @@ -57,6 +58,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import com.google.android.material.snackbar.Snackbar as materialSnackbar +import com.thewizrd.shared_resources.R as sharedRes class WeatherWidgetPreferenceFragment : BaseWeatherWidgetPreferenceFragment() { private lateinit var favorites: MutableCollection @@ -69,6 +71,7 @@ class WeatherWidgetPreferenceFragment : BaseWeatherWidgetPreferenceFragment() { private lateinit var fcastOptPref: ListPreference private lateinit var tap2switchPref: SwitchPreference private lateinit var graphTypePref: ListPreference + private lateinit var detailsTypePref: ListPreference override fun getPreferencesResId(): Int = R.xml.pref_widgetconfig @@ -245,6 +248,32 @@ class WeatherWidgetPreferenceFragment : BaseWeatherWidgetPreferenceFragment() { fcastOptPref.setValueIndex(WidgetUtils.ForecastOption.FULL.value) findPreference(KEY_FORECAST)!!.isVisible = false } + + if (mWidgetType == WidgetType.Widget1x1Custom) { + detailsTypePref = findPreference(KEY_WEATHERDETAILSTYPEOPTION)!! + + val entries = WeatherDetailsType.entries + + detailsTypePref.entries = entries.map { + DetailItemViewModel(it, "").label + }.toTypedArray() + detailsTypePref.entryValues = entries.map { it.value.toString() }.toTypedArray() + + detailsTypePref.onPreferenceChangeListener = + Preference.OnPreferenceChangeListener { _, newValue -> + mWidgetOptions.putSerializable( + KEY_WEATHERDETAILSTYPEOPTION, + WeatherDetailsType.valueOf(newValue.toString().toInt()) + ) + updateWidgetView() + true + } + detailsTypePref.isVisible = true + + val detailsType = WidgetUtils.getWidgetDetailsType(mAppWidgetId) + detailsTypePref.value = detailsType.value.toString() + detailsTypePref.callChangeListener(detailsTypePref.value) + } } override fun onSetupActivityResult(result: ActivityResult) { @@ -348,6 +377,7 @@ class WeatherWidgetPreferenceFragment : BaseWeatherWidgetPreferenceFragment() { 96f * when (mWidgetType) { WidgetType.Unknown -> 4 WidgetType.Widget1x1 -> 1 + WidgetType.Widget1x1Custom -> 1 WidgetType.Widget2x2 -> 2 WidgetType.Widget4x1 -> 1 WidgetType.Widget4x2 -> 2 @@ -372,6 +402,7 @@ class WeatherWidgetPreferenceFragment : BaseWeatherWidgetPreferenceFragment() { 96f * when (mWidgetType) { WidgetType.Unknown -> 4 WidgetType.Widget1x1 -> 1 + WidgetType.Widget1x1Custom -> 1 WidgetType.Widget2x2 -> 4 /* 2 is too small */ WidgetType.Widget4x1 -> 4 WidgetType.Widget4x2 -> 4 @@ -630,6 +661,9 @@ class WeatherWidgetPreferenceFragment : BaseWeatherWidgetPreferenceFragment() { if (mWidgetType == WidgetType.Widget4x2Graph) { WidgetUtils.setWidgetGraphType(mAppWidgetId, graphTypePref.value.toInt()) } + if (mWidgetType == WidgetType.Widget1x1Custom) { + WidgetUtils.setWidgetDetailsType(mAppWidgetId, detailsTypePref.value.toInt()) + } super.finalizeWidgetUpdate() } diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WidgetPreferenceKeys.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WidgetPreferenceKeys.kt index 8f13c894..cb28e20f 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WidgetPreferenceKeys.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/WidgetPreferenceKeys.kt @@ -22,6 +22,7 @@ internal const val KEY_FORECAST = "key_forecast" internal const val KEY_FORECASTOPTION = "key_fcastoption" internal const val KEY_TAP2SWITCH = "key_tap2switch" internal const val KEY_GRAPHTYPEOPTION = "key_graphtypeoption" +internal const val KEY_WEATHERDETAILSTYPEOPTION = "key_weatherdetailstypeoption" internal const val KEY_CATCUSTOMSIZE = "key_custom_size" internal const val KEY_TEXTSIZE = "key_textsize" diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget1x1CustomCreator.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget1x1CustomCreator.kt new file mode 100644 index 00000000..172d47f2 --- /dev/null +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/remoteviews/WeatherWidget1x1CustomCreator.kt @@ -0,0 +1,359 @@ +package com.thewizrd.simpleweather.widgets.remoteviews + +import android.appwidget.AppWidgetManager +import android.content.Context +import android.os.Bundle +import android.text.style.TextAppearanceSpan +import android.util.TypedValue +import android.view.View +import android.widget.RemoteViews +import com.thewizrd.common.controls.DetailItemViewModel +import com.thewizrd.common.controls.WeatherDetailsType +import com.thewizrd.common.controls.WeatherUiModel +import com.thewizrd.common.helpers.ColorsUtils +import com.thewizrd.common.utils.ImageUtils +import com.thewizrd.shared_resources.icons.WeatherIcons +import com.thewizrd.shared_resources.locationdata.LocationData +import com.thewizrd.shared_resources.sharedDeps +import com.thewizrd.shared_resources.utils.ContextUtils.dpToPx +import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride +import com.thewizrd.shared_resources.utils.TextUtils.applySpan +import com.thewizrd.shared_resources.weatherdata.model.UV +import com.thewizrd.simpleweather.R +import com.thewizrd.simpleweather.widgets.WeatherWidgetProvider1x1Custom +import com.thewizrd.simpleweather.widgets.WidgetProviderInfo +import com.thewizrd.simpleweather.widgets.WidgetUtils +import com.thewizrd.simpleweather.widgets.preferences.KEY_BGCOLORCODE +import com.thewizrd.simpleweather.widgets.preferences.KEY_HIDELOCNAME +import com.thewizrd.simpleweather.widgets.preferences.KEY_HIDEREFRESHBTN +import com.thewizrd.simpleweather.widgets.preferences.KEY_HIDESETTINGSBTN +import com.thewizrd.simpleweather.widgets.preferences.KEY_ICONSIZE +import com.thewizrd.simpleweather.widgets.preferences.KEY_TEXTSIZE +import com.thewizrd.simpleweather.widgets.preferences.KEY_TXTCOLORCODE +import com.thewizrd.simpleweather.widgets.preferences.KEY_TXTSHADOW +import com.thewizrd.simpleweather.widgets.preferences.KEY_WEATHERDETAILSTYPEOPTION +import com.thewizrd.shared_resources.R as sharedRes + +class WeatherWidget1x1CustomCreator(context: Context) : WidgetRemoteViewCreator(context) { + private fun generateRemoteViews(): RemoteViews { + return RemoteViews(context.packageName, info.widgetLayoutId) + } + + override val info: WidgetProviderInfo + get() = WeatherWidgetProvider1x1Custom.Info.getInstance() + + override suspend fun buildUpdate( + appWidgetId: Int, + weather: WeatherUiModel, + location: LocationData, + newOptions: Bundle + ): RemoteViews { + return buildLayout(appWidgetId, weather, location, newOptions) + } + + private suspend fun buildLayout( + appWidgetId: Int, + weather: WeatherUiModel, location: LocationData, + newOptions: Bundle + ): RemoteViews { + // Build an update that holds the updated widget contents + val updateViews = generateRemoteViews() + + val backgroundColor = + newOptions.get(KEY_BGCOLORCODE) as? Int ?: WidgetUtils.getBackgroundColor(appWidgetId) + val textColor = + newOptions.get(KEY_TXTCOLORCODE) as? Int ?: WidgetUtils.getTextColor(appWidgetId) + val useTextShadow = + newOptions.get(KEY_TXTSHADOW) as? Boolean ?: WidgetUtils.useTextShadow(appWidgetId) + val viewCtx = context.getThemeContextOverride( + ColorsUtils.isSuperLight(backgroundColor) + ) + val textAppearanceSpan = if (useTextShadow) { + TextAppearanceSpan(viewCtx, sharedRes.style.ShadowText) + } else { + null + } + + val txtSizeMultiplier = + newOptions.get(KEY_TEXTSIZE) as? Float ?: WidgetUtils.getCustomTextSizeMultiplier( + appWidgetId + ) + val icoSizeMultiplier = + newOptions.get(KEY_ICONSIZE) as? Float ?: WidgetUtils.getCustomIconSizeMultiplier( + appWidgetId + ) + + updateViews.setInt(R.id.refresh_button, "setColorFilter", textColor) + updateViews.setInt(R.id.settings_button, "setColorFilter", textColor) + + // original icon size: 24dp + val scaledIconSize = (context.dpToPx(16f) * txtSizeMultiplier).toInt() + + // Refresh icon + updateViews.setImageViewBitmap(R.id.refresh_button, null) + + updateViews.setInt(R.id.refresh_button, "setMaxWidth", scaledIconSize) + updateViews.setInt(R.id.refresh_button, "setMaxHeight", scaledIconSize) + + updateViews.setImageViewResource(R.id.refresh_button, sharedRes.drawable.ic_refresh) + + // Setting icon + updateViews.setImageViewBitmap(R.id.settings_button, null) + + updateViews.setInt(R.id.settings_button, "setMaxWidth", scaledIconSize) + updateViews.setInt(R.id.settings_button, "setMaxHeight", scaledIconSize) + + updateViews.setImageViewResource( + R.id.settings_button, + sharedRes.drawable.ic_outline_settings_24 + ) + + // Location Name + updateViews.setTextViewText( + R.id.location_name, + weather.location?.applySpan(textAppearanceSpan) + ) + updateViews.setTextColor(R.id.location_name, textColor) + + // WeatherDetailsType + val detailsType = + newOptions.getSerializable(KEY_WEATHERDETAILSTYPEOPTION) as? WeatherDetailsType + ?: WidgetUtils.getWidgetDetailsType(appWidgetId) + + var detailItemModel = weather.weatherDetailsMap[detailsType] + val notAvailValue: CharSequence = context.getString(sharedRes.string.weather_notavailable) + + when (detailsType) { + WeatherDetailsType.SUNRISE -> { + if (detailItemModel == null) { + detailItemModel = + DetailItemViewModel(detailsType, weather.sunPhase?.sunrise ?: notAvailValue) + } + } + + WeatherDetailsType.SUNSET -> { + if (detailItemModel == null) { + detailItemModel = + DetailItemViewModel(detailsType, weather.sunPhase?.sunset ?: notAvailValue) + } + } + + WeatherDetailsType.MOONPHASE -> { + if (detailItemModel == null) { + detailItemModel = weather.moonPhase?.moonPhase ?: DetailItemViewModel( + detailsType, + notAvailValue + ) + } + } + + WeatherDetailsType.BEAUFORT -> { + if (detailItemModel == null) { + detailItemModel = weather.beaufort?.beaufort ?: DetailItemViewModel( + detailsType, + notAvailValue + ) + } + } + + WeatherDetailsType.UV -> { + if (detailItemModel == null) { + detailItemModel = + weather.uvIndex?.index?.toFloat()?.let { DetailItemViewModel(UV(it)) } + ?: DetailItemViewModel(detailsType, notAvailValue) + } + } + + WeatherDetailsType.AIRQUALITY -> { + if (detailItemModel == null) { + detailItemModel = weather.airQuality?.airQuality ?: DetailItemViewModel( + detailsType, + notAvailValue + ) + } + } + + WeatherDetailsType.TREEPOLLEN -> { + if (detailItemModel == null) { + detailItemModel = weather.pollen?.let { pollenVM -> + DetailItemViewModel( + WeatherDetailsType.TREEPOLLEN, + pollenVM.treePollenDesc.toString(), + pollenVM.treePollenShortDesc.toString(), + 0 + ) + } + } + } + + WeatherDetailsType.GRASSPOLLEN -> { + if (detailItemModel == null) { + detailItemModel = weather.pollen?.let { pollenVM -> + DetailItemViewModel( + WeatherDetailsType.GRASSPOLLEN, + pollenVM.grassPollenDesc.toString(), + pollenVM.grassPollenShortDesc.toString(), + 0 + ) + } + } + } + + WeatherDetailsType.RAGWEEDPOLLEN -> { + if (detailItemModel == null) { + detailItemModel = weather.pollen?.let { pollenVM -> + DetailItemViewModel( + WeatherDetailsType.RAGWEEDPOLLEN, + pollenVM.ragweedPollenDesc.toString(), + pollenVM.ragweedPollenShortDesc.toString(), + 0 + ) + } + } + } + + else -> { + if (detailItemModel == null) { + detailItemModel = DetailItemViewModel(detailsType, notAvailValue) + } + } + } + + val wim = sharedDeps.weatherIconsManager + // icon size: 36dp + val maxIconSize = context.dpToPx(36f) * icoSizeMultiplier + updateViews.setImageViewBitmap( + R.id.weather_icon, + ImageUtils.rotateBitmap( + ImageUtils.bitmapFromDrawable( + viewCtx, + wim.getWeatherIconResource(detailItemModel?.icon ?: WeatherIcons.NA), + maxIconSize, + maxIconSize + ), + detailItemModel?.iconRotation?.toFloat() ?: 0f + ) + ) + if (wim.isFontIcon) { + updateViews.setInt(R.id.weather_icon, "setColorFilter", textColor) + } else { + updateViews.setInt(R.id.weather_icon, "setColorFilter", 0) + } + updateViews.setContentDescription( + R.id.weather_icon, + detailItemModel?.label + ) + + updateViews.setTextViewText(R.id.condition_title, detailItemModel?.label) + updateViews.setTextViewText(R.id.condition_value, detailItemModel?.shortValue) + + updateViews.setTextColor(R.id.condition_title, textColor) + updateViews.setTextColor(R.id.condition_value, textColor) + + // Visibility + updateViews.setViewVisibility( + R.id.location_name, + if (newOptions.get(KEY_HIDELOCNAME) as? Boolean ?: WidgetUtils.isLocationNameHidden( + appWidgetId + ) + ) View.GONE else View.VISIBLE + ) + updateViews.setViewVisibility( + R.id.settings_button, + if (newOptions.get(KEY_HIDESETTINGSBTN) as? Boolean + ?: WidgetUtils.isSettingsButtonHidden(appWidgetId) + ) View.GONE else View.VISIBLE + ) + updateViews.setViewVisibility( + R.id.refresh_button, + if (newOptions.get(KEY_HIDEREFRESHBTN) as? Boolean ?: WidgetUtils.isRefreshButtonHidden( + appWidgetId + ) + ) View.GONE else View.VISIBLE + ) + + // Resizing + updateViewSizes(updateViews, appWidgetId, newOptions) + + setOnClickIntent(location, updateViews) + setOnSettingsClickIntent(updateViews, location, appWidgetId) + setOnRefreshClickIntent(updateViews, appWidgetId) + + return updateViews + } + + override fun resizeWidget( + info: WidgetProviderInfo, + appWidgetManager: AppWidgetManager, + appWidgetId: Int, + newOptions: Bundle + ) { + val updateViews = generateRemoteViews() + + updateViewSizes(updateViews, appWidgetId, newOptions) + + resizeWidgetBackground(info, appWidgetId, updateViews, newOptions) + + appWidgetManager.partiallyUpdateAppWidget(appWidgetId, updateViews) + } + + private fun updateViewSizes( + updateViews: RemoteViews, + appWidgetId: Int, + newOptions: Bundle + ) { + // Widget dimensions + val minHeight = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT) + val minWidth = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH) + val cellHeight = WidgetUtils.getCellsForSize(minHeight) + val cellWidth = WidgetUtils.getCellsForSize(minWidth) + + val txtSizeMultiplier: Float = + newOptions.get(KEY_TEXTSIZE) as? Float ?: WidgetUtils.getCustomTextSizeMultiplier( + appWidgetId + ) + + if (cellWidth > 1 && cellHeight > 1) { + updateViews.setTextViewTextSize( + R.id.location_name, + TypedValue.COMPLEX_UNIT_SP, + 14f * txtSizeMultiplier + ) + updateViews.setTextViewTextSize( + R.id.condition_title, + TypedValue.COMPLEX_UNIT_SP, + 14f * txtSizeMultiplier + ) + } else { + updateViews.setTextViewTextSize( + R.id.location_name, + TypedValue.COMPLEX_UNIT_SP, + 12f * txtSizeMultiplier + ) + updateViews.setTextViewTextSize( + R.id.condition_title, + TypedValue.COMPLEX_UNIT_SP, + 12f * txtSizeMultiplier + ) + } + if (cellWidth > 2 && cellHeight > 2) { + updateViews.setTextViewTextSize( + R.id.condition_value, + TypedValue.COMPLEX_UNIT_SP, + 24f * txtSizeMultiplier + ) + } else if (cellWidth > 1 && cellHeight > 1) { + updateViews.setTextViewTextSize( + R.id.condition_value, + TypedValue.COMPLEX_UNIT_SP, + 18f * txtSizeMultiplier + ) + } else { + updateViews.setTextViewTextSize( + R.id.condition_value, + TypedValue.COMPLEX_UNIT_SP, + 16f * txtSizeMultiplier + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable-nodpi/appwidget_preview_1x1_custom.png b/app/src/main/res/drawable-nodpi/appwidget_preview_1x1_custom.png new file mode 100644 index 0000000000000000000000000000000000000000..59e3f1f96539c7cda6b1ce7973ee101698d20129 GIT binary patch literal 7683 zcmb_>cUY6%vM-?uQVbT5ZfMerfJkowk)|RbC4dS7(v%W| z8ynoEJ~wD+0EK55sh=+O8|zUY0ROv2dNkDod<)bs^!|F_duOOC{EQ2XhK9ciY@mBD zICpt6?30L9#LD`rg%Il*fPs!|kCjdbtZP2_bC$7zJc#@2Tdkg-nOA|o%ilXIUjBTo z=Z@0L`7122>lbRA4d_!-fft_3!`{+9aG{C$2@2xQ3>g$0S+0fz?5<2fMn)QT4ny)o z=FwpzkWDGu2wS9(q-~5%&HG`= zn{iR$ePeTa%HZlQ%SBmi-;3*T89yu3`Nvig{&`i4o{#gJx*jt>P3h+(3FU}lbyZBF zW4$tHn26E<_BvZyK9_oW)qhi3M^BasX+& zb9a7+_kFWfXOjLP%Qyx4Z~EdtcGfA@KSmzAen{gC9u?w^QzQ`YtX-lySC|MwfQLR{ z-r!9)7iFDw(w9qEE?nHvX0cj!gxve-{xUGL)*NKdFZuy`V9|~dTpwc+ zGh(Q@Dj>iFO@=uog?^K$G`YR(r`o0Y<0C6PAK<{|rPQ;(vtaH_hTYfd$tt0$Zs`3v zZ1Ko|*nd|0p@u$dtwLM(L+Kk`zkVlT&o0V7Wbuz4#6$i{GG<}AYDnGxq)|$b+5uxvC_KA9xDcHobcvfn`EHx%QHJIbEEw!ew<-*VJ&U-iE%($5Rx7Mw3U^)4aqCc$^! zAY+P>M3;p6W*%LQzrKF?(NWHdS4)ZBddQdF;m;W;nLt z%BE#haRijP(qw4pZ@9S1#1?J8IMZRzm}`TPy{9rC(G&?4d_UKS5jYt(c?5a>1kqkv zVEAiW-!yDHdik(f=#j$OE^vMRg10rR>gxOB7r9dhvqH(=a$aQaya0?lX@5OTjJ7fA z5JvOd{3|-1F*oSDe6RN}p}5I+id1(U=&$6T^ha-^>WrMUZ4koK{0GF)u9k6p!IU_n zLX>)hR?o?RLyjBAvd1d-RIWNUk>te2IkhL;f}9qE+AO)}JmW@W;xO+;y;J45{Sq4u zh`;U~W)VI@4nEz-+0p$7-$+p==cylC)L2>2QaF_YZt&O!=z?`4YyXnZo$3tVSyEj7 z3eQ*5L5ru~_MJlOM?@EW{9jqZilU;lr9;O-Vqu?u?&IsCL9iY1LAF{`M~Hq>Y#tSV zY>?N6mms(GQkrUnE+CB6>~QuXdBrRCM+Kg>GV2K!e~dNu-!6Fc&z+fd1?KAd9k z0wRDfF3>JdK7@-dTj}-db0p^c)3tX~v>o)gMHWKYl)YWn*!2QmX?Vs=#ef@r)e5Jis@2-=@)s%p> z3lVGqg_xrL_z$Qz!@hq~JxA>BTKkpKQ-4qS)_f5(@7~e9e#YG0^K^}aywK(<3-%3n zR`rQ~LwMu-hz{;EmV7YpIRu$}08NV0=s>El-yP+bd`37ZgJ*DjOq2wd?#!PGfh!p2 zDHrK}MB-cqo6HN^aX5|XarbdryckD#_#Qymvl8oIs*OiC9Iy-yAZW$wF?oZ64%Agl* z<7HLlgBaPV26Iz`iL*;=TgtZ`=`@UYqCesEykeiFcyaa9}ZpW=B5*h$wp)GAXS{Rs5XA^FSTRrU>T7%UFU8(osy z7;<5>#;Pd^z!YL?(6JkhNQF$P4y@2Sasu555SZE1lul!VBc9QVpITPzT0Sw3ih`=k zQRi~{bOo*fpYh7)EP0&UB{-OmM_|8W&kE021advHm=j8V2fP1W4TfYRIs@8Y;S^qV z#tgzC>JfSdl^@F3bDqa)d;`s_z=Anyh28_K&jaHdWt~4N%#|vr=on0#S(5TF zadvVRbe63(OsKa7NYf4g+5~~Ux0c2w=Y+0PjRNkmu3dIbenm`_{!s(S*GiH_&}oBs zMOG&w3xr*Nb?W+jfCZo1gHivZ`yp{tvD*nVskRtBp`%7Cr4k8u7J z5`TZOM?FSrvHGjwAQP(ZKbYI!JXmmP(K2#0>p`)+m)UjKNOQdQ-_%ydkL~W|r|7hh zKrVTGE47z%t^2=gYPe*Kp*26g8Cy|&tP0&#d=e+Nu0X3UFTbWc+mu{@P}_ZWG| zn7LNh7plTnW&Se++kIlv!c5r1%~_iif)&GNWA$BrnK&`#UIg|Y&XYs1CML40Z7|jP zPL1od>|$YhvtlkB{wQWuWzY#~*3Rn;yWdR_Z>A%rTJcG3GF?nESncATv%yyA(0)Ev zyr&Az8}nK>W9v2k2*0|vqb`~UXq5s9$Tf@QFs|C!=-}+5ol-S>T+6jHD75ha8{<&( zk%o%_tx`rfZMsr<;7qzp>~z!VP$eTDeR$y_ZIw2=U$+RFc8_)q`Nh5oK&G1pT%t?9 zFg4ArYKdcnv^ZLQ!909gvvm8k1lyT)|9T{?#&wViK!yIb+l)euZ%TkOB6R%Nn?Q-+ z^{4I6lj|?Kb5XSF$^u9BQY1J&&>fXtRKMloR9)NV@4sm)y6~HSj4#L2A6;b2KbD*8 zS^uH)2=Bf9ETM?#DraGd^uPW4zV{ReK@lPmn+pnPrhvfHJ6_yC6XAzZq>8wvDG`s& zy0d9W-nF1+CkP)fQC%r7E$nzwc6!`m06o>v>6OgXNask)NARsuq4HUWu#1se+Mt2# zhuJ}NLFCAMhSrZi$`y?i_74xZT9D%+y9Y1K*+4Tqq|f+dit*U{Q9~RbDX&UUkWowN zc7uw*U4e}TUa$=pG;MmE955|y8g#2W&|7NZr^6{>$34uddU8Ari4rHQfSDHTP{ZDW za-O!?eJFhYN5`M!oP%5+kDp}o((o70F4S7DkcUH&{RQTBg+{0mzZ!A=PiX-ch$~9i z)#&|*AMW~3Q+l@zev%^xhq>r1m)yogywC8Z9FFi~$)TojjH)X|Hp0gQI>t&$h275% z^OX{V7TVCR7R(%dO2_KT5~|_~f|mSSyjiq&QKGAzsX8Zb@Yg{zKLwUIZM>EV#r>#E zZl|N{FJT2j>ShdU{jj|Un7A?S?03_t$x`72G&0#k#R~ee+}nzxbLaAQA3VUMdNtn8 zzRz*kOLQS-LTTC>>eGCDf;v0h#4(88<)}IkU4U9W-9mTsWF;70(i8#bP%p}JbB{_g z=ZxZZ$cX!csc~(GEu1E}J8=sF*3ihKoiD3$J!bWdb^hPH;cE z^$8aAEnFEKdKGzS59Z=}{;_h@r^~Loe;a+5&TBz5LI)?jxZ>bCjTv9oo|GV|yi3iZ zRtTc00m!0G7O4{!@O4S`n+=uv@;+(Eumt5+^w4SC@cg5AYaKcGmOU6Df#UJT=%I+s zL)sz>46ZUpxBj*p0&=yV$O-lOzR^|z$5`AtaD5w>JRr)ZXAu4HM1Ar9EQ?@-E4cx+$t4~uR$svjKcrC5Vo3~@K$ZL$mD z;2@~GW$Q|4i}KN@q1{y1t?>t1gK%W4a&kI+X94Hq3C;-!^%e8@6G zG9HfcjrDK%`P*uS+6Z5Hj(^D8r*SkMmz7r)iA|%ox4(oPnzY;|2F*2wrRNQV;vhEH zbcL^d?|L6EvhYUlYLtw}q(n(bToKdRVRRsjXFz&uJF0Y?aA7k9EjDm@`rSlOI9R-~ zacENG>H_K8|Cd3=R zjv@&0vs3DowbGdMfR?(N3;TuJ$sgMDZ}t2G3-sXlOV%V4#!Tq29*qrnERsh#yzREW z#B{TIAGu>fL$>EQGD9qC_jK?}0Oi(!?aFa=EN9V&)T~So;lJEBK3s-x6$45!jq=Ci zjJc7*W^E0%tD4UNSQRM$wGz>esOE&7^XwcKr^iT-zLG z%5CGGh(E}yZTKz4PW#law6Xm*G}hn{wz(Rz5%F!`wJm35r5_z>$XwhX%ZOW28y z4x*)U*Z_}}?E%PvU2L~-5|ocL$oNYLL1{PDNCG%ZIe#pQlVrUuzL4G{fZ9;5BkMNE zFlZ@aH4=A^BO9K-3&cNuc;@Xd(0f(RTjN2Qs@AnRb>co3_}e?qfKJZ?F;{C$r6x_) zkAH|Qknm*%<|{VP?%8(8l#^DMgfKXat0YS2Vp7k$C5PSkL-!!V>il?-h`TsXk!7ic z#O(0>d8UdFffKK0wk%yAKS}v1N4E4`=EVERrftE?!U~iMHd!L>?Ywyjcw%QkEH1O$ z*PU#5{c=$F`aOg2%cBf?(zTUF!&X>MQUq}Qy)OGxi7@(Jfo3O7KzJz6?+i)M3f&y7 z+uAJIUKje5(g7O{DvA>wNVcjnret--)5hNly+Y+ixgLl6T~YLxj5?5peXn4>mxoWI zfa^3*-xfWJ!7$~6Rg_i)V^(i=pwT5wpOb#SOv#3QqRqr7oin=xY@#`>Sy6jTyK46@ z+ECoxA+w5d!wyKHhl|#a+damLzy4`ky?tf_Ro-Cd^vwN3PK5r@m7z~EelEhknO0AH z+INmxZ>pGJjT^hPa9(DXb86}@g-QRS-DS-Ko=yp{qD)5y60W5wt@Kncq--gY`l|$2 zU&Cg8>4cdbO1{-(+^hnAtX(=-{Bhu=#Zn0f7Xc0MzDF&`keeKR?}yjVhS(0gI-^LW z`#LsgY}b=kKpF3?ZuUUXfEluuLahAlYm({8SqWFk%7wv%u?>sZ;7=w*SpD===3#U)fh%Q!qOvSKybZ+0YU?CUNh6%b5+K|Jf}gA*N| zOtbD!z8 z$=DgyGr>1%6^O^kCK@i9Qp1j4kSC$SLy@@@SKxZTKyS09rvQqE0@wxE0GwXKJX_4J zkF<&$+gE63j#e?M8sqBiY7hn;m*G?RY;6~gTc-}m`&CRwQs;MT3zR0~=lbve+6s38 zul8sng5I8{!e0-Vg;^m~FoO-mQX{AFxiQVrpU2a)Q`7di!B7pS;N~JiLrEB_h{^>Z zAdh%i<%lbU6{J9eV8zns-+3C+9&JTZewZ*L%;w#wLHG%@VmZtogEGR6X+DW`t6t87 zw<5JR`gZv1-WBH4_|R61j?*@3@~fKR?qIoM%%U%1SM5(XjN(pTEQNd>1}!*s zn{zej*S}m+nhM0yVeMQ>x1f1*(knDRp2t#8PEYdjgKjjt)UeVlO&3n1{c56c-Zdf& z>>GP_XH}U-Z-5#TU}U(a)4n_DqjgScD*rKrZjZTE-(ZOws7{*$5dVD;mRj;m%?Ov+ z-Nud#vf!eVdkL!&ekktjUpGnUYza^(hEeMvm1J0d%+2N|cHdJi&=m1Wm>`i5*ZA5d zrJ=D6MULFATEG+NudSWv>p z@7@a4Ixn@Aj}2m~{6&YY#8X7E6~Z%e_J?@={$xY|$I$lSlkPSK`x>3r%#)kK)mO9z- zv^sgmB=eKU`zKBeV@BV^mmN*U@)FR=6ycdKz>#}7S=_TI&`jyEN(RzC{p%ajca}p( z?cIZFt+ATi7Vr(w3)ZI(|$tscPC}+74Z=5@|=_@x9s2gxDp9S3NhH3Hy^2 zo5mBVI+>siJ{QXGma#CsX2VXBSAnUSufYjzoqEK; zW54x15?z+_MjTWvjB;quT#XVz=@g+IPu<^a|LE40H9C0+dp6-`Mi}(339^P(12mtNa`A8Pj=0V0Cv#R;It2MQTY_@Ie_%X<8DcL2b>8fOR`>{9AQ>*ugw2b_I3wRfK8#dY`=k7?BgT&I&0@XK%l zu#2IF7Z;<*igBdM-h z5y{9Fe1piw^%a#XKzDL>H1?$WB>Rb@4Imz{dueL1rMl5ath+$c zTc^xp+-9nM)8I0|OCKt?u1I=*ZzV1r$v`yY=7k@Bx62hQE9%&yG)$YxflB+zXrEVrsaw{8?Gn?wrBRtj+4cZo3$>9iJT7Cx*RmXXgB!Fq^4JeqwPp zP2x9+j=~v;r^)9BF0oQrR(?H#Zlht^RO zI#-FG^uycib;{rQ#F8Co*BW4Zdi-Bs#ir6X_g#7Bh66sOJh?$^_+fE{w|^4}Q?2g1 z{Hk4kAeK5@;SmQ-i7gbwlm_tXdzE-Nq*UQUbYwLBjjw5QIwUb!SL3HRfb{;tkxSN>Dg`M(&TU84-N_O*Sa|Z6{R_NU8o~0 zHFcIh9K>0~epZp0XB&ab_HdkJ$jtgTmniv^j=f&-xi5WB8Fi3L1HNf)P_5_u{C@zL C8sMM+ literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/app_widget_1x1_custom.xml b/app/src/main/res/layout/app_widget_1x1_custom.xml new file mode 100644 index 00000000..d8c49ed5 --- /dev/null +++ b/app/src/main/res/layout/app_widget_1x1_custom.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/app_widget_1x1_custom_preview.xml b/app/src/main/res/layout/app_widget_1x1_custom_preview.xml new file mode 100644 index 00000000..560804f4 --- /dev/null +++ b/app/src/main/res/layout/app_widget_1x1_custom_preview.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/app_widget_1x1_custom_info.xml b/app/src/main/res/xml/app_widget_1x1_custom_info.xml new file mode 100644 index 00000000..b0932cd9 --- /dev/null +++ b/app/src/main/res/xml/app_widget_1x1_custom_info.xml @@ -0,0 +1,16 @@ + + diff --git a/app/src/main/res/xml/pref_widgetconfig.xml b/app/src/main/res/xml/pref_widgetconfig.xml index 5bf8f3ca..0c1076ad 100644 --- a/app/src/main/res/xml/pref_widgetconfig.xml +++ b/app/src/main/res/xml/pref_widgetconfig.xml @@ -16,6 +16,16 @@ android:persistent="false" app:iconSpaceReserved="false" /> + + + app:isPreferenceVisible="false" + tools:isPreferenceVisible="true" /> + app:isPreferenceVisible="false" + tools:isPreferenceVisible="true" /> + app:isPreferenceVisible="false" + tools:isPreferenceVisible="true" /> @@ -121,7 +134,8 @@ android:summary="%s" android:title="@string/pref_title_bgstyle" app:iconSpaceReserved="false" - app:isPreferenceVisible="false" /> + app:isPreferenceVisible="false" + tools:isPreferenceVisible="true" /> @@ -189,7 +203,8 @@ android:summary="%s" android:title="@string/pref_title_widgetgraphtype" app:iconSpaceReserved="false" - app:isPreferenceVisible="false" /> + app:isPreferenceVisible="false" + tools:isPreferenceVisible="true" /> From c3c058c64894ea976b261ed76f530be63055ac25 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Tue, 26 May 2026 18:16:53 -0400 Subject: [PATCH 09/67] radar: add support for WeatherAPI maps --- .../weatherapi/WeatherApiRadarViewProvider.kt | 302 +++++++++++++++++ .../simpleweather/radar/RadarProvider.kt | 55 ++- .../thewizrd/simpleweather/radar/OSMUtils.kt | 12 +- .../weatherapi/WeatherApiRadarViewProvider.kt | 317 ++++++++++++++++++ 4 files changed, 666 insertions(+), 20 deletions(-) create mode 100644 app/src/fullgms/java/com/thewizrd/simpleweather/radar/weatherapi/WeatherApiRadarViewProvider.kt create mode 100644 app/src/nongms/java/com/thewizrd/simpleweather/radar/weatherapi/WeatherApiRadarViewProvider.kt diff --git a/app/src/fullgms/java/com/thewizrd/simpleweather/radar/weatherapi/WeatherApiRadarViewProvider.kt b/app/src/fullgms/java/com/thewizrd/simpleweather/radar/weatherapi/WeatherApiRadarViewProvider.kt new file mode 100644 index 00000000..2604c840 --- /dev/null +++ b/app/src/fullgms/java/com/thewizrd/simpleweather/radar/weatherapi/WeatherApiRadarViewProvider.kt @@ -0,0 +1,302 @@ +package com.thewizrd.simpleweather.radar.weatherapi + +import android.content.Context +import android.os.Build +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.text.format.DateFormat +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.RequiresApi +import androidx.core.view.isEmpty +import com.google.android.gms.maps.GoogleMap +import com.google.android.gms.maps.model.TileOverlay +import com.google.android.gms.maps.model.TileOverlayOptions +import com.google.android.material.slider.Slider +import com.thewizrd.shared_resources.DateTimeConstants +import com.thewizrd.shared_resources.utils.Coordinate +import com.thewizrd.shared_resources.utils.DateTimeUtils +import com.thewizrd.simpleweather.databinding.RadarAnimateContainerBinding +import com.thewizrd.simpleweather.extras.isRadarInteractionEnabled +import com.thewizrd.simpleweather.radar.CachingUrlTileProvider +import com.thewizrd.simpleweather.radar.MapTileRadarViewProvider +import java.time.ZoneOffset +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter +import java.time.temporal.ChronoUnit + +@RequiresApi(value = Build.VERSION_CODES.LOLLIPOP) +class WeatherApiRadarViewProvider(context: Context, rootView: ViewGroup) : + MapTileRadarViewProvider(context, rootView) { + companion object { + private const val DEFAULT_TRANSPARENCY = 0.5f + } + + private val availableRadarFrames: MutableList + private val radarLayers: MutableMap + + private var googleMap: GoogleMap? = null + private var radarContainerBinding: RadarAnimateContainerBinding? = null + + private var animationPosition = 0 + private val mMainHandler: Handler + private var mProcessingFrames: Boolean = false + + init { + availableRadarFrames = ArrayList() + radarLayers = HashMap() + mMainHandler = Handler(Looper.getMainLooper()) + } + + override fun onCreateView(savedInstanceState: Bundle?) { + super.onCreateView(savedInstanceState) + + radarContainerBinding = RadarAnimateContainerBinding.inflate(LayoutInflater.from(context)) + viewContainer.addView(radarContainerBinding!!.root) + + radarContainerBinding!!.playButton.addOnCheckedChangeListener { _, isChecked -> + if (isChecked) { + mMainHandler.post(animationRunnable) + } else { + mMainHandler.removeCallbacks(animationRunnable) + } + } + + radarContainerBinding!!.animationSeekbar.addOnChangeListener(Slider.OnChangeListener { _, value, fromUser -> + if (fromUser) { + mMainHandler.removeCallbacks(animationRunnable) + showFrame(value.toInt()) + } + }) + + radarContainerBinding!!.animationSeekbar.value = 0f + if (radarContainerBinding!!.radarContainer.isEmpty()) { + radarContainerBinding!!.radarContainer.addView(mapView) + } + } + + override fun onPause() { + super.onPause() + // Remove animation callbacks + radarContainerBinding?.playButton?.isChecked = false + } + + override fun onViewCreated(coordinates: Coordinate) { + super.onViewCreated(coordinates) + } + + override fun updateRadarView() { + radarContainerBinding!!.radarToolbar.visibility = + if (interactionsEnabled() && isRadarInteractionEnabled()) View.VISIBLE else View.GONE + mapView.getMapAsync(this) + } + + override fun onDestroyView() { + super.onDestroyView() + this.googleMap = null + availableRadarFrames.clear() + radarLayers.clear() + radarContainerBinding = null + } + + override fun onMapReady(googleMap: GoogleMap) { + super.onMapReady(googleMap) + this.googleMap = googleMap + + getRadarFrames() + } + + private fun getRadarFrames() { + mProcessingFrames = true + + // Remove already added tile overlays + val overlaysToDelete = radarLayers.values.toList() + radarLayers.clear() + for (overlay in overlaysToDelete) { + mMainHandler.post { overlay.remove() } + } + + availableRadarFrames.clear() + animationPosition = 0 + + val now = ZonedDateTime.now(ZoneOffset.UTC) + .truncatedTo(ChronoUnit.HOURS) // 2024-05-05T14:00:00.000Z + val start = now + val end = now.plus(12, ChronoUnit.HOURS) + + var current = start + var nowIndex = -1 + + while (current <= end) { + availableRadarFrames.add(RadarFrame(current)) + + if (current == now) { + nowIndex = availableRadarFrames.size - 1 + } + + current = current.plus(1, ChronoUnit.HOURS) + } + + mProcessingFrames = false + + mMainHandler.post { + if (isViewAlive) { + val lastPastFramePosition = nowIndex + showFrame(lastPastFramePosition) + } + } + } + + private fun addLayer(mapFrame: RadarFrame) { + if (mProcessingFrames) return + + if (!radarLayers.containsKey(mapFrame.timestamp)) { + val overlay = googleMap!!.addTileOverlay( + TileOverlayOptions().tileProvider(WeatherApiTileProvider(context, mapFrame)) + .transparency(1f) + ) + if (overlay != null) { + radarLayers[mapFrame.timestamp] = overlay + } + } + + radarContainerBinding!!.animationSeekbar.stepSize = 1f + radarContainerBinding!!.animationSeekbar.valueFrom = 0f + radarContainerBinding!!.animationSeekbar.valueTo = (availableRadarFrames.size - 1).toFloat() + } + + private fun changeRadarPosition(pos: Int, preloadOnly: Boolean = false) { + if (mProcessingFrames) return + + var position = pos + while (position >= availableRadarFrames.size) { + position -= availableRadarFrames.size + } + while (position < 0) { + position += availableRadarFrames.size + } + + if (availableRadarFrames.isEmpty() || animationPosition >= availableRadarFrames.size || position >= availableRadarFrames.size) { + return + } + + val currentFrame = availableRadarFrames[animationPosition] ?: return + val currentTimeStamp = currentFrame.timestamp + + val nextFrame = availableRadarFrames[position] ?: return + val nextTimeStamp = nextFrame.timestamp + + addLayer(nextFrame) + + if (preloadOnly) { + return + } + + animationPosition = position + + // 0 is opaque; 1 is transparent + if (radarLayers.containsKey(currentTimeStamp)) { + val currentOverlay = radarLayers[currentTimeStamp] + if (currentOverlay != null) { + currentOverlay.transparency = 1f + } + } + val nextOverlay = radarLayers[nextTimeStamp] + if (nextOverlay != null) { + nextOverlay.transparency = DEFAULT_TRANSPARENCY + } + + updateToolbar(position, nextFrame) + } + + private fun updateToolbar( + position: Int, + mapFrame: RadarFrame = availableRadarFrames[position] + ) { + radarContainerBinding!!.animationSeekbar.value = position.toFloat() + + val dateTime = mapFrame.timestamp.withZoneSameInstant(ZoneOffset.systemDefault()) + val fmt = if (DateFormat.is24HourFormat(context)) { + DateTimeUtils.ofPatternForUserLocale( + DateTimeUtils.getBestPatternForSkeleton( + DateTimeConstants.SKELETON_DAYOFWEEK_AND_24HR + ) + ) + } else { + DateTimeUtils.ofPatternForUserLocale(DateTimeConstants.ABBREV_DAYOFWEEK_AND_12HR_MIN_AMPM) + } + radarContainerBinding!!.timestampText.text = dateTime.format(fmt) + } + + /** + * Check availability and show particular frame position from the timestamps list + */ + private fun showFrame(nextPosition: Int) { + if (mProcessingFrames) return + + val preloadingDirection = if (nextPosition - animationPosition > 0) 1 else -1 + + changeRadarPosition(nextPosition) + + // preload next next frame (typically, +1 frame) + // if don't do that, the animation will be blinking at the first loop + changeRadarPosition(nextPosition + preloadingDirection, true) + } + + private val animationRunnable = object : Runnable { + override fun run() { + if (isViewAlive) { + showFrame(animationPosition + 1) + mMainHandler.postDelayed(this, 500) + } else { + mMainHandler.removeCallbacks(this) + } + } + } + + private class WeatherApiTileProvider(context: Context, private val mapFrame: RadarFrame?) : + CachingUrlTileProvider(context, 256, 256) { + private val dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd") + + override fun getTileUrl(x: Int, y: Int, zoom: Int): String? { + if (!checkTileExists(x, y, zoom)) { + return null + } + + if (mapFrame != null) { + val date = mapFrame.timestamp.toLocalDate().format(dateFormatter) + val hour = mapFrame.timestamp.hour + val url = + "https://weathermaps.weatherapi.com/precip/tiles/%s%02d/%d/%d/%d.png".format( + date, + hour, + zoom, + x, + y + ) + return url + } + + return null + } + + /* + * Check that the tile server supports the requested x, y and zoom. + * Complete this stub according to the tile range you support. + * If you support a limited range of tiles at different zoom levels, then you + * need to define the supported x, y range at each zoom level. + */ + private fun checkTileExists(x: Int, y: Int, zoom: Int): Boolean { + val minZoom = MIN_ZOOM_LEVEL + val maxZoom = 6 + + return zoom in minZoom..maxZoom + } + } + + private data class RadarFrame( + val timestamp: ZonedDateTime + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/thewizrd/simpleweather/radar/RadarProvider.kt b/app/src/main/java/com/thewizrd/simpleweather/radar/RadarProvider.kt index d2aa24a4..b0df5d28 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/radar/RadarProvider.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/radar/RadarProvider.kt @@ -11,11 +11,13 @@ import com.thewizrd.shared_resources.controls.ProviderEntry import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.remoteconfig.remoteConfigService import com.thewizrd.shared_resources.weatherdata.WeatherAPI +import com.thewizrd.shared_resources.weatherdata.WeatherAPI.WEATHERAPI import com.thewizrd.simpleweather.radar.eccc.ECCCRadarViewProvider import com.thewizrd.simpleweather.radar.nws.NWSRadarViewProvider import com.thewizrd.simpleweather.radar.openweather.OWMRadarViewProvider import com.thewizrd.simpleweather.radar.rainviewer.RainViewerViewProvider import com.thewizrd.simpleweather.radar.tomorrowio.TomorrowIoRadarViewProvider +import com.thewizrd.simpleweather.radar.weatherapi.WeatherApiRadarViewProvider import com.thewizrd.weather_api.weatherModule object RadarProvider { @@ -26,7 +28,8 @@ object RadarProvider { WeatherAPI.NWS, WeatherAPI.ECCC, WeatherAPI.OPENWEATHERMAP, - WeatherAPI.TOMORROWIO + WeatherAPI.TOMORROWIO, + WeatherAPI.WEATHERAPI ) @Retention(AnnotationRetention.SOURCE) annotation class RadarProviders @@ -70,6 +73,10 @@ object RadarProvider { ProviderEntry( "Tomorrow.io", WeatherAPI.TOMORROWIO, "https://www.tomorrow.io/weather-api/", "https://www.tomorrow.io/weather-api/" + ), + ProviderEntry( + "WeatherAPI.com", WEATHERAPI, + "https://weatherapi.com", "https://weatherapi.com/api" ) ) @@ -77,19 +84,19 @@ object RadarProvider { @RadarProviders fun getRadarProvider(): String { val prefs = appLib.preferences - val provider = prefs.getString(KEY_RADARPROVIDER, WeatherAPI.RAINVIEWER)!! + val provider = prefs.getString(KEY_RADARPROVIDER, WeatherAPI.WEATHERAPI)!! if (provider == WeatherAPI.OPENWEATHERMAP) { val owm = weatherModule.weatherManager.getWeatherProvider(WeatherAPI.OPENWEATHERMAP) // Fallback to default since API KEY is unavailable if (owm.getAPIKey() == null && settingsManager.getAPIKey(WeatherAPI.OPENWEATHERMAP) == null) { - return WeatherAPI.RAINVIEWER + return WeatherAPI.WEATHERAPI } } else if (provider == WeatherAPI.TOMORROWIO) { val tmr = weatherModule.weatherManager.getWeatherProvider(WeatherAPI.TOMORROWIO) // Fallback to default since API KEY is unavailable if (tmr.getAPIKey() == null && settingsManager.getAPIKey(WeatherAPI.TOMORROWIO) == null) { - return WeatherAPI.RAINVIEWER + return WeatherAPI.WEATHERAPI } } @@ -102,18 +109,34 @@ object RadarProvider { val radarProvider = getRadarProvider() val isEnabled = isRadarProviderEnabled(radarProvider) - return if (radarProvider == WeatherAPI.OPENWEATHERMAP && isEnabled) { - OWMRadarViewProvider(context, rootView) - } else if (radarProvider == WeatherAPI.TOMORROWIO && isEnabled) { - TomorrowIoRadarViewProvider(context, rootView) - } else if (radarProvider == WeatherAPI.NWS && isEnabled) { - NWSRadarViewProvider(context, rootView) - } else if (radarProvider == WeatherAPI.ECCC && isEnabled) { - ECCCRadarViewProvider(context, rootView) - } else if (radarProvider == WeatherAPI.RAINVIEWER && isEnabled) { - RainViewerViewProvider(context, rootView) - } else { - EmptyRadarViewProvider(context, rootView) + return when (radarProvider) { + WeatherAPI.OPENWEATHERMAP if isEnabled -> { + OWMRadarViewProvider(context, rootView) + } + + WeatherAPI.TOMORROWIO if isEnabled -> { + TomorrowIoRadarViewProvider(context, rootView) + } + + WeatherAPI.NWS if isEnabled -> { + NWSRadarViewProvider(context, rootView) + } + + WeatherAPI.ECCC if isEnabled -> { + ECCCRadarViewProvider(context, rootView) + } + + WeatherAPI.RAINVIEWER if isEnabled -> { + RainViewerViewProvider(context, rootView) + } + + WeatherAPI.WEATHERAPI if isEnabled -> { + WeatherApiRadarViewProvider(context, rootView) + } + + else -> { + EmptyRadarViewProvider(context, rootView) + } } } diff --git a/app/src/nongms/java/com/thewizrd/simpleweather/radar/OSMUtils.kt b/app/src/nongms/java/com/thewizrd/simpleweather/radar/OSMUtils.kt index d4c9e5ca..bc40717f 100644 --- a/app/src/nongms/java/com/thewizrd/simpleweather/radar/OSMUtils.kt +++ b/app/src/nongms/java/com/thewizrd/simpleweather/radar/OSMUtils.kt @@ -3,6 +3,7 @@ package com.thewizrd.simpleweather.radar import android.content.Context import android.content.pm.PackageInfo import com.thewizrd.shared_resources.Constants +import com.thewizrd.simpleweather.BuildConfig import org.osmdroid.config.Configuration import java.io.File @@ -15,10 +16,13 @@ fun Context.initializeMap() { String.format("v%s", packageInfo.versionName) }.getOrDefault("") - Configuration.getInstance().userAgentValue = - String.format("SimpleWeather (${Constants.SUPPORT_EMAIL_ADDRESS}) %s", version) - Configuration.getInstance().osmdroidTileCache = File(cacheDir, "tiles") - Configuration.getInstance().osmdroidBasePath = File(noBackupFilesDir, "osmdroid") + Configuration.getInstance().run { + userAgentValue = + String.format("SimpleWeather (${Constants.SUPPORT_EMAIL_ADDRESS}) %s", version) + osmdroidTileCache = File(cacheDir, "tiles") + osmdroidBasePath = File(noBackupFilesDir, "osmdroid") + isDebugMapTileDownloader = BuildConfig.DEBUG + } mapInitialized = true } diff --git a/app/src/nongms/java/com/thewizrd/simpleweather/radar/weatherapi/WeatherApiRadarViewProvider.kt b/app/src/nongms/java/com/thewizrd/simpleweather/radar/weatherapi/WeatherApiRadarViewProvider.kt new file mode 100644 index 00000000..152e2e4d --- /dev/null +++ b/app/src/nongms/java/com/thewizrd/simpleweather/radar/weatherapi/WeatherApiRadarViewProvider.kt @@ -0,0 +1,317 @@ +package com.thewizrd.simpleweather.radar.weatherapi + +import android.content.Context +import android.graphics.ColorMatrix +import android.graphics.ColorMatrixColorFilter +import android.os.Build +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.text.format.DateFormat +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.RequiresApi +import androidx.core.view.isEmpty +import com.google.android.material.slider.Slider +import com.thewizrd.shared_resources.DateTimeConstants +import com.thewizrd.shared_resources.utils.Colors +import com.thewizrd.shared_resources.utils.Coordinate +import com.thewizrd.shared_resources.utils.DateTimeUtils +import com.thewizrd.simpleweather.databinding.RadarAnimateContainerBinding +import com.thewizrd.simpleweather.extras.isRadarInteractionEnabled +import com.thewizrd.simpleweather.radar.MapTileRadarViewProvider +import org.osmdroid.tileprovider.MapTileProviderBasic +import org.osmdroid.tileprovider.modules.TileWriter +import org.osmdroid.tileprovider.tilesource.XYTileSource +import org.osmdroid.util.GeoPoint +import org.osmdroid.util.MapTileIndex +import org.osmdroid.views.overlay.Marker +import org.osmdroid.views.overlay.TilesOverlay +import java.time.ZoneOffset +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter +import java.time.temporal.ChronoUnit + +@RequiresApi(value = Build.VERSION_CODES.LOLLIPOP) +class WeatherApiRadarViewProvider(context: Context, rootView: ViewGroup) : + MapTileRadarViewProvider(context, rootView) { + companion object { + private const val DEFAULT_TRANSPARENCY = 0.5f + private val alphaMatrix = ColorMatrix( + floatArrayOf( + 1f, 0f, 0f, 0f, 0f, + 0f, 1f, 0f, 0f, 0f, + 0f, 0f, 1f, 0f, 0f, + 0f, 0f, 0f, DEFAULT_TRANSPARENCY, 0f + ) + ) + } + + private val availableRadarFrames: MutableList + private val radarLayers: MutableMap + + private var radarContainerBinding: RadarAnimateContainerBinding? = null + + private var animationPosition = 0 + private val mMainHandler: Handler + private var mProcessingFrames: Boolean = false + + init { + availableRadarFrames = ArrayList() + radarLayers = HashMap() + mMainHandler = Handler(Looper.getMainLooper()) + } + + override fun onCreateView(savedInstanceState: Bundle?) { + super.onCreateView(savedInstanceState) + + radarContainerBinding = RadarAnimateContainerBinding.inflate(LayoutInflater.from(context)) + viewContainer.addView(radarContainerBinding!!.root) + + radarContainerBinding!!.playButton.addOnCheckedChangeListener { _, isChecked -> + if (isChecked) { + mMainHandler.post(animationRunnable) + } else { + mMainHandler.removeCallbacks(animationRunnable) + } + } + + radarContainerBinding!!.animationSeekbar.addOnChangeListener(Slider.OnChangeListener { _, value, fromUser -> + if (fromUser) { + mMainHandler.removeCallbacks(animationRunnable) + showFrame(value.toInt()) + } + }) + + radarContainerBinding!!.animationSeekbar.value = 0f + if (radarContainerBinding!!.radarContainer.isEmpty()) { + radarContainerBinding!!.radarContainer.addView(mapView) + } + } + + override fun onPause() { + super.onPause() + // Remove animation callbacks + radarContainerBinding?.playButton?.isChecked = false + } + + override fun onViewCreated(coordinates: Coordinate) { + super.onViewCreated(coordinates) + } + + override fun updateRadarView() { + super.updateRadarView() + radarContainerBinding!!.radarToolbar.visibility = + if (interactionsEnabled() && isRadarInteractionEnabled()) View.VISIBLE else View.GONE + } + + override fun onDestroyView() { + super.onDestroyView() + availableRadarFrames.clear() + radarLayers.clear() + radarContainerBinding = null + } + + override fun onMapReady() { + super.onMapReady() + + mapCameraPosition?.let { cameraPosition -> + if (interactionsEnabled()) { + if (locationMarker == null) { + locationMarker = Marker(mapView) + locationMarker.setDefaultIcon() + mapView.overlays.add(locationMarker) + } + locationMarker.position = + GeoPoint(cameraPosition.latitude, cameraPosition.longitude) + } + } + + getRadarFrames() + } + + private fun getRadarFrames() { + mProcessingFrames = true + + availableRadarFrames.clear() + animationPosition = 0 + + val now = ZonedDateTime.now(ZoneOffset.UTC) + .truncatedTo(ChronoUnit.HOURS) // 2024-05-05T14:00:00.000Z + val start = now + val end = now.plus(12, ChronoUnit.HOURS) + + var current = start + var nowIndex = -1 + + while (current <= end) { + availableRadarFrames.add(RadarFrame(current)) + + if (current == now) { + nowIndex = availableRadarFrames.size - 1 + } + + current = current.plus(1, ChronoUnit.HOURS) + } + + mProcessingFrames = false + + mMainHandler.post { + if (isViewAlive) { + val lastPastFramePosition = nowIndex + showFrame(lastPastFramePosition) + } + } + } + + private fun addLayer(mapFrame: RadarFrame) { + if (mProcessingFrames) return + + if (!radarLayers.containsKey(mapFrame.timestamp)) { + val overlay = TilesOverlay( + MapTileProviderBasic(context, WeatherApiTileProvider(mapFrame), TileWriter()), + context, + false, + false + ) + overlay.loadingBackgroundColor = Colors.TRANSPARENT + overlay.loadingLineColor = Colors.TRANSPARENT + overlay.setColorFilter(ColorMatrixColorFilter(alphaMatrix)) + + overlay.isEnabled = false + mapView.overlays.add(overlay) + radarLayers[mapFrame.timestamp] = overlay + } + + radarContainerBinding!!.animationSeekbar.stepSize = 1f + radarContainerBinding!!.animationSeekbar.valueFrom = 0f + radarContainerBinding!!.animationSeekbar.valueTo = (availableRadarFrames.size - 1).toFloat() + } + + private fun changeRadarPosition(pos: Int, preloadOnly: Boolean = false) { + if (mProcessingFrames) return + + var position = pos + while (position >= availableRadarFrames.size) { + position -= availableRadarFrames.size + } + while (position < 0) { + position += availableRadarFrames.size + } + + if (availableRadarFrames.isEmpty() || animationPosition >= availableRadarFrames.size || position >= availableRadarFrames.size) { + return + } + + val currentFrame = availableRadarFrames[animationPosition] ?: return + val currentTimeStamp = currentFrame.timestamp + + val nextFrame = availableRadarFrames[position] ?: return + val nextTimeStamp = nextFrame.timestamp + + addLayer(nextFrame) + + if (preloadOnly) { + return + } + + animationPosition = position + + // 0 is opaque; 1 is transparent + if (radarLayers.containsKey(currentTimeStamp)) { + val currentOverlay = radarLayers[currentTimeStamp] + if (currentOverlay != null) { + currentOverlay.isEnabled = false + } + } + val nextOverlay = radarLayers[nextTimeStamp] + if (nextOverlay != null) { + nextOverlay.isEnabled = true + } + + mapView.postInvalidate() + + updateToolbar(position, nextFrame) + } + + private fun updateToolbar( + position: Int, + mapFrame: RadarFrame = availableRadarFrames[position] + ) { + radarContainerBinding!!.animationSeekbar.value = position.toFloat() + + val dateTime = mapFrame.timestamp.withZoneSameInstant(ZoneOffset.systemDefault()) + val fmt = if (DateFormat.is24HourFormat(context)) { + DateTimeUtils.ofPatternForUserLocale( + DateTimeUtils.getBestPatternForSkeleton( + DateTimeConstants.SKELETON_DAYOFWEEK_AND_24HR + ) + ) + } else { + DateTimeUtils.ofPatternForUserLocale(DateTimeConstants.ABBREV_DAYOFWEEK_AND_12HR_MIN_AMPM) + } + radarContainerBinding!!.timestampText.text = dateTime.format(fmt) + } + + /** + * Check availability and show particular frame position from the timestamps list + */ + private fun showFrame(nextPosition: Int) { + if (mProcessingFrames) return + + val preloadingDirection = if (nextPosition - animationPosition > 0) 1 else -1 + + changeRadarPosition(nextPosition) + + // preload next next frame (typically, +1 frame) + // if don't do that, the animation will be blinking at the first loop + changeRadarPosition(nextPosition + preloadingDirection, true) + } + + private val animationRunnable = object : Runnable { + override fun run() { + if (isViewAlive) { + showFrame(animationPosition + 1) + mMainHandler.postDelayed(this, 500) + } else { + mMainHandler.removeCallbacks(this) + } + } + } + + private class WeatherApiTileProvider(private val mapFrame: RadarFrame?) : XYTileSource( + "WeatherApi", + MIN_ZOOM_LEVEL, + 6, + 256, + "${mapFrame?.timestamp ?: ""}.png", + arrayOf("https://weathermaps.weatherapi.com") + ) { + private val dateFormatter = DateTimeFormatter.ofPattern("yyyyMMdd") + + override fun getTileURLString(pMapTileIndex: Long): String? { + val zoom = MapTileIndex.getZoom(pMapTileIndex) + val x = MapTileIndex.getX(pMapTileIndex) + val y = MapTileIndex.getY(pMapTileIndex) + + if (mapFrame != null) { + val date = mapFrame.timestamp.toLocalDate().format(dateFormatter) + val hour = mapFrame.timestamp.hour + return "https://weathermaps.weatherapi.com/precip/tiles/%s%02d/%d/%d/%d.png".format( + date, + hour, + zoom, + x, + y + ) + } + + return null + } + } + + private data class RadarFrame( + val timestamp: ZonedDateTime + ) +} \ No newline at end of file From 71f90f0ab8c0890f54ef30ddc1f6709a4aebaa86 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Tue, 26 May 2026 18:57:57 -0400 Subject: [PATCH 10/67] radar: enable interactions for all --- .../fullgms/java/com/thewizrd/simpleweather/extras/Extras.kt | 4 ++-- .../radar/tomorrowio/TomorrowIoRadarViewProvider.kt | 3 ++- .../radar/tomorrowio/TomorrowIoRadarViewProvider.kt | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/fullgms/java/com/thewizrd/simpleweather/extras/Extras.kt b/app/src/fullgms/java/com/thewizrd/simpleweather/extras/Extras.kt index d03f0307..cbb2363d 100644 --- a/app/src/fullgms/java/com/thewizrd/simpleweather/extras/Extras.kt +++ b/app/src/fullgms/java/com/thewizrd/simpleweather/extras/Extras.kt @@ -15,7 +15,6 @@ import com.google.android.play.core.splitcompat.SplitCompat import com.google.firebase.Firebase import com.google.firebase.installations.installations import com.thewizrd.extras.extrasModule -import com.thewizrd.extras.R as extrasRes import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.store.PlayStoreUtils import com.thewizrd.simpleweather.App @@ -33,6 +32,7 @@ import com.thewizrd.simpleweather.utils.NavigationUtils.safeNavigate import kotlinx.coroutines.launch import kotlinx.coroutines.tasks.await import timber.log.Timber +import com.thewizrd.extras.R as extrasRes fun initializeExtras() { extrasModule.initialize() @@ -125,7 +125,7 @@ fun isPremiumSupported(): Boolean { } fun isRadarInteractionEnabled(): Boolean { - return extrasModule.isAtLeastProEnabled() + return true } fun areNotificationExtrasEnabled(): Boolean { diff --git a/app/src/fullgms/java/com/thewizrd/simpleweather/radar/tomorrowio/TomorrowIoRadarViewProvider.kt b/app/src/fullgms/java/com/thewizrd/simpleweather/radar/tomorrowio/TomorrowIoRadarViewProvider.kt index 9cc99b86..d1d2db53 100644 --- a/app/src/fullgms/java/com/thewizrd/simpleweather/radar/tomorrowio/TomorrowIoRadarViewProvider.kt +++ b/app/src/fullgms/java/com/thewizrd/simpleweather/radar/tomorrowio/TomorrowIoRadarViewProvider.kt @@ -20,6 +20,7 @@ import com.thewizrd.shared_resources.utils.Coordinate import com.thewizrd.shared_resources.utils.DateTimeUtils import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.simpleweather.databinding.RadarAnimateContainerBinding +import com.thewizrd.simpleweather.extras.isRadarInteractionEnabled import com.thewizrd.simpleweather.radar.CachingUrlTileProvider import com.thewizrd.simpleweather.radar.MapTileRadarViewProvider import com.thewizrd.weather_api.keys.Keys @@ -88,7 +89,7 @@ class TomorrowIoRadarViewProvider(context: Context, rootView: ViewGroup) : override fun updateRadarView() { radarContainerBinding!!.radarToolbar.visibility = - if (interactionsEnabled()/* && isRadarInteractionEnabled()*/) View.VISIBLE else View.GONE + if (interactionsEnabled() && isRadarInteractionEnabled()) View.VISIBLE else View.GONE mapView.getMapAsync(this) } diff --git a/app/src/nongms/java/com/thewizrd/simpleweather/radar/tomorrowio/TomorrowIoRadarViewProvider.kt b/app/src/nongms/java/com/thewizrd/simpleweather/radar/tomorrowio/TomorrowIoRadarViewProvider.kt index 8790243e..0a2f51f3 100644 --- a/app/src/nongms/java/com/thewizrd/simpleweather/radar/tomorrowio/TomorrowIoRadarViewProvider.kt +++ b/app/src/nongms/java/com/thewizrd/simpleweather/radar/tomorrowio/TomorrowIoRadarViewProvider.kt @@ -18,6 +18,7 @@ import com.thewizrd.shared_resources.utils.Coordinate import com.thewizrd.shared_resources.utils.DateTimeUtils import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.simpleweather.databinding.RadarAnimateContainerBinding +import com.thewizrd.simpleweather.extras.isRadarInteractionEnabled import com.thewizrd.simpleweather.radar.MapTileRadarViewProvider import com.thewizrd.weather_api.keys.Keys import org.osmdroid.tileprovider.MapTileProviderBasic @@ -92,7 +93,7 @@ class TomorrowIoRadarViewProvider(context: Context, rootView: ViewGroup) : override fun updateRadarView() { super.updateRadarView() radarContainerBinding!!.radarToolbar.visibility = - if (interactionsEnabled()/* && isRadarInteractionEnabled()*/) View.VISIBLE else View.GONE + if (interactionsEnabled() && isRadarInteractionEnabled()) View.VISIBLE else View.GONE } override fun onDestroyView() { From 41383a8918f06586f25f8d0013af931983bb9a3d Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Tue, 26 May 2026 19:02:46 -0400 Subject: [PATCH 11/67] WeatherAPI: reorganize providers --- .../weatherdata/WeatherAPI.kt | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/WeatherAPI.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/WeatherAPI.kt index bbfd5c27..81f016d6 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/WeatherAPI.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/WeatherAPI.kt @@ -104,16 +104,16 @@ object WeatherAPI { private val GMSFullAPIs by lazy { listOf( - ProviderEntry( - "HERE Weather", HERE, - "https://www.here.com/en", - "https://developer.here.com/?create=Freemium-Basic&keepState=true&step=account" - ), ProviderEntry( "Apple Weather", APPLE, "https://developer.apple.com/weatherkit/", "https://developer.apple.com/weatherkit/" ), + ProviderEntry( + "HERE Weather", HERE, + "https://www.here.com/en", + "https://developer.here.com/?create=Freemium-Basic&keepState=true&step=account" + ), ProviderEntry( "OpenWeatherMap", OPENWEATHERMAP, "http://www.openweathermap.org", "https://home.openweathermap.org/users/sign_up" @@ -153,11 +153,6 @@ object WeatherAPI { ProviderEntry( "WeatherUnlocked", WEATHERUNLOCKED, "https://developer.weatherunlocked.com/", "https://developer.weatherunlocked.com/" - ), - ProviderEntry( - "Meteomatics", METEOMATICS, - "https://www.meteomatics.com/", - "https://www.meteomatics.com/en/sign-up-weather-api-free-basic-account/" ) ) } @@ -180,6 +175,11 @@ object WeatherAPI { "Environment and Climate Change Canada (ECCC)", ECCC, "https://www.weather.gc.ca/", "https://www.weather.gc.ca/canada_e.html" ), + ProviderEntry( + "HERE Weather", HERE, + "https://www.here.com/en", + "https://developer.here.com/?create=Freemium-Basic&keepState=true&step=account" + ), ProviderEntry( "OpenWeatherMap", OPENWEATHERMAP, "http://www.openweathermap.org", "https://home.openweathermap.org/users/sign_up" @@ -195,11 +195,6 @@ object WeatherAPI { ProviderEntry( "Weatherbit.io", WEATHERBITIO, "https://www.weatherbit.io/", "https://www.weatherbit.io/pricing" - ), - ProviderEntry( - "Meteomatics", METEOMATICS, - "https://www.meteomatics.com/", - "https://www.meteomatics.com/en/sign-up-weather-api-free-basic-account/" ) ) } From 107d08cdd5644293a82acd69f2f8348bfeb09eda Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 30 May 2026 13:37:35 -0400 Subject: [PATCH 12/67] weather: add snow to minutely forecast --- .../controls/ForecastBarGraphView.kt | 17 ++++++++-- .../viewmodels/ForecastGraphViewModel.java | 33 +++++++++++-------- .../weatherdata/model/MinutelyForecast.java | 18 ++++++++++ .../tomorrow/TomorrowIOWeatherProvider.kt | 12 +++---- .../thewizrd/weather_api/tomorrow/Values.java | 11 +++++++ .../weather_api/tomorrow/WeatherData.kt | 14 ++++++-- .../weather_api/weatherbit/WeatherData.kt | 1 + 7 files changed, 82 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/ForecastBarGraphView.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/ForecastBarGraphView.kt index aee3f972..6aed189d 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/ForecastBarGraphView.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/ForecastBarGraphView.kt @@ -14,8 +14,9 @@ import androidx.core.view.forEachIndexed import androidx.core.view.isGone import androidx.core.view.updateLayoutParams import androidx.databinding.DataBindingUtil -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.helpers.RecyclerOnClickListenerInterface +import com.thewizrd.shared_resources.icons.WeatherIcons +import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.ContextUtils.dpToPx import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.controls.graphs.BarGraphData @@ -24,6 +25,7 @@ import com.thewizrd.simpleweather.controls.viewmodels.ForecastType import com.thewizrd.simpleweather.databinding.LayoutBarBinding import com.thewizrd.simpleweather.databinding.LayoutBarViewBinding import kotlin.math.max +import com.thewizrd.shared_resources.R as sharedRes class ForecastBarGraphView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null @@ -157,7 +159,10 @@ class ForecastBarGraphView @JvmOverloads constructor( // Update icon item.barIcon.rotation = data.xIconRotation.toFloat() - item.barIcon.setImageResource(getIconResourceFromForecastType(forecastType)) + item.barIcon.setImageResource( + getIconResourceFromWeatherIcon(data.xWeatherIcon) + ?: getIconResourceFromForecastType(forecastType) + ) if (getChildAt(i) == null) { addView( @@ -216,6 +221,14 @@ class ForecastBarGraphView @JvmOverloads constructor( return heightChanged } + @DrawableRes + private fun getIconResourceFromWeatherIcon(icon: String?): Int? { + return when (icon) { + WeatherIcons.NA, null -> null + else -> sharedDeps.weatherIconsManager.iconProvider.getWeatherIconResource(icon) + } + } + @DrawableRes private fun getIconResourceFromForecastType(forecastType: ForecastType?): Int { return when (forecastType) { diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastGraphViewModel.java b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastGraphViewModel.java index a551bd9a..d80bc420 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastGraphViewModel.java +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastGraphViewModel.java @@ -7,6 +7,7 @@ import androidx.core.content.ContextCompat; import com.thewizrd.shared_resources.DateTimeConstants; +import com.thewizrd.shared_resources.icons.WeatherIcons; import com.thewizrd.shared_resources.preferences.SettingsManager; import com.thewizrd.shared_resources.utils.Colors; import com.thewizrd.shared_resources.utils.ConversionMethods; @@ -238,7 +239,7 @@ private void addEntryData(BaseForecast forecast, LineDataSeries series, @NonNull } private void addMinutelyEntryData(@NonNull MinutelyForecast forecast, LineDataSeries series) { - if (forecast.getRainMm() != null && forecast.getRainMm() >= 0) { + if ((forecast.getRainMm() != null && forecast.getRainMm() >= 0) || (forecast.getSnowMm() != null && forecast.getSnowMm() >= 0)) { final DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance(LocaleUtils.getLocale()); df.applyPattern("0.##"); @@ -253,13 +254,17 @@ private void addMinutelyEntryData(@NonNull MinutelyForecast forecast, LineDataSe final String unit = settingsMgr.getPrecipitationUnit(); float precipValue; + float rainMm = forecast.getRainMm() != null ? forecast.getRainMm() : 0f; + float snowMm = forecast.getSnowMm() != null ? forecast.getSnowMm() : 0f; + boolean isSnow = snowMm > rainMm; + switch (unit) { case Units.INCHES: default: - precipValue = ConversionMethods.mmToIn(forecast.getRainMm()); + precipValue = ConversionMethods.mmToIn(isSnow ? snowMm : rainMm); break; case Units.MILLIMETERS: - precipValue = forecast.getRainMm(); + precipValue = isSnow ? snowMm : rainMm; break; } @@ -508,7 +513,7 @@ private void addEntryData(@NonNull BaseForecast forecast, @NonNull BarGraphDataS } private void addMinutelyEntryData(@NonNull MinutelyForecast forecast, BarGraphDataSet dataSet) { - if (forecast.getRainMm() != null && forecast.getRainMm() >= 0) { + if ((forecast.getRainMm() != null && forecast.getRainMm() >= 0) || (forecast.getSnowMm() != null && forecast.getSnowMm() >= 0)) { final DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance(LocaleUtils.getLocale()); df.applyPattern("0.##"); @@ -523,18 +528,18 @@ private void addMinutelyEntryData(@NonNull MinutelyForecast forecast, BarGraphDa final String unit = settingsMgr.getPrecipitationUnit(); float precipValue; - switch (unit) { - case Units.INCHES: - default: - precipValue = ConversionMethods.mmToIn(forecast.getRainMm()); - break; - case Units.MILLIMETERS: - precipValue = forecast.getRainMm(); - break; - } + float rainMm = forecast.getRainMm() != null ? forecast.getRainMm() : 0f; + float snowMm = forecast.getSnowMm() != null ? forecast.getSnowMm() : 0f; + boolean isSnow = snowMm > rainMm; + + precipValue = switch (unit) { + default -> ConversionMethods.mmToIn(isSnow ? snowMm : rainMm); + case Units.MILLIMETERS -> isSnow ? snowMm : rainMm; + }; final BarGraphEntry entry = new BarGraphEntry(date, new YEntryData(precipValue, String.format(LocaleUtils.getLocale(), "%s", df.format(precipValue)))); - entry.setFillColor(Colors.DEEPSKYBLUE); + entry.setXWeatherIcon(isSnow ? WeatherIcons.SNOWFLAKE_COLD : WeatherIcons.RAINDROP); + entry.setFillColor(isSnow ? Colors.SKYBLUE : Colors.DEEPSKYBLUE); dataSet.addEntry(entry); } } diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/model/MinutelyForecast.java b/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/model/MinutelyForecast.java index 9d6b6fa9..f60c5ebd 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/model/MinutelyForecast.java +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/model/MinutelyForecast.java @@ -24,6 +24,9 @@ public class MinutelyForecast extends CustomJsonObject { @Json(name = "rain_mm") private Float rainMm; + @Json(name = "snow_mm") + private Float snowMm; + public ZonedDateTime getDate() { return date; } @@ -40,6 +43,14 @@ public void setRainMm(Float rainMm) { this.rainMm = rainMm; } + public Float getSnowMm() { + return snowMm; + } + + public void setSnowMm(Float snowMm) { + this.snowMm = snowMm; + } + @Override public void fromJson(@NonNull JsonReader extReader) { try { @@ -77,6 +88,9 @@ public void fromJson(@NonNull JsonReader extReader) { case "rain_mm": this.rainMm = NumberUtils.tryParseFloat(reader.nextString()); break; + case "snow_mm": + this.snowMm = NumberUtils.tryParseFloat(reader.nextString()); + break; default: reader.skipValue(); break; @@ -104,6 +118,10 @@ public void toJson(@NonNull JsonWriter writer) { writer.name("rain_mm"); writer.value(rainMm); + // "snow_mm" : "" + writer.name("snow_mm"); + writer.value(snowMm); + // } writer.endObject(); } catch (IOException e) { diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt index 15e31d84..15cf32fe 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt @@ -189,7 +189,7 @@ class TomorrowIOWeatherProvider : WeatherProviderImpl(), PollenProvider { .appendQueryParameter("location", query) .appendQueryParameter( "fields", - "temperature,temperatureApparent,temperatureMin,temperatureMax,dewPoint,humidity,windSpeed,windDirection,windGust,pressureSeaLevel,precipitationIntensity,precipitationProbability,snowAccumulation,sunriseTime,sunsetTime,visibility,cloudCover,moonPhase,weatherCode,weatherCodeFullDay,weatherCodeDay,weatherCodeNight,treeIndex,grassIndex,weedIndex,epaIndex,particulateMatter25,particulateMatter10,pollutantO3,pollutantNO2,pollutantCO,pollutantSO2" + "temperature,temperatureApparent,temperatureMin,temperatureMax,dewPoint,humidity,windSpeed,windDirection,windGust,pressureSeaLevel,precipitationIntensity,precipitationProbability,precipitationType,snowAccumulation,sunriseTime,sunsetTime,visibility,cloudCover,moonPhase,weatherCode,weatherCodeFullDay,weatherCodeDay,weatherCodeNight,treeIndex,grassIndex,weedIndex,epaIndex,particulateMatter25,particulateMatter10,pollutantO3,pollutantNO2,pollutantCO,pollutantSO2" ) .appendQueryParameter("timesteps", "current,1h,1d") .appendQueryParameter("units", "metric") @@ -207,7 +207,7 @@ class TomorrowIOWeatherProvider : WeatherProviderImpl(), PollenProvider { .appendQueryParameter("location", query) .appendQueryParameter( "fields", - "precipitationIntensity,precipitationProbability" + "precipitationIntensity,precipitationProbability,precipitationType" ) .appendQueryParameter("timesteps", "1m") .appendQueryParameter("units", "metric") @@ -258,8 +258,8 @@ class TomorrowIOWeatherProvider : WeatherProviderImpl(), PollenProvider { runCatching { minutelyResponse = client.newCall(minutelyRequest).await() - checkForErrors(minutelyResponse!!) - minutelyResponse!!.getStream().use { + checkForErrors(minutelyResponse) + minutelyResponse.getStream().use { minutelyRoot = JSONParser.deserializer(it, Rootobject::class.java) } @@ -267,8 +267,8 @@ class TomorrowIOWeatherProvider : WeatherProviderImpl(), PollenProvider { runCatching { alertsResponse = client.newCall(alertsRequest).await() - checkForErrors(alertsResponse!!) - alertsResponse!!.getStream().use { + checkForErrors(alertsResponse) + alertsResponse.getStream().use { alertsRoot = JSONParser.deserializer( it, AlertsRootobject::class.java diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/Values.java b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/Values.java index 106f5ec7..00887472 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/Values.java +++ b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/Values.java @@ -21,6 +21,9 @@ public class Values { @Json(name = "precipitationIntensity") private Float precipitationIntensity; + @Json(name = "precipitationType") + private Integer precipitationType; + @Json(name = "temperatureApparent") private Float temperatureApparent; @@ -142,6 +145,14 @@ public Float getPrecipitationIntensity() { return precipitationIntensity; } + public Integer getPrecipitationType() { + return precipitationType; + } + + public void setPrecipitationType(Integer precipitationType) { + this.precipitationType = precipitationType; + } + public void setTemperatureApparent(Float temperatureApparent) { this.temperatureApparent = temperatureApparent; } diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/WeatherData.kt index c1efeb52..c8dd8f1f 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/WeatherData.kt @@ -1,6 +1,7 @@ package com.thewizrd.weather_api.tomorrow import android.annotation.SuppressLint +import com.thewizrd.shared_resources.R import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.AirQualityUtils.AQICO import com.thewizrd.shared_resources.utils.AirQualityUtils.AQINO2 @@ -27,7 +28,6 @@ import com.thewizrd.shared_resources.weatherdata.model.Pollen import com.thewizrd.shared_resources.weatherdata.model.Precipitation import com.thewizrd.shared_resources.weatherdata.model.TextForecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.weatherModule import java.time.LocalDateTime import java.time.ZoneOffset @@ -281,7 +281,17 @@ fun createHourlyForecast(item: IntervalsItem): HourlyForecast { fun createMinutelyForecast(item: IntervalsItem): MinutelyForecast { return MinutelyForecast().apply { date = ZonedDateTime.parse(item.startTime).withZoneSameInstant(ZoneOffset.UTC) - rainMm = item.values.precipitationIntensity + /** + * 0: No precipitation + * 1: Rain + * 2: Snow + * 3: Freezing Rain + * 4: Ice Pellets / Sleet + */ + when (item.values.precipitationType) { + 2 -> snowMm = item.values.precipitationIntensity + else -> rainMm = item.values.precipitationIntensity + } } } diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherbit/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherbit/WeatherData.kt index 804367d4..c333581e 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherbit/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherbit/WeatherData.kt @@ -233,6 +233,7 @@ fun createMinutelyForecast(item: MinutelyItem): MinutelyForecast { return MinutelyForecast().apply { date = ZonedDateTime.ofInstant(Instant.ofEpochSecond(item.ts!!.toLong()), ZoneOffset.UTC) rainMm = item.precip + snowMm = item.snow } } From 672a0c962a673ee16e13e113fcdaefaf8923cc08 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 30 May 2026 13:38:17 -0400 Subject: [PATCH 13/67] GoogleWeather: add minutely and alerts support --- .../google/weather/AlertsResponse.kt | 99 +++++++++++++ .../google/weather/GoogleWeatherProvider.kt | 135 +++++++++++++++++- .../google/weather/MinutelyResponse.kt | 72 ++++++++++ .../google/weather/WeatherAlerts.kt | 56 ++++++++ .../weather_api/google/weather/WeatherData.kt | 23 ++- 5 files changed, 380 insertions(+), 5 deletions(-) create mode 100644 weather-api/src/main/java/com/thewizrd/weather_api/google/weather/AlertsResponse.kt create mode 100644 weather-api/src/main/java/com/thewizrd/weather_api/google/weather/MinutelyResponse.kt create mode 100644 weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherAlerts.kt diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/AlertsResponse.kt b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/AlertsResponse.kt new file mode 100644 index 00000000..1d36533e --- /dev/null +++ b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/AlertsResponse.kt @@ -0,0 +1,99 @@ +package com.thewizrd.weather_api.google.weather + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class AlertsResponse( + + @Json(name = "regionCode") + var regionCode: String? = null, + + @Json(name = "weatherAlerts") + var weatherAlerts: List? = null, + + @Json(name = "nextPageToken") + var nextPageToken: String? = null +) + +@JsonClass(generateAdapter = true) +data class AlertTitle( + + @Json(name = "text") + var text: String? = null, + + @Json(name = "languageCode") + var languageCode: String? = null +) + +@JsonClass(generateAdapter = true) +data class PublicAlerts( + + @Json(name = "alertId") + var alertId: String? = null, + + @Json(name = "alertTitle") + var alertTitle: AlertTitle? = null, + + @Json(name = "eventType") + var eventType: String? = null, + + @Json(name = "areaName") + var areaName: String? = null, + + @Json(name = "instruction") + var instruction: List? = null, + + @Json(name = "safetyRecommendations") + var safetyRecommendations: List? = null, + + @Json(name = "timezoneOffset") + var timezoneOffset: String? = null, + + @Json(name = "startTime") + var startTime: String? = null, + + @Json(name = "expirationTime") + var expirationTime: String? = null, + + @Json(name = "dataSource") + var dataSource: DataSource? = null, + + @Json(name = "polygon") + var polygon: String? = null, + + @Json(name = "description") + var description: String? = null, + + @Json(name = "severity") + var severity: String? = null, + + @Json(name = "certainty") + var certainty: String? = null, + + @Json(name = "urgency") + var urgency: String? = null +) + +@JsonClass(generateAdapter = true) +data class DataSource( + + @Json(name = "authorityUri") + var authorityUri: String? = null, + + @Json(name = "name") + var name: String? = null, + + @Json(name = "publisher") + var publisher: String? = null +) + +@JsonClass(generateAdapter = true) +data class SafetyRecommendationsItem( + + @Json(name = "directive") + var directive: String? = null, + + @Json(name = "subtext") + var subtext: String? = null +) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/GoogleWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/GoogleWeatherProvider.kt index ce91f6a2..ce44ace5 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/GoogleWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/GoogleWeatherProvider.kt @@ -49,6 +49,8 @@ class GoogleWeatherProvider : WeatherProviderImpl() { private const val CONDITIONS_PATH = "currentConditions:lookup" private const val FORECAST_PATH = "forecast/days:lookup" private const val HOURLY_FORECAST_PATH = "forecast/hours:lookup" + private const val MINUTELY_FORECAST_PATH = "forecast/minutes:lookup" + private const val PUBLIC_ALERTS_PATH = "publicAlerts:lookup" } init { @@ -87,6 +89,10 @@ class GoogleWeatherProvider : WeatherProviderImpl() { return AuthType.APIKEY } + override fun needsExternalAlertData(): Boolean { + return false + } + @Throws(WeatherException::class) override suspend fun isKeyValid(key: String?): Boolean = withContext(Dispatchers.IO) { if (key.isNullOrBlank()) { @@ -226,6 +232,36 @@ class GoogleWeatherProvider : WeatherProviderImpl() { .addGoogleAuth(context) .build() + val minutelyRequestUri = BASE_URL.toUri().buildUpon() + .appendEncodedPath(MINUTELY_FORECAST_PATH) + .appendQueryParameter("location.latitude", df.format(location.latitude)) + .appendQueryParameter("location.longitude", df.format(location.longitude)) + .appendQueryParameter("units_system", "METRIC") + .appendQueryParameter("key", key) + .build() + + val minutelyRequest = Request.Builder() + .cacheRequestIfNeeded(isKeyRequired(), 1, TimeUnit.HOURS) + .url(minutelyRequestUri.toString()) + .addUserAgent(context) + .addGoogleAuth(context) + .build() + + val alertRequestUri = BASE_URL.toUri().buildUpon() + .appendEncodedPath(PUBLIC_ALERTS_PATH) + .appendQueryParameter("location.latitude", df.format(location.latitude)) + .appendQueryParameter("location.longitude", df.format(location.longitude)) + .appendQueryParameter("languageCode", locale) + .appendQueryParameter("key", key) + .build() + + val alertRequest = Request.Builder() + .cacheRequestIfNeeded(isKeyRequired(), 1, TimeUnit.HOURS) + .url(alertRequestUri.toString()) + .addUserAgent(context) + .addGoogleAuth(context) + .build() + // Connect to webstream conditionResponse = client.newCall(conditionRequest).await() checkForErrors(conditionResponse) @@ -238,8 +274,16 @@ class GoogleWeatherProvider : WeatherProviderImpl() { val dailyData = getDailyForecasts(client, dailyRequest) val hourlyData = getHourlyForecasts(client, hourlyRequest) - - weather = createWeatherData(conditionData, dailyData, hourlyData) + val minutelyData = getMinutelyForecasts(client, minutelyRequest) + val alertData = getPublicAlerts(client, alertRequest) + + weather = createWeatherData( + conditionData, + dailyData, + hourlyData, + minutely = minutelyData, + alerts = alertData + ) } catch (ex: Exception) { weather = null if (ex is IOException) { @@ -343,6 +387,86 @@ class GoogleWeatherProvider : WeatherProviderImpl() { return hourlyData } + private suspend fun getMinutelyForecasts( + client: OkHttpClient, + minutelyRequest: Request + ): MinutelyResponse { + val minutelyData = MinutelyResponse() + val minutelySegments = mutableListOf() + + do { + val request = if (minutelyData.nextPageToken != null) { + val newUrl = minutelyRequest.url.newBuilder() + .setQueryParameter("pageToken", minutelyData.nextPageToken) + .build() + + minutelyRequest.newBuilder() + .url(newUrl) + .build() + } else { + minutelyRequest + } + + val minutelyResponse = client.newCall(request).await() + checkForErrors(minutelyResponse) + val minutelyResponseData = minutelyResponse.use { r -> + r.getStream().use { s -> + JSONParser.deserializer(s, MinutelyResponse::class.java) + } + } + + minutelyData.overallPredictionTimeframe = minutelyData.overallPredictionTimeframe + ?: minutelyResponseData?.overallPredictionTimeframe + minutelyData.timeZone = minutelyData.timeZone ?: minutelyResponseData?.timeZone + minutelyData.nextPageToken = minutelyResponseData?.nextPageToken + + minutelyResponseData?.segments?.run { minutelySegments.addAll(this) } + } while (!minutelyData.nextPageToken.isNullOrEmpty()) + + minutelyData.segments = minutelySegments + + return minutelyData + } + + private suspend fun getPublicAlerts( + client: OkHttpClient, + alertsRequest: Request + ): AlertsResponse { + val alertsData = AlertsResponse() + val weatherAlerts = mutableListOf() + + do { + val request = if (alertsData.nextPageToken != null) { + val newUrl = alertsRequest.url.newBuilder() + .setQueryParameter("pageToken", alertsData.nextPageToken) + .build() + + alertsRequest.newBuilder() + .url(newUrl) + .build() + } else { + alertsRequest + } + + val alertsResponse = client.newCall(request).await() + checkForErrors(alertsResponse) + val alertsResponseData = alertsResponse.use { r -> + r.getStream().use { s -> + JSONParser.deserializer(s, AlertsResponse::class.java) + } + } + + alertsData.regionCode = alertsData.regionCode ?: alertsResponseData?.regionCode + alertsData.nextPageToken = alertsResponseData?.nextPageToken + + alertsResponseData?.weatherAlerts?.run { weatherAlerts.addAll(this) } + } while (!alertsData.nextPageToken.isNullOrEmpty()) + + alertsData.weatherAlerts = weatherAlerts + + return alertsData + } + override suspend fun updateWeatherData(location: LocationData, weather: Weather) { super.updateWeatherData(location, weather) @@ -359,6 +483,13 @@ class GoogleWeatherProvider : WeatherProviderImpl() { weather.hrForecast?.forEach { hr_forecast -> hr_forecast.date = hr_forecast.date.withZoneSameInstant(offset) } + weather.minForecast?.forEach { min_forecast -> + min_forecast.date = min_forecast.date.withZoneSameInstant(offset) + } + weather.weatherAlerts?.forEach { alert -> + alert.date = alert.date.withZoneSameInstant(offset) + alert.expiresDate = alert.expiresDate.withZoneSameInstant(offset) + } if (weather.astronomy != null) { // The time of day is set to max if the sun never sets/rises and diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/MinutelyResponse.kt b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/MinutelyResponse.kt new file mode 100644 index 00000000..9d28d1c9 --- /dev/null +++ b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/MinutelyResponse.kt @@ -0,0 +1,72 @@ +package com.thewizrd.weather_api.google.weather + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class MinutelyResponse( + + @Json(name = "timeZone") + var timeZone: TimeZone? = null, + + @Json(name = "overallPredictionTimeframe") + var overallPredictionTimeframe: OverallPredictionTimeframe? = null, + + @Json(name = "segments") + var segments: List? = null, + + @Json(name = "nextPageToken") + var nextPageToken: String? = null +) + +@JsonClass(generateAdapter = true) +data class OverallPredictionTimeframe( + + @Json(name = "startTime") + var startTime: String? = null, + + @Json(name = "endTime") + var endTime: String? = null +) + +@JsonClass(generateAdapter = true) +data class SnowfallAmount( + + @Json(name = "unit") + var unit: String? = null, + + @Json(name = "quantity") + var quantity: Float? = null +) + +@JsonClass(generateAdapter = true) +data class TimeFrame( + + @Json(name = "startTime") + var startTime: String? = null, + + @Json(name = "endTime") + var endTime: String? = null +) + +@JsonClass(generateAdapter = true) +data class SegmentsItem( + + @Json(name = "intensity") + var intensity: String? = null, + + @Json(name = "snowfallAmount") + var snowfallAmount: SnowfallAmount? = null, + + @Json(name = "probability") + var probability: Int? = null, + + @Json(name = "qpf") + var qpf: Qpf? = null, + + @Json(name = "type") + var type: String? = null, + + @Json(name = "timeFrame") + var timeFrame: TimeFrame? = null +) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherAlerts.kt b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherAlerts.kt new file mode 100644 index 00000000..b3de4d10 --- /dev/null +++ b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherAlerts.kt @@ -0,0 +1,56 @@ +package com.thewizrd.weather_api.google.weather + +import com.thewizrd.shared_resources.weatherdata.model.WeatherAlert +import com.thewizrd.shared_resources.weatherdata.model.WeatherAlertSeverity +import com.thewizrd.shared_resources.weatherdata.model.WeatherAlertType +import java.time.ZonedDateTime + +fun createWeatherAlerts(response: AlertsResponse?): Collection? { + return response?.weatherAlerts?.map { + createWeatherAlert(it) + } +} + +fun createWeatherAlert(alert: PublicAlerts): WeatherAlert { + return WeatherAlert().apply { + title = alert.alertTitle?.text + message = alert.description + attribution = alert.dataSource?.name + date = ZonedDateTime.parse(alert.startTime) + expiresDate = ZonedDateTime.parse(alert.expirationTime) + severity = when (alert.severity) { + "EXTREME" -> WeatherAlertSeverity.EXTREME + "SEVERE" -> WeatherAlertSeverity.SEVERE + "MODERATE" -> WeatherAlertSeverity.MODERATE + "MINOR" -> WeatherAlertSeverity.MINOR + else -> WeatherAlertSeverity.UNKNOWN + } + type = when (alert.eventType) { + "ACID_RAIN", "AVALANCHE", "DROUGHT", + "HUMIDITY", "LANDSLIDE", "MONSOON", "OUTFLOW", "RADIATION", "RAIN_EVENT" -> WeatherAlertType.SPECIALWEATHERALERT + + "BLIZZARD", "BLOWING_SNOW", "COLD", "FREEZING", "FREEZING_AIR_TEMPERATURE", + "FREEZING_DRIZZLE", "FREEZING_RAIN_EVENT", "FROST", "GLAZE", "ICE_STORM", + "LAKE_EFFECT_SNOW", "SNOWSQUALL", "SNOW_EVENT", "WIND_CHILL", "WINTER_STORM" -> WeatherAlertType.WINTERWEATHER + + "BUSHFIRE", "FIRE", "FIRE_WEATHER", "INDUSTRIAL_FIRE", "WILDFIRE" -> WeatherAlertType.FIRE + "COASTAL_FLOOD", "COASTAL_HAZARD", "FLASH_FLOOD", "FLOOD", "MUDDY_FLOOD", "RIVER_FLOODING" -> WeatherAlertType.FLOODWARNING + "DUST_STORM" -> WeatherAlertType.DUSTADVISORY + "AFTERSHOCK", "EARTHQUAKE" -> WeatherAlertType.EARTHQUAKEWARNING + "FOG" -> WeatherAlertType.DENSEFOG + "GALE" -> WeatherAlertType.GALEWARNING + "HEAT" -> WeatherAlertType.HEAT + "HURRICANE", "CYCLONE", "EXTRATROPICAL_CYCLONE", "TROPICAL_CYCLONE", + "TROPICAL_CYCLONE_WARNINGS_AND_WATCHES", "TROPICAL_DISTURBANCE", "TROPICAL_STORM", "TYPHOON" -> WeatherAlertType.HURRICANEWINDWARNING + + "SEVERE_THUNDERSTORM_WARNING", "THUNDER", "THUNDERSTORM", "HAIL" -> WeatherAlertType.SEVERETHUNDERSTORMWARNING + "STORM", "STORM_SURGE" -> WeatherAlertType.STORMWARNING + "TORNADO", "TORNADO_WARNING" -> WeatherAlertType.TORNADOWARNING + "TSUNAMI" -> WeatherAlertType.TSUNAMIWARNING + "VOLCANIC_ASH", "VOLCANIC_ERUPTION" -> WeatherAlertType.VOLCANO + "WIND" -> WeatherAlertType.HIGHWIND + "HAZARDOUS_SEAS", "WIND_WAVE" -> WeatherAlertType.SMALLCRAFT + else -> WeatherAlertType.SPECIALWEATHERALERT + } + } +} \ No newline at end of file diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherData.kt index 288e3319..e870ec3e 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherData.kt @@ -1,5 +1,6 @@ package com.thewizrd.weather_api.google.weather +import com.thewizrd.shared_resources.R import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.ConversionMethods import com.thewizrd.shared_resources.utils.DateTimeUtils @@ -13,20 +14,23 @@ import com.thewizrd.shared_resources.weatherdata.model.Forecast import com.thewizrd.shared_resources.weatherdata.model.ForecastExtras import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.Location +import com.thewizrd.shared_resources.weatherdata.model.MinutelyForecast import com.thewizrd.shared_resources.weatherdata.model.MoonPhase import com.thewizrd.shared_resources.weatherdata.model.MoonPhase.MoonPhaseType import com.thewizrd.shared_resources.weatherdata.model.TextForecast import com.thewizrd.shared_resources.weatherdata.model.UV import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.weatherModule import java.time.LocalDateTime +import java.time.ZoneOffset import java.time.ZonedDateTime fun createWeatherData( current: CurrentResponse, daily: DailyResponse, - hourly: HourlyResponse + hourly: HourlyResponse, + minutely: MinutelyResponse? = null, + alerts: AlertsResponse? = null ): Weather { return Weather().apply { @@ -69,13 +73,18 @@ fun createWeatherData( createHourlyForecast(it) } + minForecast = minutely?.segments?.map { + createMinutelyForecast(it) + } + condition = createCondition(current, todaysForecast?.second, todaysTxtForecast) atmosphere = createAtmosphere(current) astronomy = createAstronomy(todaysForecast?.first) precipitation = createPrecipitation(current) + weatherAlerts = createWeatherAlerts(alerts) ttl = 60 // TODO: TBD - if ((condition!!.highF == null || condition!!.highC == null) && forecast!!.size > 0) { + if ((condition!!.highF == null || condition!!.highC == null) && forecast!!.isNotEmpty()) { condition!!.highF = forecast!![0].highF condition!!.highC = forecast!![0].highC condition!!.lowF = forecast!![0].lowF @@ -290,6 +299,14 @@ fun createHourlyForecast(hour: ForecastHoursItem): HourlyForecast { } } +fun createMinutelyForecast(minute: SegmentsItem): MinutelyForecast { + return MinutelyForecast().apply { + date = ZonedDateTime.parse(minute.timeFrame?.startTime).withZoneSameInstant(ZoneOffset.UTC) + rainMm = minute.qpf?.quantity + snowMm = minute.snowfallAmount?.quantity + } +} + fun createAtmosphere(current: CurrentResponse): Atmosphere { return Atmosphere().apply { current.dewPoint?.degrees?.let { From 0bd2a87d3116859a04ed23889cc82a72ac225bef Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 30 May 2026 13:56:02 -0400 Subject: [PATCH 14/67] weather-api: correct date on alerts --- .../weather_api/here/weather/HEREWeatherProvider.kt | 9 ++------- .../meteofrance/weather/MeteoFranceProvider.kt | 9 ++------- .../weather/onecall/OWMOneCallWeatherProvider.kt | 9 ++------- .../weather_api/tomorrow/TomorrowIOWeatherProvider.kt | 9 ++------- 4 files changed, 8 insertions(+), 28 deletions(-) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/here/weather/HEREWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/here/weather/HEREWeatherProvider.kt index 294cedf8..74c17cf4 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/here/weather/HEREWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/here/weather/HEREWeatherProvider.kt @@ -219,13 +219,8 @@ class HEREWeatherProvider : WeatherProviderImpl() { val offset = location.tzOffset weather.weatherAlerts?.forEach { alert -> - if (alert.date.offset != offset) { - alert.date = alert.date.withZoneSameLocal(offset) - } - - if (alert.expiresDate.offset != offset) { - alert.expiresDate = alert.expiresDate.withZoneSameLocal(offset) - } + alert.date = alert.date.withZoneSameInstant(offset) + alert.expiresDate = alert.expiresDate.withZoneSameInstant(offset) } // Update tz for weather properties diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt index df115798..a1a832bb 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt @@ -272,13 +272,8 @@ class MeteoFranceProvider : WeatherProviderImpl() { if (!weather.weatherAlerts.isNullOrEmpty()) { for (alert in weather.weatherAlerts) { - if (alert.date.offset != offset) { - alert.date = alert.date.withZoneSameLocal(offset) - } - - if (alert.expiresDate.offset != offset) { - alert.expiresDate = alert.expiresDate.withZoneSameLocal(offset) - } + alert.date = alert.date.withZoneSameInstant(offset) + alert.expiresDate = alert.expiresDate.withZoneSameInstant(offset) } } } diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/onecall/OWMOneCallWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/onecall/OWMOneCallWeatherProvider.kt index eaf2f78b..e6228a66 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/onecall/OWMOneCallWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/onecall/OWMOneCallWeatherProvider.kt @@ -296,13 +296,8 @@ class OWMOneCallWeatherProvider : WeatherProviderImpl, AirQualityProvider { if (weather.weatherAlerts?.isNotEmpty() == true) { for (alert in weather.weatherAlerts) { - if (alert.date.offset != offset) { - alert.date = alert.date.withZoneSameLocal(offset) - } - - if (alert.expiresDate.offset != offset) { - alert.expiresDate = alert.expiresDate.withZoneSameLocal(offset) - } + alert.date = alert.date.withZoneSameInstant(offset) + alert.expiresDate = alert.expiresDate.withZoneSameInstant(offset) } } } diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt index 15cf32fe..29d02ebf 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt @@ -466,13 +466,8 @@ class TomorrowIOWeatherProvider : WeatherProviderImpl(), PollenProvider { if (!weather.weatherAlerts.isNullOrEmpty()) { for (alert in weather.weatherAlerts) { - if (alert.date.offset != offset) { - alert.date = alert.date.withZoneSameLocal(offset) - } - - if (alert.expiresDate.offset != offset) { - alert.expiresDate = alert.expiresDate.withZoneSameLocal(offset) - } + alert.date = alert.date.withZoneSameInstant(offset) + alert.expiresDate = alert.expiresDate.withZoneSameInstant(offset) } } } From 532de0b423534b229e7f3d4b877c69e01ab9d110 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sun, 31 May 2026 19:03:22 -0400 Subject: [PATCH 15/67] weather-api: add support for Open-Meteo --- .../thewizrd/simpleweather/test/UnitTests.kt | 11 + .../thewizrd/simpleweather/test/UnitTests.kt | 25 +- app/src/main/res/xml/pref_credits.xml | 8 + .../src/main/res/layout/credit_openmeteo.xml | 25 + .../res/xml/remote_config_defaults.xml | 12 +- .../locationdata/LocationQuery.kt | 8 + .../shared_resources/utils/LocationUtils.kt | 7 + .../weatherdata/WeatherAPI.kt | 37 +- .../main/res/drawable-nodpi/open_meteo.xml | 27 + .../src/main/res/values/strings.xml | 1 + wearapp/src/main/res/xml/pref_credits.xml | 7 + weather-api/build.gradle | 2 + .../weather_api/oauth/OAuthRequest.java | 8 +- .../weather_api/openmeteo/AQIResponse.kt | 121 +++ .../weather_api/openmeteo/ForecastResponse.kt | 415 +++++++++++ .../openmeteo/OpenMeteoWeatherProvider.kt | 692 ++++++++++++++++++ .../weather_api/openmeteo/WeatherData.kt | 326 +++++++++ .../weatherdata/WeatherProviderFactoryImpl.kt | 4 +- .../weatherdata/WeatherProviderImpl.kt | 13 + .../com/thewizrd/weather_api/keys/Keys.java | 4 + 20 files changed, 1730 insertions(+), 23 deletions(-) create mode 100644 common/src/main/res/layout/credit_openmeteo.xml create mode 100644 shared_resources/src/main/res/drawable-nodpi/open_meteo.xml create mode 100644 weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/AQIResponse.kt create mode 100644 weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/ForecastResponse.kt create mode 100644 weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/OpenMeteoWeatherProvider.kt create mode 100644 weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/WeatherData.kt diff --git a/app/src/androidTestFullgms/java/com/thewizrd/simpleweather/test/UnitTests.kt b/app/src/androidTestFullgms/java/com/thewizrd/simpleweather/test/UnitTests.kt index 21c556d0..58b8d04d 100644 --- a/app/src/androidTestFullgms/java/com/thewizrd/simpleweather/test/UnitTests.kt +++ b/app/src/androidTestFullgms/java/com/thewizrd/simpleweather/test/UnitTests.kt @@ -682,6 +682,17 @@ class UnitTests { settingsManager.setPersonalKey(WeatherAPI.GOOGLE, false) } + @Throws(WeatherException::class) + @Test + fun getOpenMeteoWeather() { + runBlocking(Dispatchers.Default) { + val provider = weatherModule.weatherManager.getWeatherProvider(WeatherAPI.OPENMETEO) + val weather = + getWeather(provider, Coordinate(52.52, 13.41)) // ~ Berlin + assertTrue(weather.isValid && WeatherUiModel(weather).isValid) + } + } + @Throws(WeatherException::class) @Test fun getGooglePollen() { diff --git a/app/src/androidTestNongms/java/com/thewizrd/simpleweather/test/UnitTests.kt b/app/src/androidTestNongms/java/com/thewizrd/simpleweather/test/UnitTests.kt index 8fd5a3e8..5663823a 100644 --- a/app/src/androidTestNongms/java/com/thewizrd/simpleweather/test/UnitTests.kt +++ b/app/src/androidTestNongms/java/com/thewizrd/simpleweather/test/UnitTests.kt @@ -12,20 +12,23 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import com.thewizrd.common.CommonModule import com.thewizrd.common.commonModule import com.thewizrd.common.controls.WeatherUiModel -import com.thewizrd.shared_resources.* +import com.thewizrd.shared_resources.AppState +import com.thewizrd.shared_resources.ApplicationLib +import com.thewizrd.shared_resources.SharedModule +import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.exceptions.WeatherException import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.locationdata.WeatherLocationProvider import com.thewizrd.shared_resources.locationdata.toLocationData import com.thewizrd.shared_resources.preferences.SettingsManager +import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Coordinate import com.thewizrd.shared_resources.utils.DateTimeUtils import com.thewizrd.shared_resources.utils.JSONParser import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.shared_resources.weatherdata.WeatherProvider import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.viewmodels.WeatherNowViewModel import com.thewizrd.weather_api.aqicn.AQICNProvider import com.thewizrd.weather_api.google.location.getFromLocationAsync import com.thewizrd.weather_api.google.location.getFromLocationNameAsync @@ -41,7 +44,10 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext import org.junit.After -import org.junit.Assert.* +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -49,7 +55,7 @@ import java.io.IOException import java.time.Duration import java.time.ZonedDateTime import java.time.format.DateTimeFormatter -import java.util.* +import java.util.Locale @RunWith(AndroidJUnit4::class) class UnitTests { @@ -546,4 +552,15 @@ class UnitTests { assertTrue(weather.isValid && WeatherUiModel(weather).isValid) } } + + @Throws(WeatherException::class) + @Test + fun getOpenMeteoWeather() { + runBlocking(Dispatchers.Default) { + val provider = weatherModule.weatherManager.getWeatherProvider(WeatherAPI.OPENMETEO) + val weather = + getWeather(provider, Coordinate(52.52, 13.41)) // ~ Berlin + assertTrue(weather.isValid && WeatherUiModel(weather).isValid) + } + } } \ No newline at end of file diff --git a/app/src/main/res/xml/pref_credits.xml b/app/src/main/res/xml/pref_credits.xml index 9c60f88d..89897671 100644 --- a/app/src/main/res/xml/pref_credits.xml +++ b/app/src/main/res/xml/pref_credits.xml @@ -101,6 +101,14 @@ android:data="https://www.weather.gc.ca/" /> + + + + + + + + + \ No newline at end of file diff --git a/shared_resources/src/fullgms/res/xml/remote_config_defaults.xml b/shared_resources/src/fullgms/res/xml/remote_config_defaults.xml index de85383e..c21573b3 100644 --- a/shared_resources/src/fullgms/res/xml/remote_config_defaults.xml +++ b/shared_resources/src/fullgms/res/xml/remote_config_defaults.xml @@ -180,9 +180,19 @@ } + + open_meteo + + { + "enabled": true, + "locSource": "weatherapi", + "newWeatherSource": "" + } + + default_weather_provider - weatherapi + open_meteo key_imagedb_valid_days diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/locationdata/LocationQuery.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/locationdata/LocationQuery.kt index b92bb200..80195935 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/locationdata/LocationQuery.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/locationdata/LocationQuery.kt @@ -91,6 +91,14 @@ class LocationQuery { df.format(locationLong) ) } + WeatherAPI.OPENMETEO -> { + String.format( + Locale.ROOT, + "latitude=%s&longitude=%s", + df.format(locationLat), + df.format(locationLong) + ) + } else -> { String.format( Locale.ROOT, diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/LocationUtils.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/LocationUtils.kt index 63d85e86..7dde5d0a 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/LocationUtils.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/LocationUtils.kt @@ -35,6 +35,9 @@ object LocationUtils { private val DE_BOUNDING_BOX = BoundingBox(47.2701114, 55.099161, 5.8663153, 15.0419319) + private val CAMS_OPENMETEO_EUROPE_BBOX = + BoundingBox(-25.0, 45.0, 30.0, 72.0) + private val NWS_SUPPORTED_COUNTRIES = setOf("US", "AS", "UM", "GU", "MP", "PR", "VI") private val NWS_SUPPORTED_LOCATIONS = listOf( US_BOUNDING_BOX, @@ -233,6 +236,10 @@ object LocationUtils { } } + fun isCAMSEuroCovered(location: LocationData): Boolean { + return CAMS_OPENMETEO_EUROPE_BBOX.intersects(location.latitude, location.longitude) + } + private data class BoundingBox( val lat_min: Double, val lat_max: Double, diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/WeatherAPI.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/WeatherAPI.kt index 81f016d6..b308af6e 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/WeatherAPI.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/WeatherAPI.kt @@ -25,6 +25,7 @@ object WeatherAPI { const val APPLE = "apple" const val DWD = "dwd" const val ECCC = "eccc" + const val OPENMETEO = "open_meteo" // Location APIs const val ANDROID = "android" @@ -44,7 +45,7 @@ object WeatherAPI { * 2) Add constructor for [Weather] data objects * 3) Update [LocationQuery] (if needed) * 4) Add API to provider list below - * 5) Add API to WeatherProviderManager / [com.thewizrd.weather_api.weatherdata.WeatherProviderFactoryImpl] + * 5) Add API to [com.thewizrd.weather_api.weatherdata.WeatherProviderFactoryImpl] * 6) Add to remote_config_defaults.xml */ @StringDef( @@ -63,7 +64,8 @@ object WeatherAPI { APPLE, DWD, ECCC, - GOOGLE + GOOGLE, + OPENMETEO ) @Retention(AnnotationRetention.SOURCE) annotation class WeatherProviders @@ -110,17 +112,9 @@ object WeatherAPI { "https://developer.apple.com/weatherkit/" ), ProviderEntry( - "HERE Weather", HERE, - "https://www.here.com/en", - "https://developer.here.com/?create=Freemium-Basic&keepState=true&step=account" - ), - ProviderEntry( - "OpenWeatherMap", OPENWEATHERMAP, - "http://www.openweathermap.org", "https://home.openweathermap.org/users/sign_up" - ), - ProviderEntry( - "WeatherAPI.com", WEATHERAPI, - "https://weatherapi.com", "https://weatherapi.com/api" + "Open-Meteo", OPENMETEO, + "https://open-meteo.com/", + "https://open-meteo.com/en/features" ), ProviderEntry( "National Weather Service (United States)", NWS, @@ -142,6 +136,19 @@ object WeatherAPI { "MET Norway", METNO, "https://www.met.no/en", "https://www.met.no/en" ), + ProviderEntry( + "HERE Weather", HERE, + "https://www.here.com/en", + "https://developer.here.com/?create=Freemium-Basic&keepState=true&step=account" + ), + ProviderEntry( + "OpenWeatherMap", OPENWEATHERMAP, + "http://www.openweathermap.org", "https://home.openweathermap.org/users/sign_up" + ), + ProviderEntry( + "WeatherAPI.com", WEATHERAPI, + "https://weatherapi.com", "https://weatherapi.com/api" + ), ProviderEntry( "Tomorrow.io", TOMORROWIO, "https://www.tomorrow.io/weather-api/", "https://www.tomorrow.io/weather-api/" @@ -163,6 +170,10 @@ object WeatherAPI { "MET Norway", METNO, "https://www.met.no/en", "https://www.met.no/en" ), + ProviderEntry( + "Open-Meteo", OPENMETEO, + "https://open-meteo.com/", "https://open-meteo.com/en/features" + ), ProviderEntry( "National Weather Service (United States)", NWS, "https://www.weather.gov", "https://www.weather.gov" diff --git a/shared_resources/src/main/res/drawable-nodpi/open_meteo.xml b/shared_resources/src/main/res/drawable-nodpi/open_meteo.xml new file mode 100644 index 00000000..19dbf9a7 --- /dev/null +++ b/shared_resources/src/main/res/drawable-nodpi/open_meteo.xml @@ -0,0 +1,27 @@ + + + + + diff --git a/shared_resources/src/main/res/values/strings.xml b/shared_resources/src/main/res/values/strings.xml index 51ae180c..9eaaf8c5 100644 --- a/shared_resources/src/main/res/values/strings.xml +++ b/shared_resources/src/main/res/values/strings.xml @@ -19,6 +19,7 @@ Google Bright Sky (DWD) Environment and Climate Change Canada (ECCC) + Open-Meteo RainViewer Current Location Get Started diff --git a/wearapp/src/main/res/xml/pref_credits.xml b/wearapp/src/main/res/xml/pref_credits.xml index 8d5c7a47..cf865827 100644 --- a/wearapp/src/main/res/xml/pref_credits.xml +++ b/wearapp/src/main/res/xml/pref_credits.xml @@ -70,6 +70,13 @@ android:action="android.intent.action.VIEW" android:data="https://www.weather.gc.ca/" /> + + + diff --git a/weather-api/build.gradle b/weather-api/build.gradle index ab044000..378373a5 100644 --- a/weather-api/build.gradle +++ b/weather-api/build.gradle @@ -72,9 +72,11 @@ android { productFlavors { nongms { dimension 'gms' + buildConfigField "boolean", "IS_NONGMS", "true" } fullgms { dimension 'gms' + buildConfigField "boolean", "IS_NONGMS", "false" externalNativeBuild { ndkBuild { arguments "FULL_GMS_VERSION=true" diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/oauth/OAuthRequest.java b/weather-api/src/main/java/com/thewizrd/weather_api/oauth/OAuthRequest.java index d9a7cb74..0f436a63 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/oauth/OAuthRequest.java +++ b/weather-api/src/main/java/com/thewizrd/weather_api/oauth/OAuthRequest.java @@ -7,7 +7,7 @@ import com.thewizrd.shared_resources.utils.StringUtils; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.Set; @@ -69,7 +69,7 @@ private static String getTimeStamp() { } private static String getNonce() { - return Base64.encodeToString((System.nanoTime() + "").getBytes(Charset.forName("UTF-8")), Base64.NO_WRAP); + return Base64.encodeToString((System.nanoTime() + "").getBytes(StandardCharsets.UTF_8), Base64.NO_WRAP); } public String getAuthorizationHeader(String url) throws InvalidKeyException, NoSuchAlgorithmException { @@ -121,9 +121,9 @@ public String getAuthorizationHeader(String urlString, boolean addGrantType) thr lHasher = Mac.getInstance("HmacSHA1"); } - SecretKeySpec secret_key = new SecretKeySpec(lCKey.getBytes(Charset.forName("UTF-8")), lHasher.getAlgorithm()); + SecretKeySpec secret_key = new SecretKeySpec(lCKey.getBytes(StandardCharsets.UTF_8), lHasher.getAlgorithm()); lHasher.init(secret_key); - lSign = Base64.encodeToString(lHasher.doFinal(lSign.getBytes(Charset.forName("UTF-8"))), Base64.NO_WRAP); + lSign = Base64.encodeToString(lHasher.doFinal(lSign.getBytes(StandardCharsets.UTF_8)), Base64.NO_WRAP); return "OAuth " + "oauth_consumer_key=\"" + uriEncode(consumerKey) + "\", " + diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/AQIResponse.kt b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/AQIResponse.kt new file mode 100644 index 00000000..1cc72e7e --- /dev/null +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/AQIResponse.kt @@ -0,0 +1,121 @@ +package com.thewizrd.weather_api.openmeteo + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class AQIResponse( + + @Json(name = "elevation") + var elevation: Float? = null, + + @Json(name = "generationtime_ms") + var generationtimeMs: Double? = null, + + @Json(name = "current") + var current: CurrentAQI? = null, + + @Json(name = "timezone_abbreviation") + var timezoneAbbreviation: String? = null, + + @Json(name = "current_units") + var currentUnits: CurrentAQIUnits? = null, + + @Json(name = "timezone") + var timezone: String? = null, + + @Json(name = "latitude") + var latitude: Float? = null, + + @Json(name = "utc_offset_seconds") + var utcOffsetSeconds: Int? = null, + + @Json(name = "longitude") + var longitude: Float? = null +) + +@JsonClass(generateAdapter = true) +data class CurrentAQI( + + @Json(name = "birch_pollen") + var birchPollen: Float? = null, + + @Json(name = "us_aqi_nitrogen_dioxide") + var usAqiNitrogenDioxide: Int? = null, + + @Json(name = "us_aqi_pm2_5") + var usAqiPm25: Int? = null, + + @Json(name = "us_aqi") + var usAqi: Int? = null, + + @Json(name = "us_aqi_sulphur_dioxide") + var usAqiSulphurDioxide: Int? = null, + + @Json(name = "us_aqi_ozone") + var usAqiOzone: Int? = null, + + @Json(name = "us_aqi_pm10") + var usAqiPm10: Int? = null, + + @Json(name = "grass_pollen") + var grassPollen: Float? = null, + + @Json(name = "interval") + var interval: Int? = null, + + @Json(name = "time") + var time: Long? = null, + + @Json(name = "us_aqi_carbon_monoxide") + var usAqiCarbonMonoxide: Int? = null, + + @Json(name = "ragweed_pollen") + var ragweedPollen: Float? = null, + + @Json(name = "alder_pollen") + var alderPollen: Float? = null +) + +@JsonClass(generateAdapter = true) +data class CurrentAQIUnits( + + @Json(name = "birch_pollen") + var birchPollen: String? = null, + + @Json(name = "us_aqi_nitrogen_dioxide") + var usAqiNitrogenDioxide: String? = null, + + @Json(name = "us_aqi_pm2_5") + var usAqiPm25: String? = null, + + @Json(name = "us_aqi") + var usAqi: String? = null, + + @Json(name = "us_aqi_sulphur_dioxide") + var usAqiSulphurDioxide: String? = null, + + @Json(name = "us_aqi_ozone") + var usAqiOzone: String? = null, + + @Json(name = "us_aqi_pm10") + var usAqiPm10: String? = null, + + @Json(name = "grass_pollen") + var grassPollen: String? = null, + + @Json(name = "interval") + var interval: String? = null, + + @Json(name = "time") + var time: String? = null, + + @Json(name = "us_aqi_carbon_monoxide") + var usAqiCarbonMonoxide: String? = null, + + @Json(name = "ragweed_pollen") + var ragweedPollen: String? = null, + + @Json(name = "alder_pollen") + var alderPollen: String? = null +) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/ForecastResponse.kt b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/ForecastResponse.kt new file mode 100644 index 00000000..526d43a6 --- /dev/null +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/ForecastResponse.kt @@ -0,0 +1,415 @@ +package com.thewizrd.weather_api.openmeteo + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class ForecastResponse( + + @Json(name = "elevation") + var elevation: Float? = null, + + @Json(name = "minutely_15") + var minutely15: Minutely15? = null, + + @Json(name = "daily_units") + var dailyUnits: DailyUnits? = null, + + @Json(name = "timezone") + var timezone: String? = null, + + @Json(name = "latitude") + var latitude: Float? = null, + + @Json(name = "minutely_15_units") + var minutely15Units: Minutely15Units? = null, + + @Json(name = "hourly_units") + var hourlyUnits: HourlyUnits? = null, + + @Json(name = "generationtime_ms") + var generationtimeMs: Double? = null, + + @Json(name = "current") + var current: Current? = null, + + @Json(name = "timezone_abbreviation") + var timezoneAbbreviation: String? = null, + + @Json(name = "current_units") + var currentUnits: CurrentUnits? = null, + + @Json(name = "daily") + var daily: Daily? = null, + + @Json(name = "utc_offset_seconds") + var utcOffsetSeconds: Int? = null, + + @Json(name = "hourly") + var hourly: Hourly? = null, + + @Json(name = "longitude") + var longitude: Float? = null +) + +@JsonClass(generateAdapter = true) +data class Daily( + + @Json(name = "sunrise") + var sunrise: List? = null, + + @Json(name = "wind_speed_10m_max") + var windSpeed10mMax: List? = null, + + @Json(name = "cloud_cover_mean") + var cloudCoverMean: List? = null, + + @Json(name = "uv_index_max") + var uvIndexMax: List? = null, + + @Json(name = "visibility_mean") + var visibilityMean: List? = null, + + @Json(name = "apparent_temperature_mean") + var apparentTemperatureMean: List? = null, + + @Json(name = "temperature_2m_min") + var temperature2mMin: List? = null, + + @Json(name = "wind_gusts_10m_max") + var windGusts10mMax: List? = null, + + @Json(name = "dew_point_2m_mean") + var dewPoint2mMean: List? = null, + + @Json(name = "relative_humidity_2m_mean") + var relativeHumidity2mMean: List? = null, + + @Json(name = "sunset") + var sunset: List? = null, + + @Json(name = "precipitation_probability_max") + var precipitationProbabilityMax: List? = null, + + @Json(name = "temperature_2m_max") + var temperature2mMax: List? = null, + + @Json(name = "wind_direction_10m_dominant") + var windDirection10mDominant: List? = null, + + @Json(name = "pressure_msl_mean") + var pressureMslMean: List? = null, + + @Json(name = "time") + var time: List? = null, + + @Json(name = "weather_code") + var weatherCode: List? = null +) + +@JsonClass(generateAdapter = true) +data class DailyUnits( + + @Json(name = "sunrise") + var sunrise: String? = null, + + @Json(name = "wind_speed_10m_max") + var windSpeed10mMax: String? = null, + + @Json(name = "cloud_cover_mean") + var cloudCoverMean: String? = null, + + @Json(name = "uv_index_max") + var uvIndexMax: String? = null, + + @Json(name = "visibility_mean") + var visibilityMean: String? = null, + + @Json(name = "apparent_temperature_mean") + var apparentTemperatureMean: String? = null, + + @Json(name = "temperature_2m_min") + var temperature2mMin: String? = null, + + @Json(name = "wind_gusts_10m_max") + var windGusts10mMax: String? = null, + + @Json(name = "dew_point_2m_mean") + var dewPoint2mMean: String? = null, + + @Json(name = "relative_humidity_2m_mean") + var relativeHumidity2mMean: String? = null, + + @Json(name = "sunset") + var sunset: String? = null, + + @Json(name = "precipitation_probability_max") + var precipitationProbabilityMax: String? = null, + + @Json(name = "temperature_2m_max") + var temperature2mMax: String? = null, + + @Json(name = "wind_direction_10m_dominant") + var windDirection10mDominant: String? = null, + + @Json(name = "pressure_msl_mean") + var pressureMslMean: String? = null, + + @Json(name = "time") + var time: String? = null, + + @Json(name = "weather_code") + var weatherCode: String? = null +) + +@JsonClass(generateAdapter = true) +data class Hourly( + + @Json(name = "pressure_msl") + var pressureMsl: List? = null, + + @Json(name = "wind_speed_10m") + var windSpeed10m: List? = null, + + @Json(name = "rain") + var rain: List? = null, + + @Json(name = "dew_point_2m") + var dewPoint2m: List? = null, + + @Json(name = "visibility") + var visibility: List? = null, + + @Json(name = "relative_humidity_2m") + var relativeHumidity2m: List? = null, + + @Json(name = "snowfall") + var snowfall: List? = null, + + @Json(name = "is_day") + var isDay: List? = null, + + @Json(name = "wind_direction_10m") + var windDirection10m: List? = null, + + @Json(name = "wind_gusts_10m") + var windGusts10m: List? = null, + + @Json(name = "temperature_2m") + var temperature2m: List? = null, + + @Json(name = "uv_index") + var uvIndex: List? = null, + + @Json(name = "precipitation_probability") + var precipitationProbability: List? = null, + + @Json(name = "cloud_cover") + var cloudCover: List? = null, + + @Json(name = "apparent_temperature") + var apparentTemperature: List? = null, + + @Json(name = "time") + var time: List? = null, + + @Json(name = "weather_code") + var weatherCode: List? = null +) + +@JsonClass(generateAdapter = true) +data class Current( + + @Json(name = "pressure_msl") + var pressureMsl: Float? = null, + + @Json(name = "wind_speed_10m") + var windSpeed10m: Float? = null, + + @Json(name = "rain") + var rain: Float? = null, + + @Json(name = "dew_point_2m") + var dewPoint2m: Float? = null, + + @Json(name = "visibility") + var visibility: Float? = null, + + @Json(name = "relative_humidity_2m") + var relativeHumidity2m: Int? = null, + + @Json(name = "snowfall") + var snowfall: Float? = null, + + @Json(name = "is_day") + var isDay: Int? = null, + + @Json(name = "wind_direction_10m") + var windDirection10m: Int? = null, + + @Json(name = "wind_gusts_10m") + var windGusts10m: Float? = null, + + @Json(name = "temperature_2m") + var temperature2m: Float? = null, + + @Json(name = "uv_index") + var uvIndex: Float? = null, + + @Json(name = "precipitation_probability") + var precipitationProbability: Int? = null, + + @Json(name = "cloud_cover") + var cloudCover: Int? = null, + + @Json(name = "apparent_temperature") + var apparentTemperature: Float? = null, + + @Json(name = "interval") + var interval: Int? = null, + + @Json(name = "time") + var time: Long? = null, + + @Json(name = "weather_code") + var weatherCode: Int? = null +) + +@JsonClass(generateAdapter = true) +data class HourlyUnits( + + @Json(name = "pressure_msl") + var pressureMsl: String? = null, + + @Json(name = "wind_speed_10m") + var windSpeed10m: String? = null, + + @Json(name = "rain") + var rain: String? = null, + + @Json(name = "dew_point_2m") + var dewPoint2m: String? = null, + + @Json(name = "visibility") + var visibility: String? = null, + + @Json(name = "relative_humidity_2m") + var relativeHumidity2m: String? = null, + + @Json(name = "snowfall") + var snowfall: String? = null, + + @Json(name = "is_day") + var isDay: String? = null, + + @Json(name = "wind_direction_10m") + var windDirection10m: String? = null, + + @Json(name = "wind_gusts_10m") + var windGusts10m: String? = null, + + @Json(name = "temperature_2m") + var temperature2m: String? = null, + + @Json(name = "uv_index") + var uvIndex: String? = null, + + @Json(name = "precipitation_probability") + var precipitationProbability: String? = null, + + @Json(name = "cloud_cover") + var cloudCover: String? = null, + + @Json(name = "apparent_temperature") + var apparentTemperature: String? = null, + + @Json(name = "time") + var time: String? = null, + + @Json(name = "weather_code") + var weatherCode: String? = null +) + +@JsonClass(generateAdapter = true) +data class Minutely15( + + @Json(name = "rain") + var rain: List? = null, + + @Json(name = "snowfall") + var snowfall: List? = null, + + @Json(name = "time") + var time: List? = null +) + +@JsonClass(generateAdapter = true) +data class Minutely15Units( + + @Json(name = "rain") + var rain: String? = null, + + @Json(name = "snowfall") + var snowfall: String? = null, + + @Json(name = "time") + var time: String? = null +) + +@JsonClass(generateAdapter = true) +data class CurrentUnits( + + @Json(name = "pressure_msl") + var pressureMsl: String? = null, + + @Json(name = "wind_speed_10m") + var windSpeed10m: String? = null, + + @Json(name = "rain") + var rain: String? = null, + + @Json(name = "dew_point_2m") + var dewPoint2m: String? = null, + + @Json(name = "visibility") + var visibility: String? = null, + + @Json(name = "relative_humidity_2m") + var relativeHumidity2m: String? = null, + + @Json(name = "snowfall") + var snowfall: String? = null, + + @Json(name = "is_day") + var isDay: String? = null, + + @Json(name = "wind_direction_10m") + var windDirection10m: String? = null, + + @Json(name = "wind_gusts_10m") + var windGusts10m: String? = null, + + @Json(name = "temperature_2m") + var temperature2m: String? = null, + + @Json(name = "uv_index") + var uvIndex: String? = null, + + @Json(name = "precipitation_probability") + var precipitationProbability: String? = null, + + @Json(name = "cloud_cover") + var cloudCover: String? = null, + + @Json(name = "apparent_temperature") + var apparentTemperature: String? = null, + + @Json(name = "interval") + var interval: String? = null, + + @Json(name = "time") + var time: String? = null, + + @Json(name = "weather_code") + var weatherCode: String? = null +) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/OpenMeteoWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/OpenMeteoWeatherProvider.kt new file mode 100644 index 00000000..4ad8ecd2 --- /dev/null +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/OpenMeteoWeatherProvider.kt @@ -0,0 +1,692 @@ +package com.thewizrd.weather_api.openmeteo + +import android.util.Log +import androidx.core.net.toUri +import com.ibm.icu.util.ULocale +import com.thewizrd.shared_resources.R +import com.thewizrd.shared_resources.exceptions.ErrorStatus +import com.thewizrd.shared_resources.exceptions.WeatherException +import com.thewizrd.shared_resources.icons.WeatherIcons +import com.thewizrd.shared_resources.locationdata.LocationData +import com.thewizrd.shared_resources.okhttp3.OkHttp3Utils.await +import com.thewizrd.shared_resources.okhttp3.OkHttp3Utils.getStream +import com.thewizrd.shared_resources.remoteconfig.remoteConfigService +import com.thewizrd.shared_resources.sharedDeps +import com.thewizrd.shared_resources.utils.JSONParser +import com.thewizrd.shared_resources.utils.LocaleUtils +import com.thewizrd.shared_resources.utils.Logger +import com.thewizrd.shared_resources.utils.ZoneIdCompat +import com.thewizrd.shared_resources.weatherdata.PollenProvider +import com.thewizrd.shared_resources.weatherdata.WeatherAPI +import com.thewizrd.shared_resources.weatherdata.auth.AuthType +import com.thewizrd.shared_resources.weatherdata.model.Pollen +import com.thewizrd.shared_resources.weatherdata.model.Weather +import com.thewizrd.shared_resources.weatherdata.model.isNullOrInvalid +import com.thewizrd.weather_api.BuildConfig +import com.thewizrd.weather_api.extras.cacheRequestIfNeeded +import com.thewizrd.weather_api.keys.Keys +import com.thewizrd.weather_api.nws.SolCalcAstroProvider +import com.thewizrd.weather_api.smc.SunMoonCalcProvider +import com.thewizrd.weather_api.utils.APIRequestUtils.checkForErrors +import com.thewizrd.weather_api.utils.APIRequestUtils.checkRateLimit +import com.thewizrd.weather_api.utils.APIRequestUtils.throwIfRateLimited +import com.thewizrd.weather_api.utils.logMissingIcon +import com.thewizrd.weather_api.weatherModule +import com.thewizrd.weather_api.weatherapi.location.WeatherApiLocationProvider +import com.thewizrd.weather_api.weatherdata.WeatherProviderImpl +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import okhttp3.CacheControl +import okhttp3.Request +import okhttp3.Response +import okhttp3.internal.closeQuietly +import java.io.IOException +import java.net.HttpURLConnection +import java.text.DecimalFormat +import java.time.Instant +import java.time.LocalTime +import java.time.ZoneOffset +import java.time.ZonedDateTime +import java.util.Locale +import java.util.concurrent.TimeUnit +import kotlin.math.max + +class OpenMeteoWeatherProvider : WeatherProviderImpl(), PollenProvider { + companion object { + private const val NON_COMMERCIAL_FORECAST_URL = "https://api.open-meteo.com/v1/forecast" + private const val COMMERCIAL_FORECAST_URL = + "https://customer-api.open-meteo.com/v1/forecast" + + private const val NON_COMMERCIAL_AQ_URL = + "https://air-quality-api.open-meteo.com/v1/air-quality" + private const val COMMERCIAL_AQ_URL = + "https://customer-air-quality-api.open-meteo.com/v1/air-quality" + private const val KEYCHECK_QUERY_URL = "$COMMERCIAL_FORECAST_URL?apikey=%s" + } + + init { + mLocationProvider = runCatching { + weatherModule.locationProviderFactory.getLocationProvider( + remoteConfigService.getLocationProvider( + getWeatherAPI() + ) + ) + }.getOrElse { + WeatherApiLocationProvider() + } + } + + override fun getWeatherAPI(): String { + return WeatherAPI.OPENMETEO + } + + override fun supportsWeatherLocale(): Boolean { + return false + } + + override fun isKeyRequired(): Boolean { + return !BuildConfig.IS_NONGMS + } + + override fun getAuthType(): AuthType { + return if (BuildConfig.IS_NONGMS) AuthType.APIKEY else AuthType.INTERNAL + } + + @Throws(WeatherException::class) + override suspend fun isKeyValid(key: String?): Boolean = withContext(Dispatchers.IO) { + if (key.isNullOrBlank()) { + throw WeatherException(ErrorStatus.INVALIDAPIKEY) + } + + var isValid = false + var wEx: WeatherException? = null + + val client = sharedDeps.httpClient + var response: Response? = null + + try { + // If were under rate limit, deny request + checkRateLimit() + + val request = Request.Builder() + .cacheControl( + CacheControl.Builder() + .maxAge(1, TimeUnit.DAYS) + .build() + ) + .url(String.format(KEYCHECK_QUERY_URL, key)) + .build() + + // Connect to webstream + response = client.newCall(request).await() + throwIfRateLimited(response) + + when (response.code) { + HttpURLConnection.HTTP_BAD_REQUEST -> isValid = true + HttpURLConnection.HTTP_UNAUTHORIZED -> { + wEx = WeatherException(ErrorStatus.INVALIDAPIKEY) + isValid = false + } + } + } catch (ex: Exception) { + if (ex is IOException) { + wEx = WeatherException(ErrorStatus.NETWORKERROR, ex) + } else if (ex is WeatherException) { + wEx = ex + } + + isValid = false + } finally { + response?.closeQuietly() + } + + if (wEx != null && wEx.errorStatus != ErrorStatus.INVALIDAPIKEY) { + throw wEx + } + + return@withContext isValid + } + + override fun getAPIKey(): String? { + return Keys.getOpenMeteoKey() + } + + @Throws(WeatherException::class) + override suspend fun getWeatherData(location: LocationData): Weather = + withContext(Dispatchers.IO) { + var weather: Weather? + + val uLocale = ULocale.forLocale(LocaleUtils.getLocale()) + val locale = localeToLangCode(uLocale.language, uLocale.toLanguageTag()) + val query = updateLocationQuery(location) + + val key = getProviderKey() + + val client = sharedDeps.httpClient + var response: Response? = null + var aqiResponse: Response? = null + var wEx: WeatherException? = null + + try { + // If were under rate limit, deny request + checkRateLimit() + + if (isKeyRequired() && key.isNullOrBlank()) { + throw WeatherException(ErrorStatus.INVALIDAPIKEY) + } + + val baseUrl = if (BuildConfig.IS_NONGMS) { + NON_COMMERCIAL_FORECAST_URL + } else { + COMMERCIAL_FORECAST_URL + } + + val aqiBaseUrl = if (BuildConfig.IS_NONGMS) { + NON_COMMERCIAL_AQ_URL + } else { + COMMERCIAL_AQ_URL + } + + val df = DecimalFormat.getInstance(Locale.ROOT) as DecimalFormat + df.applyPattern("0.####") + + val forecastRequestUri = baseUrl.toUri().buildUpon() + .appendQueryParameter("latitude", df.format(location.latitude)) + .appendQueryParameter("longitude", df.format(location.longitude)) + .appendQueryParameter( + "daily", + "weather_code,temperature_2m_max,temperature_2m_min,uv_index_max,precipitation_probability_max,wind_speed_10m_max,wind_gusts_10m_max,wind_direction_10m_dominant,cloud_cover_mean,apparent_temperature_mean,dew_point_2m_mean,pressure_msl_mean,relative_humidity_2m_mean,visibility_mean" + ) + .appendQueryParameter( + "hourly", + "temperature_2m,relative_humidity_2m,dew_point_2m,apparent_temperature,precipitation_probability,weather_code,pressure_msl,cloud_cover,visibility,wind_speed_10m,wind_gusts_10m,wind_direction_10m,rain,snowfall,uv_index,is_day" + ) + .appendQueryParameter( + "current", + "temperature_2m,relative_humidity_2m,dew_point_2m,apparent_temperature,precipitation_probability,weather_code,pressure_msl,cloud_cover,visibility,wind_speed_10m,wind_gusts_10m,wind_direction_10m,rain,snowfall,uv_index,is_day" + ) + .appendQueryParameter("minutely_15", "rain,snowfall") + .appendQueryParameter("models", "best_match") + .appendQueryParameter("timeformat", "unixtime") + .appendQueryParameter("timezone", "auto") + .apply { + if (isKeyRequired()) { + this.appendQueryParameter("apikey", key) + } + } + .build() + + val forecastRequest = Request.Builder() + .cacheRequestIfNeeded(isKeyRequired(), 30, TimeUnit.MINUTES) + .url(forecastRequestUri.toString()) + .header("Accept", "application/json") + .build() + + val aqiRequestUri = aqiBaseUrl.toUri().buildUpon() + .appendQueryParameter("latitude", df.format(location.latitude)) + .appendQueryParameter("longitude", df.format(location.longitude)) + .appendQueryParameter( + "current", + "us_aqi,ragweed_pollen,grass_pollen,birch_pollen,alder_pollen,pm10,pm2_5,carbon_monoxide,nitrogen_dioxide,sulphur_dioxide,ozone" + ) + .appendQueryParameter("timeformat", "unixtime") + .appendQueryParameter("timezone", "auto") + .apply { + if (isKeyRequired()) { + this.appendQueryParameter("apikey", key) + } + } + .build() + + val aqiRequest = Request.Builder() + .cacheRequestIfNeeded(isKeyRequired(), 20, TimeUnit.MINUTES) + .url(aqiRequestUri.toString()) + .header("Accept", "application/json") + .build() + + // Connect to webstream + response = client.newCall(forecastRequest).await() + checkForErrors(response) + // Load weather + val root = response.getStream().use { + JSONParser.deserializer(it, ForecastResponse::class.java) + } + + val aqiRoot = runCatching { + aqiResponse = client.newCall(aqiRequest).await() + checkForErrors(aqiResponse) + aqiResponse.getStream().use { + JSONParser.deserializer( + it, + AQIResponse::class.java + ) + } + }.getOrNull() + + requireNotNull(root) + requireNotNull(aqiRoot) + + weather = createWeatherData(root, aqiRoot) + } catch (ex: Exception) { + weather = null + if (ex is IOException) { + wEx = WeatherException(ErrorStatus.NETWORKERROR, ex) + } else if (ex is WeatherException) { + wEx = ex + } + Logger.writeLine( + Log.ERROR, + ex, + "OpenMeteoWeatherProvider: error getting weather data" + ) + } finally { + response?.closeQuietly() + aqiResponse?.closeQuietly() + } + + if (wEx == null && weather.isNullOrInvalid()) { + wEx = WeatherException(ErrorStatus.NOWEATHER) + } else if (weather != null) { + if (supportsWeatherLocale()) weather.locale = locale + + weather.query = query + } + + if (wEx != null) throw wEx + + return@withContext weather!! + } + + override suspend fun getPollenData(location: LocationData): Pollen? = + withContext(Dispatchers.IO) { + var pollenData: Pollen? = null + + val key = getProviderKey() + + val client = sharedDeps.httpClient + var response: Response? = null + + try { + // If were under rate limit, deny request + checkRateLimit() + + if (isKeyRequired() && key.isNullOrBlank()) { + throw WeatherException(ErrorStatus.INVALIDAPIKEY) + } + + val baseUrl = if (BuildConfig.IS_NONGMS) { + NON_COMMERCIAL_AQ_URL + } else { + COMMERCIAL_AQ_URL + } + + val df = DecimalFormat.getInstance(Locale.ROOT) as DecimalFormat + df.applyPattern("0.####") + + val requestUri = baseUrl.toUri().buildUpon() + .appendQueryParameter("latitude", df.format(location.latitude)) + .appendQueryParameter("longitude", df.format(location.longitude)) + .appendQueryParameter( + "current", + "ragweed_pollen,grass_pollen,birch_pollen,alder_pollen" + ) + .appendQueryParameter("timeformat", "unixtime") + .appendQueryParameter("timezone", "auto") + .apply { + if (isKeyRequired()) { + this.appendQueryParameter("apikey", key) + } + } + .build() + + val request = Request.Builder() + .cacheRequestIfNeeded(isKeyRequired(), 20, TimeUnit.MINUTES) + .url(requestUri.toString()) + .header("Accept", "application/json") + .build() + + // Connect to webstream + response = client.newCall(request).await() + checkForErrors(response) + // Load weather + val root = response.getStream().use { + JSONParser.deserializer(it, AQIResponse::class.java) + } + + requireNotNull(root) + + root.current?.let { current -> + val treePollenMeasure = + if (current.birchPollen != null && current.alderPollen != null) { + max(current.birchPollen!!, current.alderPollen!!) + } else { + current.birchPollen ?: current.alderPollen + } + val grassPollenMeasure = current.grassPollen + val ragweedPollenMeasure = current.ragweedPollen + + pollenData = Pollen().apply { + treePollenCount = when { + treePollenMeasure == null -> Pollen.PollenCount.UNKNOWN + treePollenMeasure < 15 -> Pollen.PollenCount.LOW + treePollenMeasure < 90 -> Pollen.PollenCount.MODERATE + treePollenMeasure < 1500 -> Pollen.PollenCount.HIGH + treePollenMeasure >= 1500 -> Pollen.PollenCount.VERY_HIGH + else -> Pollen.PollenCount.UNKNOWN + } + + grassPollenCount = when { + grassPollenMeasure == null -> Pollen.PollenCount.UNKNOWN + grassPollenMeasure < 5 -> Pollen.PollenCount.LOW + grassPollenMeasure < 20 -> Pollen.PollenCount.MODERATE + grassPollenMeasure < 200 -> Pollen.PollenCount.HIGH + grassPollenMeasure >= 200 -> Pollen.PollenCount.VERY_HIGH + else -> Pollen.PollenCount.UNKNOWN + } + + ragweedPollenCount = when { + ragweedPollenMeasure == null -> Pollen.PollenCount.UNKNOWN + ragweedPollenMeasure < 10 -> Pollen.PollenCount.LOW + ragweedPollenMeasure < 50 -> Pollen.PollenCount.MODERATE + ragweedPollenMeasure < 500 -> Pollen.PollenCount.HIGH + ragweedPollenMeasure >= 500 -> Pollen.PollenCount.VERY_HIGH + else -> Pollen.PollenCount.UNKNOWN + } + } + } + } catch (ex: Exception) { + pollenData = null + Logger.writeLine( + Log.ERROR, + ex, + "OpenMeteoWeatherProvider: error getting pollen data" + ) + } finally { + response?.closeQuietly() + } + + return@withContext pollenData + } + + @Throws(WeatherException::class) + override suspend fun updateWeatherData(location: LocationData, weather: Weather) { + super.updateWeatherData(location, weather) + + val offset = location.tzOffset + + // Update tz for weather properties + weather.updateTime = weather.updateTime!!.withZoneSameInstant(offset) + weather.condition!!.observationTime = + weather.condition!!.observationTime.withZoneSameInstant(offset) + + weather.astronomy = try { + SunMoonCalcProvider().getAstronomyData(location, weather.condition!!.observationTime) + } catch (e: WeatherException) { + Logger.writeLine(Log.ERROR, e, "Error") + SolCalcAstroProvider().getAstronomyData(location, weather.condition!!.observationTime) + } + + weather.condition?.icon.let { + weather.condition!!.icon = getWeatherIcon(it) + weather.condition!!.weather = getWeatherCondition(it) + } + + weather.forecast?.forEach { forecast -> + forecast.date = forecast.date.plusSeconds(offset.totalSeconds.toLong()) + + forecast.icon.let { + forecast.icon = getWeatherIcon(it) + forecast.condition = getWeatherCondition(it) + } + } + + weather.hrForecast?.forEach { hrf -> + hrf.date = hrf.date.withZoneSameInstant(offset) + + hrf.icon?.let { + hrf.icon = getWeatherIcon(it) + hrf.condition = getWeatherCondition(it) + } + } + + weather.minForecast?.forEach { minutelyForecast -> + minutelyForecast.date = minutelyForecast.date.withZoneSameInstant(offset) + } + } + + override suspend fun updateLocationQuery(weather: Weather): String { + val df = DecimalFormat.getInstance(Locale.ROOT) as DecimalFormat + df.applyPattern("0.####") + return String.format( + Locale.ROOT, + "latitude=%s&longitude=%s", + df.format(weather.location!!.latitude), + df.format(weather.location!!.longitude) + ) + } + + override suspend fun updateLocationQuery(location: LocationData): String { + val df = DecimalFormat.getInstance(Locale.ROOT) as DecimalFormat + df.applyPattern("0.####") + return String.format( + Locale.ROOT, + "latitude=%s&longitude=%s", + df.format(location.latitude), + df.format(location.longitude) + ) + } + + override fun getWeatherIcon(icon: String?): String { + var isNight = false + + if (icon == null) return WeatherIcons.NA + + if (icon.endsWith("_0")) isNight = true + + return getWeatherIcon(isNight, icon) + } + + override fun getWeatherIcon(isNight: Boolean, icon: String?): String { + var weatherIcon = "" + + val conditionCode = + icon?.split('_')?.getOrNull(0)?.toIntOrNull() ?: return WeatherIcons.NA + + when (conditionCode) { + /* + * 0: Clear sky + * 1: Mainly clear + */ + 0, 1 -> { + weatherIcon = if (isNight) WeatherIcons.NIGHT_CLEAR else WeatherIcons.DAY_SUNNY + } + /* + * 2: Partly cloudy + */ + 2 -> { + weatherIcon = + if (isNight) WeatherIcons.NIGHT_ALT_PARTLY_CLOUDY else WeatherIcons.DAY_PARTLY_CLOUDY + } + + /* + * 3: overcast + */ + 3 -> { + weatherIcon = + if (isNight) WeatherIcons.NIGHT_OVERCAST else WeatherIcons.DAY_SUNNY_OVERCAST + } + + /* + * 45: Fog + * 48: depositing rime fog + */ + 45, 48 -> { + weatherIcon = WeatherIcons.FOG + } + + /* + * 51, 53, 55: Drizzle: Light, moderate, and dense intensity + */ + 51, 53, 55 -> { + weatherIcon = WeatherIcons.SPRINKLE + } + + /* + * 56, 57: Freezing Drizzle: Light and dense intensity + */ + 56, 57 -> { + weatherIcon = WeatherIcons.RAIN_MIX + } + + /* + * 61, 63, 65: Rain: Slight, moderate and heavy intensity + */ + 61, 63 -> { + weatherIcon = WeatherIcons.RAIN + } + + 65 -> { + weatherIcon = WeatherIcons.RAIN_WIND + } + + /* + * 66, 67: Freezing Rain: Light and heavy intensity + */ + 66, 67 -> { + weatherIcon = WeatherIcons.RAIN_MIX + } + + /* + * 71, 73, 75: Snow fall: Slight, moderate, and heavy intensity + * 77: Snow grains + */ + 71, 73, 77 -> { + weatherIcon = WeatherIcons.SNOW + } + + 75 -> { + weatherIcon = WeatherIcons.SNOW_WIND + } + + /* + * 80, 81, 82: Rain showers: Slight, moderate, and violent + */ + 80, 81 -> { + weatherIcon = WeatherIcons.SHOWERS + } + + 82 -> { + weatherIcon = WeatherIcons.STORM_SHOWERS + } + + /* + * 85, 86: Snow showers slight and heavy + */ + 85 -> { + weatherIcon = WeatherIcons.SNOW + } + + 86 -> { + weatherIcon = WeatherIcons.SNOW_WIND + } + + /* + * 95: Thunderstorm: Slight or moderate + * 96, 99: Thunderstorm with slight and heavy hail + */ + 95 -> { + weatherIcon = WeatherIcons.THUNDERSTORM + } + + 96, 99 -> { + weatherIcon = WeatherIcons.SNOW_THUNDERSTORM + } + } + + if (weatherIcon.isBlank()) { + // Not Available + logMissingIcon(icon) + weatherIcon = WeatherIcons.NA + } + return weatherIcon + } + + override fun getWeatherCondition(icon: String?): String { + val conditionCode = icon?.split('_')?.getOrNull(0)?.toIntOrNull() + ?: return super.getWeatherCondition(icon) + + return when (conditionCode) { + /* 0: Clear sky */ + 0 -> context.getString(R.string.weather_clearsky) + /* 1: Mainly clear */ + 1 -> context.getString(R.string.weather_mostlyclear) + /* 2: partly cloudy */ + 2 -> context.getString(R.string.weather_partlycloudy) + /* 3: overcast */ + 3 -> context.getString(R.string.weather_overcast) + /* 45, 48: Fog and depositing rime fog */ + 45, 48 -> context.getString(R.string.weather_fog) + /* 51, 53, 55: Drizzle: Light, moderate, and dense intensity */ + 51, 53, 55 -> context.getString(R.string.weather_drizzle) + /* + * 56, 57: Freezing Drizzle: Light and dense intensity + * 66, 67: Freezing Rain: Light and heavy intensity + */ + 56, 57, 66, 67 -> context.getString(R.string.weather_freezingrain) + /* 61, 63, 65: Rain: Slight, moderate and heavy intensity */ + 61 -> context.getString(R.string.weather_lightrain) + 63 -> context.getString(R.string.weather_rain) + 65 -> context.getString(R.string.weather_heavyrain) + /* + * 71, 73, 75: Snow fall: Slight, moderate, and heavy intensity + * 77: Snow grains + */ + 71 -> context.getString(R.string.weather_lightsnowshowers) + 73, 77 -> context.getString(R.string.weather_snow) + 75 -> context.getString(R.string.weather_heavysnow) + /* 80, 81, 82: Rain showers: Slight, moderate, and violent */ + 80, 81, 82 -> context.getString(R.string.weather_rainshowers) + /* 85, 86: Snow showers slight and heavy */ + 85 -> context.getString(R.string.weather_lightsnowshowers) + 86 -> context.getString(R.string.weather_heavysnow) + /* + * 95: Thunderstorm: Slight or moderate + * 96, 99: Thunderstorm with slight and heavy hail + */ + 95, 96, 99 -> context.getString(R.string.weather_tstorms) + else -> { + logMissingIcon(icon) + context.getString(R.string.weather_notavailable) + } + } + } + + // Some conditions can be for any time of day + // So use sunrise/set data as fallback + override fun isNight(weather: Weather): Boolean { + var isNight = super.isNight(weather) + + if (!isNight) { + // Fallback to sunset/rise time just in case + var tz: ZoneOffset? = null + if (!weather.location!!.tzLong.isNullOrBlank()) { + val id = ZoneIdCompat.of(weather.location!!.tzLong) + tz = id.rules.getOffset(Instant.now()) + } + if (tz == null) { + tz = weather.location!!.tzOffset + } + + val sunrise = weather.astronomy?.sunrise?.toLocalTime() ?: LocalTime.of(6, 0) + val sunset = weather.astronomy?.sunset?.toLocalTime() ?: LocalTime.of(18, 0) + + val now = ZonedDateTime.now(tz).toLocalTime() + + // Determine whether its night using sunset/rise times + if (now.toNanoOfDay() < sunrise.toNanoOfDay() || now.toNanoOfDay() > sunset.toNanoOfDay()) + isNight = true + } + + return isNight + } +} \ No newline at end of file diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/WeatherData.kt new file mode 100644 index 00000000..9e1c9aa5 --- /dev/null +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/WeatherData.kt @@ -0,0 +1,326 @@ +package com.thewizrd.weather_api.openmeteo + +import android.annotation.SuppressLint +import com.thewizrd.shared_resources.utils.ConversionMethods +import com.thewizrd.shared_resources.utils.getBeaufortScale +import com.thewizrd.shared_resources.weatherdata.WeatherAPI +import com.thewizrd.shared_resources.weatherdata.model.AirQuality +import com.thewizrd.shared_resources.weatherdata.model.Atmosphere +import com.thewizrd.shared_resources.weatherdata.model.Beaufort +import com.thewizrd.shared_resources.weatherdata.model.Condition +import com.thewizrd.shared_resources.weatherdata.model.Forecast +import com.thewizrd.shared_resources.weatherdata.model.ForecastExtras +import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast +import com.thewizrd.shared_resources.weatherdata.model.Location +import com.thewizrd.shared_resources.weatherdata.model.MinutelyForecast +import com.thewizrd.shared_resources.weatherdata.model.Pollen +import com.thewizrd.shared_resources.weatherdata.model.Precipitation +import com.thewizrd.shared_resources.weatherdata.model.UV +import com.thewizrd.shared_resources.weatherdata.model.Weather +import java.time.Instant +import java.time.ZoneOffset +import java.time.ZonedDateTime +import kotlin.math.max +import kotlin.math.roundToInt + +@SuppressLint("VisibleForTests") +fun createWeatherData(forecast: ForecastResponse, aqiResponse: AQIResponse): Weather { + return Weather().apply { + location = createLocation(forecast) + updateTime = ZonedDateTime.now(ZoneOffset.UTC) + + this.forecast = forecast.daily?.let { createForecasts(it) } + hrForecast = forecast.hourly?.let { createHourlyForecasts(it) } + minForecast = forecast.minutely15?.let { createMinutelyForecasts(it) } + + condition = forecast.current?.let { createCondition(it, aqiResponse.current) } + atmosphere = forecast.current?.let { createAtmosphere(it) } + precipitation = forecast.current?.let { createPrecipitation(it) } + + if ((condition?.highF == null || condition?.highC == null) && !this.forecast.isNullOrEmpty()) { + condition!!.highF = this.forecast!![0].highF + condition!!.highC = this.forecast!![0].highC + condition!!.lowF = this.forecast!![0].lowF + condition!!.lowC = this.forecast!![0].lowC + } + + ttl = 120 + source = WeatherAPI.OPENMETEO + } +} + +fun createLocation(forecast: ForecastResponse): Location { + return Location().apply { + // Use location name from location provider + name = null + latitude = forecast.latitude + longitude = forecast.longitude + tzLong = forecast.timezone + } +} + +fun createForecasts(daily: Daily): List? { + return daily.time?.mapIndexed { index, ts -> + Forecast().apply { + date = + ZonedDateTime.ofInstant(Instant.ofEpochSecond(ts), ZoneOffset.UTC).toLocalDateTime() + + daily.temperature2mMax?.getOrNull(index)?.let { + highF = ConversionMethods.CtoF(it) + highC = it + } + daily.temperature2mMin?.getOrNull(index)?.let { + lowF = ConversionMethods.CtoF(it) + lowC = it + } + + icon = (daily.weatherCode?.getOrNull(index) ?: -1).toString() + condition = icon + + // Extras + extras = ForecastExtras() + + extras.uvIndex = daily.uvIndexMax?.getOrNull(index) + extras.pop = daily.precipitationProbabilityMax?.getOrNull(index) + + daily.windSpeed10mMax?.getOrNull(index)?.let { + extras.windKph = it + extras.windMph = ConversionMethods.kphTomph(it) + } + + daily.windGusts10mMax?.getOrNull(index)?.let { + extras.windGustKph = it + extras.windGustMph = ConversionMethods.kphTomph(it) + } + + extras.windDegrees = daily.windDirection10mDominant?.getOrNull(index) + + extras.cloudiness = daily.cloudCoverMean?.getOrNull(index) + + daily.apparentTemperatureMean?.getOrNull(index)?.let { + extras.feelslikeC = it + extras.feelslikeF = ConversionMethods.CtoF(it) + } + + daily.dewPoint2mMean?.getOrNull(index)?.let { + extras.dewpointC = it + extras.dewpointF = ConversionMethods.CtoF(it) + } + + // 1hPA = 1mbar + daily.pressureMslMean?.getOrNull(index)?.let { + extras.pressureMb = it + extras.pressureIn = ConversionMethods.mbToInHg(it) + } + + extras.humidity = daily.relativeHumidity2mMean?.getOrNull(index) + + daily.visibilityMean?.getOrNull(index)?.let { + extras.visibilityKm = it / 1000 + extras.visibilityMi = ConversionMethods.kmToMi(it / 1000) + } + } + } +} + +fun createHourlyForecasts(hourly: Hourly): List? { + return hourly.time?.mapIndexed { index, ts -> + HourlyForecast().apply { + date = ZonedDateTime.ofInstant(Instant.ofEpochSecond(ts), ZoneOffset.UTC) + + hourly.temperature2m?.getOrNull(index)?.let { + highC = it + highF = ConversionMethods.CtoF(it) + } + + val isDay = hourly.isDay?.getOrNull(index) ?: 1 + icon = hourly.weatherCode?.getOrNull(index)?.toString() + "_" + isDay + condition = icon + + // Extras + extras = ForecastExtras() + + extras.humidity = hourly.relativeHumidity2m?.getOrNull(index) + + hourly.dewPoint2m?.getOrNull(index)?.let { + extras.dewpointC = it + extras.dewpointF = ConversionMethods.CtoF(it) + } + + hourly.apparentTemperature?.getOrNull(index)?.let { + extras.feelslikeC = it + extras.feelslikeF = ConversionMethods.CtoF(it) + } + + extras.pop = hourly.precipitationProbability?.getOrNull(index) + + // 1hPA = 1mbar + hourly.pressureMsl?.getOrNull(index)?.let { + extras.pressureMb = it + extras.pressureIn = ConversionMethods.mbToInHg(it) + } + + extras.cloudiness = hourly.cloudCover?.getOrNull(index) + + hourly.visibility?.getOrNull(index)?.let { + extras.visibilityKm = it / 1000 + extras.visibilityMi = ConversionMethods.kmToMi(it / 1000) + } + + hourly.windSpeed10m?.getOrNull(index)?.let { speed -> + extras.windKph = speed + extras.windMph = ConversionMethods.kphTomph(speed) + } + + hourly.windGusts10m?.getOrNull(index)?.let { speed -> + extras.windGustKph = speed + extras.windGustKph = ConversionMethods.kphTomph(speed) + } + + extras.windDegrees = hourly.windDirection10m?.getOrNull(index) + + hourly.rain?.getOrNull(index)?.let { + extras.qpfRainMm = it + extras.qpfRainIn = ConversionMethods.mmToIn(it) + } + + hourly.snowfall?.getOrNull(index)?.let { + extras.qpfSnowCm = it + extras.qpfSnowIn = ConversionMethods.mmToIn(it) + } + } + } +} + +fun createMinutelyForecasts(minutely15: Minutely15): List? { + return minutely15.time?.mapIndexed { index, ts -> + MinutelyForecast().apply { + date = ZonedDateTime.ofInstant(Instant.ofEpochSecond(ts), ZoneOffset.UTC) + rainMm = minutely15.rain?.getOrNull(index) + snowMm = minutely15.snowfall?.getOrNull(index)?.let { it * 10 } + } + } +} + +fun createCondition(current: Current, aqi: CurrentAQI?): Condition { + return Condition().apply { + observationTime = + current.time?.let { ZonedDateTime.ofInstant(Instant.ofEpochSecond(it), ZoneOffset.UTC) } + + val isDay = current.isDay ?: 1 + icon = current.weatherCode?.toString() + "_" + isDay + weather = icon + + current.temperature2m?.let { + tempC = it + tempF = ConversionMethods.CtoF(it) + } + + current.apparentTemperature?.let { + feelslikeC = it + feelslikeF = ConversionMethods.CtoF(it) + } + + current.windSpeed10m?.let { + windKph = it + windMph = ConversionMethods.kphTomph(it) + beaufort = Beaufort(getBeaufortScale(mph = windMph.roundToInt())) + } + + current.windGusts10m?.let { + windGustKph = it + windGustMph = ConversionMethods.kphTomph(it) + } + + windDegrees = current.windDirection10m + + uv = current.uvIndex?.let { UV(it) } + + airQuality = AirQuality().apply { + index = aqi?.usAqi + pm25 = aqi?.usAqiPm25 + pm10 = aqi?.usAqiPm10 + o3 = aqi?.usAqiOzone + no2 = aqi?.usAqiNitrogenDioxide + co = aqi?.usAqiCarbonMonoxide + so2 = aqi?.usAqiSulphurDioxide + } + + val treePollenMeasure = if (aqi?.birchPollen != null && aqi.alderPollen != null) { + max(aqi.birchPollen!!, aqi.alderPollen!!) + } else { + aqi?.birchPollen ?: aqi?.alderPollen + } + val grassPollenMeasure = aqi?.grassPollen + val ragweedPollenMeasure = aqi?.ragweedPollen + + pollen = Pollen().apply { + treePollenCount = when { + treePollenMeasure == null -> Pollen.PollenCount.UNKNOWN + treePollenMeasure < 15 -> Pollen.PollenCount.LOW + treePollenMeasure < 90 -> Pollen.PollenCount.MODERATE + treePollenMeasure < 1500 -> Pollen.PollenCount.HIGH + treePollenMeasure >= 1500 -> Pollen.PollenCount.VERY_HIGH + else -> Pollen.PollenCount.UNKNOWN + } + + grassPollenCount = when { + grassPollenMeasure == null -> Pollen.PollenCount.UNKNOWN + grassPollenMeasure < 5 -> Pollen.PollenCount.LOW + grassPollenMeasure < 20 -> Pollen.PollenCount.MODERATE + grassPollenMeasure < 200 -> Pollen.PollenCount.HIGH + grassPollenMeasure >= 200 -> Pollen.PollenCount.VERY_HIGH + else -> Pollen.PollenCount.UNKNOWN + } + + ragweedPollenCount = when { + ragweedPollenMeasure == null -> Pollen.PollenCount.UNKNOWN + ragweedPollenMeasure < 10 -> Pollen.PollenCount.LOW + ragweedPollenMeasure < 50 -> Pollen.PollenCount.MODERATE + ragweedPollenMeasure < 500 -> Pollen.PollenCount.HIGH + ragweedPollenMeasure >= 500 -> Pollen.PollenCount.VERY_HIGH + else -> Pollen.PollenCount.UNKNOWN + } + } + } +} + +fun createAtmosphere(current: Current): Atmosphere { + return Atmosphere().apply { + humidity = current.relativeHumidity2m + + // 1hPa = 1mb + current.pressureMsl?.let { + pressureMb = it + pressureIn = ConversionMethods.mbToInHg(it) + } + pressureTrend = "" + + current.dewPoint2m?.let { + dewpointC = it + dewpointF = ConversionMethods.CtoF(it) + } + + current.visibility?.let { + visibilityKm = it / 1000 + visibilityMi = ConversionMethods.kmToMi(visibilityKm) + } + } +} + +fun createPrecipitation(current: Current): Precipitation { + return Precipitation().apply { + pop = current.precipitationProbability + cloudiness = current.cloudCover + + current.rain?.let { + qpfRainMm = it + qpfRainIn = ConversionMethods.mmToIn(it) + } + + current.snowfall?.let { + qpfSnowCm = it + qpfSnowIn = ConversionMethods.mmToIn(it * 10) + } + } +} \ No newline at end of file diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderFactoryImpl.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderFactoryImpl.kt index b89fcaa0..c1e646e7 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderFactoryImpl.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderFactoryImpl.kt @@ -12,6 +12,7 @@ import com.thewizrd.weather_api.meteofrance.weather.MeteoFranceProvider import com.thewizrd.weather_api.meteomatics.weather.MeteomaticsWeatherProvider import com.thewizrd.weather_api.metno.MetnoWeatherProvider import com.thewizrd.weather_api.nws.NWSWeatherProvider +import com.thewizrd.weather_api.openmeteo.OpenMeteoWeatherProvider import com.thewizrd.weather_api.openweather.location.OpenWeatherMapLocationProvider import com.thewizrd.weather_api.openweather.weather.OpenWeatherMapProvider import com.thewizrd.weather_api.tomorrow.TomorrowIOWeatherProvider @@ -43,10 +44,11 @@ class WeatherProviderFactoryImpl : WeatherProviderFactory { WeatherAPI.DWD -> BrightSkyProvider() WeatherAPI.ECCC -> ECCCWeatherProvider() WeatherAPI.GOOGLE -> GoogleWeatherProvider() + WeatherAPI.OPENMETEO -> OpenMeteoWeatherProvider() else -> { if (!BuildConfig.DEBUG) { if (!BuildConfig.IS_NONGMS) - WeatherApiProvider() + OpenMeteoWeatherProvider() else MetnoWeatherProvider() } else { diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt index 7844fc39..166f2452 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt @@ -33,6 +33,7 @@ import com.thewizrd.weather_api.aqicn.AQICNProvider import com.thewizrd.weather_api.extras.isPremiumEnabled import com.thewizrd.weather_api.google.pollen.GooglePollenProvider import com.thewizrd.weather_api.nws.alerts.NWSAlertProvider +import com.thewizrd.weather_api.openmeteo.OpenMeteoWeatherProvider import com.thewizrd.weather_api.utils.RateLimitedRequest import com.thewizrd.weather_api.utils.logMissingIcon import com.thewizrd.weather_api.weatherModule @@ -203,6 +204,18 @@ abstract class WeatherProviderImpl : WeatherProvider, RateLimitedRequest { GooglePollenProvider().getPollenData(location)?.apply { attribution = context.getString(R.string.api_google) } + } else if (LocationUtils.isCAMSEuroCovered(location) && remoteConfigService.isProviderEnabled( + WeatherAPI.OPENMETEO + ) && (isPremiumEnabled() || BuildConfig.IS_NONGMS || settingsManager.isDevSettingsEnabled() && !settingsManager.getAPIKey( + WeatherAPI.OPENMETEO + ).isNullOrBlank()) + ) { + // Pollen coverage is only supported in Europe for Open-Meteo + // https://open-meteo.com/en/docs/air-quality-api + weather.condition!!.pollen = + OpenMeteoWeatherProvider().getPollenData(location)?.apply { + attribution = context.getString(R.string.api_openmeteo) + } } } } diff --git a/weather-api/src/nongms/java/com/thewizrd/weather_api/keys/Keys.java b/weather-api/src/nongms/java/com/thewizrd/weather_api/keys/Keys.java index 5ed9660b..db3c3414 100644 --- a/weather-api/src/nongms/java/com/thewizrd/weather_api/keys/Keys.java +++ b/weather-api/src/nongms/java/com/thewizrd/weather_api/keys/Keys.java @@ -60,4 +60,8 @@ public static String getWeatherBitIoKey() { public static String getGWeatherKey() { return null; } + + public static String getOpenMeteoKey() { + return null; + } } \ No newline at end of file From 373ca14d838573ced5a2b7514959ad962b635d30 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sun, 31 May 2026 20:32:28 -0400 Subject: [PATCH 16/67] HourlyForecast: remove wind data * This is already in extras --- .../viewmodels/HourlyForecastNowViewModel.kt | 4 +- .../main/WeatherChartsFragment.kt | 8 +-- ...AbstractWeatherWidgetPreferenceFragment.kt | 2 - .../controls/HourlyForecastItemViewModel.java | 8 +-- .../common/weatherdata/WeatherDataLoader.kt | 26 ++++++--- .../weatherdata/model/HourlyForecast.java | 54 ------------------- .../complications/WindComplicationService.kt | 9 ++-- .../tiles/layouts/DetailsWeatherTileLayout.kt | 5 +- .../accuweather/weather/WeatherData.kt | 3 -- .../weather_api/brightsky/WeatherData.kt | 23 ++++---- .../thewizrd/weather_api/eccc/WeatherData.kt | 14 ++--- .../weather_api/google/weather/WeatherData.kt | 14 ++--- .../weather_api/here/weather/WeatherData.kt | 14 ++--- .../meteofrance/weather/WeatherData.kt | 19 +++---- .../thewizrd/weather_api/metno/WeatherData.kt | 25 +++++---- .../thewizrd/weather_api/nws/WeatherData.kt | 10 ++-- .../openweather/weather/WeatherData.kt | 10 ++-- .../weather/onecall/WeatherData.kt | 10 ++-- .../weather_api/tomorrow/WeatherData.kt | 6 +-- .../weatherapi/weather/WeatherData.kt | 10 ++-- .../weather_api/weatherbit/WeatherData.kt | 6 --- .../weather_api/weatherkit/WeatherData.kt | 15 +++--- .../weatherunlocked/WeatherData.kt | 10 ++-- 23 files changed, 108 insertions(+), 197 deletions(-) diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/HourlyForecastNowViewModel.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/HourlyForecastNowViewModel.kt index f99f2529..104e1453 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/HourlyForecastNowViewModel.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/HourlyForecastNowViewModel.kt @@ -87,7 +87,7 @@ class HourlyForecastNowViewModel(forecast: HourlyForecast) { condition = if (wm.supportsWeatherLocale()) forecast.condition ?: context.getString(R.string.weather_notavailable) else wm.getWeatherCondition(forecast.icon) - if (forecast.windMph != null && forecast.windKph != null && forecast.windMph >= 0 && forecast.windDegrees != null && forecast.windDegrees >= 0) { + if (forecast.extras?.windMph != null && forecast.extras?.windKph != null && forecast.extras.windMph >= 0 && forecast.extras?.windDegrees != null && forecast.extras.windDegrees >= 0) { val unit = settingsManager.getSpeedUnit() val speedVal: Int val speedUnit: String @@ -116,7 +116,7 @@ class HourlyForecastNowViewModel(forecast: HourlyForecast) { } } - windDirection = forecast.windDegrees.getValueOrDefault(0) + 180 + windDirection = forecast.extras?.windDegrees.getValueOrDefault(0) + 180 windSpeed = String.format(LocaleUtils.getLocale(), "%d %s", speedVal, speedUnit) } diff --git a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherChartsFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherChartsFragment.kt index 595acfa5..fb836877 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/main/WeatherChartsFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/main/WeatherChartsFragment.kt @@ -17,7 +17,6 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.material.snackbar.BaseTransientBottomBar import com.thewizrd.common.helpers.SimpleRecyclerViewAdapterObserver import com.thewizrd.shared_resources.Constants -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.utils.AnalyticsLogger @@ -50,6 +49,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +import com.thewizrd.shared_resources.R as sharedRes class WeatherChartsFragment : CollapsingToolbarFragment() { private val wNowViewModel: WeatherNowViewModel by activityViewModels() @@ -310,8 +310,8 @@ class WeatherChartsFragment : CollapsingToolbarFragment() { if (hrfcasts.firstOrNull()?.extras?.pop != null || hrfcasts.lastOrNull()?.extras?.pop != null) { popData = ForecastGraphViewModel(ctx) } - if (hrfcasts.firstOrNull()?.windMph != null && hrfcasts.firstOrNull()?.windKph != null || - hrfcasts.lastOrNull()?.windMph != null && hrfcasts.lastOrNull()?.windKph != null + if (hrfcasts.firstOrNull()?.extras?.windMph != null && hrfcasts.firstOrNull()?.extras?.windKph != null || + hrfcasts.lastOrNull()?.extras?.windMph != null && hrfcasts.lastOrNull()?.extras?.windKph != null ) { windData = ForecastGraphViewModel(ctx) } @@ -344,7 +344,7 @@ class WeatherChartsFragment : CollapsingToolbarFragment() { } } if (windData != null) { - if (hrfcast.windMph != null && hrfcast.windKph != null) { + if (hrfcast.extras?.windMph != null && hrfcast.extras?.windKph != null) { windData.addForecastData( hrfcast, ForecastType.WIND, diff --git a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/AbstractWeatherWidgetPreferenceFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/AbstractWeatherWidgetPreferenceFragment.kt index 58bef469..e678ee32 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/AbstractWeatherWidgetPreferenceFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/widgets/preferences/AbstractWeatherWidgetPreferenceFragment.kt @@ -556,8 +556,6 @@ abstract class AbstractWeatherWidgetPreferenceFragment : ToolbarPreferenceFragme highC = 23f + index / 2f condition = getString(sharedRes.string.weather_sunny) icon = WeatherIcons.DAY_SUNNY - windMph = 5f - windKph = 8f extras = ForecastExtras().apply { feelslikeF = 80f feelslikeC = 26f diff --git a/common/src/main/java/com/thewizrd/common/controls/HourlyForecastItemViewModel.java b/common/src/main/java/com/thewizrd/common/controls/HourlyForecastItemViewModel.java index 27dd238d..88da7f5d 100644 --- a/common/src/main/java/com/thewizrd/common/controls/HourlyForecastItemViewModel.java +++ b/common/src/main/java/com/thewizrd/common/controls/HourlyForecastItemViewModel.java @@ -78,10 +78,10 @@ public HourlyForecastItemViewModel(@NonNull HourlyForecast forecast) { Logger.writeLine(Log.ERROR, nFe); } - if (forecast.getWindMph() != null && forecast.getWindKph() != null && forecast.getWindMph() >= 0 && - forecast.getWindDegrees() != null && forecast.getWindDegrees() >= 0) { - windDirection = NumberUtils.getValueOrDefault(forecast.getWindDegrees(), 0); - windDir = WeatherUtils.getWindDirection(forecast.getWindDegrees()); + if (forecast.getExtras() != null && forecast.getExtras().getWindMph() != null && forecast.getExtras().getWindKph() != null && forecast.getExtras().getWindMph() >= 0 && + forecast.getExtras().getWindDegrees() != null && forecast.getExtras().getWindDegrees() >= 0) { + windDirection = NumberUtils.getValueOrDefault(forecast.getExtras().getWindDegrees(), 0); + windDir = WeatherUtils.getWindDirection(forecast.getExtras().getWindDegrees()); final String unit = settingsMgr.getSpeedUnit(); int speedVal; diff --git a/common/src/main/java/com/thewizrd/common/weatherdata/WeatherDataLoader.kt b/common/src/main/java/com/thewizrd/common/weatherdata/WeatherDataLoader.kt index 7df770b8..9340fb5e 100644 --- a/common/src/main/java/com/thewizrd/common/weatherdata/WeatherDataLoader.kt +++ b/common/src/main/java/com/thewizrd/common/weatherdata/WeatherDataLoader.kt @@ -11,9 +11,20 @@ import com.thewizrd.shared_resources.exceptions.ErrorStatus import com.thewizrd.shared_resources.exceptions.WeatherException import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.remoteconfig.remoteConfigService -import com.thewizrd.shared_resources.utils.* +import com.thewizrd.shared_resources.utils.CommonActions +import com.thewizrd.shared_resources.utils.JSONParser +import com.thewizrd.shared_resources.utils.LocaleUtils +import com.thewizrd.shared_resources.utils.Logger import com.thewizrd.shared_resources.utils.NumberUtils.getValueOrDefault -import com.thewizrd.shared_resources.weatherdata.model.* +import com.thewizrd.shared_resources.utils.createUnsupportedLocationException +import com.thewizrd.shared_resources.utils.getBeaufortScale +import com.thewizrd.shared_resources.weatherdata.model.Beaufort +import com.thewizrd.shared_resources.weatherdata.model.Forecasts +import com.thewizrd.shared_resources.weatherdata.model.HourlyForecasts +import com.thewizrd.shared_resources.weatherdata.model.LocationType +import com.thewizrd.shared_resources.weatherdata.model.UV +import com.thewizrd.shared_resources.weatherdata.model.Weather +import com.thewizrd.shared_resources.weatherdata.model.WeatherAlert import com.thewizrd.weather_api.weatherModule import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ensureActive @@ -25,6 +36,7 @@ import java.time.ZonedDateTime import java.time.temporal.ChronoUnit import kotlin.coroutines.coroutineContext import kotlin.math.max +import kotlin.math.roundToInt class WeatherDataLoader { companion object { @@ -441,13 +453,13 @@ class WeatherDataLoader { weather.condition!!.tempF = hrf.highF weather.condition!!.tempC = hrf.highC - weather.condition!!.windMph = hrf.windMph - weather.condition!!.windKph = hrf.windKph - weather.condition!!.windDegrees = hrf.windDegrees + weather.condition!!.windMph = hrf.extras?.windMph + weather.condition!!.windKph = hrf.extras?.windKph + weather.condition!!.windDegrees = hrf.extras?.windDegrees - if (hrf.windMph != null) { + if (hrf.extras?.windMph != null) { weather.condition!!.beaufort = - Beaufort(getBeaufortScale(Math.round(hrf.windMph))) + Beaufort(getBeaufortScale(hrf.extras.windMph.roundToInt())) } weather.condition!!.feelslikeF = hrf.extras?.feelslikeF weather.condition!!.feelslikeC = hrf.extras?.feelslikeC diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/model/HourlyForecast.java b/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/model/HourlyForecast.java index 0cca633b..e342f46c 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/model/HourlyForecast.java +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/model/HourlyForecast.java @@ -19,15 +19,6 @@ public class HourlyForecast extends BaseForecast { - @Json(name = "wind_degrees") - private Integer windDegrees; - - @Json(name = "wind_mph") - private Float windMph; - - @Json(name = "wind_kph") - private Float windKph; - @Json(name = "date") private String _date; @@ -62,30 +53,6 @@ public void setDate(ZonedDateTime date) { _date = date.format(DateTimeUtils.getZonedDateTimeFormatter()); } - public Integer getWindDegrees() { - return windDegrees; - } - - public void setWindDegrees(Integer windDegrees) { - this.windDegrees = windDegrees; - } - - public Float getWindMph() { - return windMph; - } - - public void setWindMph(Float windMph) { - this.windMph = windMph; - } - - public Float getWindKph() { - return windKph; - } - - public void setWindKph(Float windKph) { - this.windKph = windKph; - } - @Override public void fromJson(@NonNull JsonReader extReader) { try { @@ -132,15 +99,6 @@ public void fromJson(@NonNull JsonReader extReader) { case "icon": this.icon = reader.nextString(); break; - case "wind_degrees": - this.windDegrees = NumberUtils.tryParseInt(reader.nextString()); - break; - case "wind_mph": - this.windMph = NumberUtils.tryParseFloat(reader.nextString()); - break; - case "wind_kph": - this.windKph = NumberUtils.tryParseFloat(reader.nextString()); - break; case "extras": this.extras = new ForecastExtras(); this.extras.fromJson(reader); @@ -184,18 +142,6 @@ public void toJson(@NonNull JsonWriter writer) { writer.name("icon"); writer.value(icon); - // "wind_degrees" : "" - writer.name("wind_degrees"); - writer.value(windDegrees); - - // "wind_mph" : "" - writer.name("wind_mph"); - writer.value(windMph); - - // "wind_kph" : "" - writer.name("wind_kph"); - writer.value(windKph); - // "extras" : "" if (extras != null) { writer.name("extras"); diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WindComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WindComplicationService.kt index cc49e248..09eed361 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WindComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WindComplicationService.kt @@ -13,7 +13,6 @@ import androidx.wear.watchface.complications.data.SmallImage import androidx.wear.watchface.complications.data.SmallImageComplicationData import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.utils.ImageUtils -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.Colors @@ -24,8 +23,8 @@ import com.thewizrd.shared_resources.utils.Units import com.thewizrd.shared_resources.utils.getWindDirection import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R import kotlin.math.roundToInt +import com.thewizrd.shared_resources.R as sharedRes class WindComplicationService : WeatherHourlyForecastComplicationService() { companion object { @@ -135,9 +134,9 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { return null } - val windMph = weather.condition?.windMph ?: hourlyForecast?.windMph - val windKph = weather.condition?.windKph ?: hourlyForecast?.windKph - val windDirection = weather.condition?.windDegrees ?: hourlyForecast?.windDegrees + val windMph = weather.condition?.windMph ?: hourlyForecast?.extras?.windMph + val windKph = weather.condition?.windKph ?: hourlyForecast?.extras?.windKph + val windDirection = weather.condition?.windDegrees ?: hourlyForecast?.extras?.windDegrees if (windMph == null || windKph == null || windDirection == null || windMph < 0 || windKph < 0 || windDirection < 0) { return buildUpdate(dataType) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/DetailsWeatherTileLayout.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/DetailsWeatherTileLayout.kt index b7a8dcea..3855d5c8 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/DetailsWeatherTileLayout.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/layouts/DetailsWeatherTileLayout.kt @@ -62,7 +62,6 @@ import com.thewizrd.common.controls.WeatherDetailsType import com.thewizrd.common.controls.toUiModel import com.thewizrd.common.utils.ImageUtils import com.thewizrd.common.utils.ImageUtils.rotate -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.designer.initializeDependencies import com.thewizrd.shared_resources.designer.isInEditMode @@ -86,7 +85,6 @@ import com.thewizrd.shared_resources.weatherdata.model.Precipitation import com.thewizrd.shared_resources.weatherdata.model.UV import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.simpleweather.LaunchActivity -import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.preferences.DetailsWeatherTileUtils import com.thewizrd.simpleweather.ui.theme.wearTileColorScheme import com.thewizrd.simpleweather.ui.tiles.tools.WearPreviewDevices @@ -97,6 +95,7 @@ import java.time.LocalTime import java.time.ZonedDateTime import java.time.temporal.ChronoUnit import kotlin.random.Random +import com.thewizrd.shared_resources.R as sharedRes internal const val ID_DETAIL_ICON_PREFIX = "detail_icon:" internal const val ID_ROTATION_PREFIX = "rotation:" @@ -806,8 +805,6 @@ private fun buildMockWeatherData(): Weather { highC = 23f + index / 2f condition = "Sunny" icon = WeatherIcons.DAY_SUNNY - windMph = 5f - windKph = 8f extras = ForecastExtras().apply { feelslikeF = 80f feelslikeC = 26f diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/accuweather/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/accuweather/weather/WeatherData.kt index f12aa03c..c15644f1 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/accuweather/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/accuweather/weather/WeatherData.kt @@ -204,10 +204,7 @@ fun createHourlyForecast(hourly: HourlyResponseItem): HourlyForecast { hourly.wind?.speed?.value?.let { extras.windKph = it - windKph = it - extras.windMph = ConversionMethods.kphTomph(it) - windMph = extras.windMph } extras.windDegrees = hourly.wind?.direction?.degrees?.roundToInt() diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/brightsky/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/brightsky/WeatherData.kt index b30e4fb5..b44747ec 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/brightsky/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/brightsky/WeatherData.kt @@ -232,22 +232,12 @@ fun createHourlyForecast(hr_forecast: WeatherItem): HourlyForecast { highF = ConversionMethods.CtoF(it) highC = it } - windDegrees = hr_forecast.windDirection?.roundToInt() - hr_forecast.windSpeed?.let { - windMph = ConversionMethods.kphTomph(it) - windKph = it - } icon = hr_forecast.icon // Extras val humidity = hr_forecast.relativeHumidity?.roundToInt() extras = ForecastExtras() - if (highF != null && windMph != null && humidity != null) { - val feelsLikeF = getFeelsLikeTemp(highF, windMph, humidity) - extras.feelslikeF = feelsLikeF - extras.feelslikeC = ConversionMethods.FtoC(feelsLikeF) - } extras.humidity = humidity hr_forecast.dewPoint?.let { extras.dewpointF = ConversionMethods.CtoF(it) @@ -260,9 +250,11 @@ fun createHourlyForecast(hr_forecast: WeatherItem): HourlyForecast { extras.pressureIn = ConversionMethods.mbToInHg(it) extras.pressureMb = it } - extras.windDegrees = windDegrees - extras.windMph = windMph - extras.windKph = windKph + extras.windDegrees = hr_forecast.windDirection?.roundToInt() + hr_forecast.windSpeed?.let { + extras.windMph = ConversionMethods.kphTomph(it) + extras.windKph = it + } hr_forecast.windGustSpeed?.let { extras.windGustMph = ConversionMethods.kphTomph(it) extras.windGustKph = it @@ -271,6 +263,11 @@ fun createHourlyForecast(hr_forecast: WeatherItem): HourlyForecast { extras.visibilityMi = ConversionMethods.kmToMi(it / 1000f) extras.visibilityKm = it / 1000f } + if (highF != null && extras.windMph != null && humidity != null) { + val feelsLikeF = getFeelsLikeTemp(highF, extras.windMph, humidity) + extras.feelslikeF = feelsLikeF + extras.feelslikeC = ConversionMethods.FtoC(feelsLikeF) + } } } diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/eccc/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/eccc/WeatherData.kt index 66deb9a6..95107519 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/eccc/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/eccc/WeatherData.kt @@ -188,12 +188,6 @@ fun createHourlyForecast(item: HourlyItem): HourlyForecast { highF = item.temperature?.imperial?.toFloatOrNull() highC = item.temperature?.metric?.toFloatOrNull() - windDegrees = item.windDir?.let { - getWindDirection(it) - } - windMph = item.windSpeed?.imperial?.toFloatOrNull() - windKph = item.windSpeed?.metric?.toFloatOrNull() - icon = item.iconCode condition = item.condition @@ -202,9 +196,11 @@ fun createHourlyForecast(item: HourlyItem): HourlyForecast { extras.feelslikeF = item.feelsLike?.imperial?.toFloatOrNull() extras.feelslikeC = item.feelsLike?.metric?.toFloatOrNull() extras.pop = item.precip?.toIntOrNull() - extras.windDegrees = windDegrees - extras.windMph = windMph - extras.windKph = windKph + extras.windDegrees = item.windDir?.let { + getWindDirection(it) + } + extras.windMph = item.windSpeed?.imperial?.toFloatOrNull() + extras.windKph = item.windSpeed?.metric?.toFloatOrNull() extras.windGustMph = item.windGust?.imperial?.toFloatOrNull() extras.windGustKph = item.windGust?.metric?.toFloatOrNull() extras.uvIndex = item.uv?.index?.toFloatOrNull() diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherData.kt index e870ec3e..719a1468 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/google/weather/WeatherData.kt @@ -258,12 +258,6 @@ fun createHourlyForecast(hour: ForecastHoursItem): HourlyForecast { icon = wm.getWeatherIcon(hour.isDaytime?.not() ?: false, hour.weatherCondition?.type) condition = hour.weatherCondition?.description?.text - windDegrees = hour.wind?.direction?.degrees - hour.wind?.speed?.value?.let { - windKph = it - windMph = ConversionMethods.kphTomph(it) - } - extras = ForecastExtras() hour.feelsLikeTemperature?.degrees?.let { extras.feelslikeC = it @@ -284,9 +278,11 @@ fun createHourlyForecast(hour: ForecastHoursItem): HourlyForecast { extras.pressureMb = it extras.pressureIn = ConversionMethods.mbToInHg(it) } - extras.windDegrees = windDegrees - extras.windKph = windKph - extras.windMph = windMph + extras.windDegrees = hour.wind?.direction?.degrees + hour.wind?.speed?.value?.let { + extras.windKph = it + extras.windMph = ConversionMethods.kphTomph(it) + } hour.wind?.gust?.value?.let { extras.windGustKph = it extras.windGustMph = ConversionMethods.kphTomph(it) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/here/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/here/weather/WeatherData.kt index 68f6b40e..a76580b8 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/here/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/here/weather/WeatherData.kt @@ -201,12 +201,6 @@ fun createHourlyForecast(hr_forecast: ForecastsItem): HourlyForecast { hr_forecast.iconName ) - windDegrees = hr_forecast.windDirection?.toIntOrNull() - hr_forecast.windSpeed?.toFloatOrNull()?.let { - windMph = it - windKph = ConversionMethods.mphTokph(it) - } - // Extras extras = ForecastExtras() hr_forecast.comfort?.toFloatOrNull()?.let { @@ -237,9 +231,11 @@ fun createHourlyForecast(hr_forecast: ForecastsItem): HourlyForecast { extras.pressureIn = it extras.pressureMb = ConversionMethods.inHgToMB(it) } - extras.windDegrees = windDegrees - extras.windMph = windMph - extras.windKph = windKph + extras.windDegrees = hr_forecast.windDirection?.toIntOrNull() + hr_forecast.windSpeed?.toFloatOrNull()?.let { + extras.windMph = it + extras.windKph = ConversionMethods.mphTokph(it) + } } } diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/WeatherData.kt index 4c4b5d4c..5e69c73b 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/WeatherData.kt @@ -76,7 +76,7 @@ fun createWeatherData(currRoot: CurrentsResponse, foreRoot: ForecastResponse, condition!!.feelslikeC = ConversionMethods.FtoC(condition!!.feelslikeF) } - if ((condition?.highF == null || condition?.highC == null) && forecast!!.size > 0) { + if ((condition?.highF == null || condition?.highC == null) && forecast!!.isNotEmpty()) { condition!!.highF = forecast!![0].highF condition!!.highC = forecast!![0].highC condition!!.lowF = forecast!![0].lowF @@ -188,16 +188,13 @@ fun createHourlyForecast(forecast: ForecastItem, if (forecast.wind != null) { if (forecast.wind!!.speed != null && forecast.wind!!.direction != null) { - windDegrees = forecast.wind!!.direction - windKph = ConversionMethods.msecToKph(forecast.wind!!.speed!!.toFloat()) - windMph = ConversionMethods.msecToMph(forecast.wind!!.speed!!.toFloat()) - extras.windDegrees = windDegrees - extras.windMph = windMph - extras.windKph = windKph + extras.windDegrees = forecast.wind!!.direction + extras.windMph = ConversionMethods.msecToMph(forecast.wind!!.speed!!) + extras.windKph = ConversionMethods.msecToKph(forecast.wind!!.speed!!) } if (forecast.wind!!.gust != null) { - extras.windGustKph = ConversionMethods.msecToKph(forecast.wind!!.gust!!.toFloat()) - extras.windGustMph = ConversionMethods.msecToMph(forecast.wind!!.gust!!.toFloat()) + extras.windGustKph = ConversionMethods.msecToKph(forecast.wind!!.gust!!) + extras.windGustMph = ConversionMethods.msecToMph(forecast.wind!!.gust!!) } } @@ -317,9 +314,9 @@ fun createCondition(currRoot: CurrentsResponse): Condition { windDegrees = currRoot.observation!!.wind!!.direction if (currRoot.observation!!.wind!!.speed != null) { windKph = - ConversionMethods.msecToKph(currRoot.observation!!.wind!!.speed!!.toFloat()) + ConversionMethods.msecToKph(currRoot.observation!!.wind!!.speed!!) windMph = - ConversionMethods.msecToMph(currRoot.observation!!.wind!!.speed!!.toFloat()) + ConversionMethods.msecToMph(currRoot.observation!!.wind!!.speed!!) } } diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/metno/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/metno/WeatherData.kt index 4301e0ba..3128fdf9 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/metno/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/metno/WeatherData.kt @@ -27,6 +27,7 @@ import java.time.ZonedDateTime import java.time.format.DateTimeFormatter import java.time.temporal.ChronoUnit import java.util.Locale +import kotlin.math.roundToInt fun createWeatherData( foreRoot: Response, @@ -254,9 +255,9 @@ fun createHourlyForecast(hr_forecast: TimeseriesItem): HourlyForecast { ) highF = ConversionMethods.CtoF(hr_forecast.data.instant.details.airTemperature) highC = hr_forecast.data.instant.details.airTemperature - windDegrees = Math.round(hr_forecast.data.instant.details.windFromDirection) - windMph = ConversionMethods.msecToMph(hr_forecast.data.instant.details.windSpeed) - windKph = ConversionMethods.msecToKph(hr_forecast.data.instant.details.windSpeed) + val windDegrees = hr_forecast.data.instant.details.windFromDirection.roundToInt() + val windMph = ConversionMethods.msecToMph(hr_forecast.data.instant.details.windSpeed) + val windKph = ConversionMethods.msecToKph(hr_forecast.data.instant.details.windSpeed) if (hr_forecast.data.next1Hours != null) { icon = hr_forecast.data.next1Hours.summary.symbolCode @@ -269,23 +270,25 @@ fun createHourlyForecast(hr_forecast: TimeseriesItem): HourlyForecast { val humidity = hr_forecast.data.instant.details.relativeHumidity // Extras extras = ForecastExtras() - extras.feelslikeF = getFeelsLikeTemp(highF, windMph, Math.round(humidity)) - extras.feelslikeC = ConversionMethods.FtoC(getFeelsLikeTemp(highF, windMph, Math.round(humidity))) - extras.humidity = Math.round(humidity) + extras.feelslikeF = getFeelsLikeTemp(highF, windMph, humidity.roundToInt()) + extras.feelslikeC = + ConversionMethods.FtoC(getFeelsLikeTemp(highF, windMph, humidity.roundToInt())) + extras.humidity = humidity.roundToInt() extras.dewpointF = ConversionMethods.CtoF(hr_forecast.data.instant.details.dewPointTemperature) extras.dewpointC = hr_forecast.data.instant.details.dewPointTemperature if (hr_forecast.data.instant.details.cloudAreaFraction != null) { - extras.cloudiness = Math.round(hr_forecast.data.instant.details.cloudAreaFraction) + extras.cloudiness = hr_forecast.data.instant.details.cloudAreaFraction.roundToInt() } // Precipitation if (hr_forecast.data.instant.details.probabilityOfPrecipitation != null) { - extras.pop = Math.round(hr_forecast.data.instant.details.probabilityOfPrecipitation) + extras.pop = hr_forecast.data.instant.details.probabilityOfPrecipitation.roundToInt() } else if (hr_forecast.data?.next1Hours?.details?.probabilityOfPrecipitation != null) { - extras.pop = Math.round(hr_forecast.data.next1Hours.details.probabilityOfPrecipitation) + extras.pop = hr_forecast.data.next1Hours.details.probabilityOfPrecipitation.roundToInt() } else if (hr_forecast.data?.next6Hours?.details?.probabilityOfPrecipitation != null) { - extras.pop = Math.round(hr_forecast.data.next6Hours.details.probabilityOfPrecipitation) + extras.pop = hr_forecast.data.next6Hours.details.probabilityOfPrecipitation.roundToInt() } else if (hr_forecast.data?.next12Hours?.details?.probabilityOfPrecipitation != null) { - extras.pop = Math.round(hr_forecast.data.next12Hours.details.probabilityOfPrecipitation) + extras.pop = + hr_forecast.data.next12Hours.details.probabilityOfPrecipitation.roundToInt() } extras.pressureIn = ConversionMethods.mbToInHg(hr_forecast.data.instant.details.airPressureAtSeaLevel) extras.pressureMb = hr_forecast.data.instant.details.airPressureAtSeaLevel diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/nws/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/nws/WeatherData.kt index 8151e253..31699e5b 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/nws/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/nws/WeatherData.kt @@ -288,13 +288,9 @@ fun createHourlyForecast(forecastItem: PeriodItem, adjustDate: Boolean = false): val windSpeed = forecastItem.windSpeed?.toFloatOrNull() val windDirection = forecastItem.windDirection?.toIntOrNull() if (windSpeed != null && windDirection != null) { - windDegrees = windDirection - windMph = windSpeed - windKph = ConversionMethods.mphTokph(windMph) - - extras.windDegrees = windDegrees - extras.windMph = windMph - extras.windKph = windKph + extras.windDegrees = windDirection + extras.windMph = windSpeed + extras.windKph = ConversionMethods.mphTokph(windSpeed) } forecastItem.windChill?.toFloatOrNull()?.let { diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/WeatherData.kt index 7287b0a0..97f339e5 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/WeatherData.kt @@ -140,10 +140,6 @@ fun createHourlyForecast(hr_forecast: ListItem): HourlyForecast { icon = weatherModule.weatherManager.getWeatherProvider(WeatherAPI.OPENWEATHERMAP) .getWeatherIcon(hr_forecast.weather[0].id.toString() + dn) - windDegrees = hr_forecast.wind.deg.roundToInt() - windMph = ConversionMethods.msecToMph(hr_forecast.wind.speed) - windKph = ConversionMethods.msecToKph(hr_forecast.wind.speed) - // Extras extras = ForecastExtras() extras.humidity = hr_forecast.main.humidity @@ -151,9 +147,9 @@ fun createHourlyForecast(hr_forecast: ListItem): HourlyForecast { // 1hPA = 1mbar extras.pressureMb = hr_forecast.main.pressure extras.pressureIn = ConversionMethods.mbToInHg(hr_forecast.main.pressure) - extras.windDegrees = windDegrees - extras.windMph = windMph - extras.windKph = windKph + extras.windDegrees = hr_forecast.wind.deg.roundToInt() + extras.windMph = ConversionMethods.msecToMph(hr_forecast.wind.speed) + extras.windKph = ConversionMethods.msecToKph(hr_forecast.wind.speed) if (highC > 0 && highC < 60 && hr_forecast.main.humidity > 1) { extras.dewpointC = calculateDewpointC(highC, hr_forecast.main.humidity) extras.dewpointF = ConversionMethods.CtoF(extras.dewpointC) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/onecall/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/onecall/WeatherData.kt index 70f8be93..f8011565 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/onecall/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/onecall/WeatherData.kt @@ -134,10 +134,6 @@ fun createHourlyForecast(hr_forecast: HourlyItem): HourlyForecast { icon = weatherModule.weatherManager.getWeatherProvider(WeatherAPI.OPENWEATHERMAP) .getWeatherIcon(hr_forecast.weather[0].id.toString() + dn) - windDegrees = hr_forecast.windDeg - windMph = ConversionMethods.msecToMph(hr_forecast.windSpeed) - windKph = ConversionMethods.msecToKph(hr_forecast.windSpeed) - // Extras extras = ForecastExtras() extras.feelslikeF = ConversionMethods.KtoF(hr_forecast.feelsLike) @@ -152,9 +148,9 @@ fun createHourlyForecast(hr_forecast: HourlyItem): HourlyForecast { // 1hPA = 1mbar extras.pressureMb = hr_forecast.pressure extras.pressureIn = ConversionMethods.mbToInHg(hr_forecast.pressure) - extras.windDegrees = windDegrees - extras.windMph = windMph - extras.windKph = windKph + extras.windDegrees = hr_forecast.windDeg + extras.windMph = ConversionMethods.msecToMph(hr_forecast.windSpeed) + extras.windKph = ConversionMethods.msecToKph(hr_forecast.windSpeed) if (hr_forecast.windGust != null) { extras.windGustMph = ConversionMethods.msecToMph(hr_forecast.windGust) extras.windGustKph = ConversionMethods.msecToKph(hr_forecast.windGust) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/WeatherData.kt index c8dd8f1f..2464d8a9 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/WeatherData.kt @@ -259,11 +259,11 @@ fun createHourlyForecast(item: IntervalsItem): HourlyForecast { extras.pressureIn = ConversionMethods.mbToInHg(it) } - extras.windDegrees = item.values.windDirection?.roundToInt()?.also { windDegrees = it } + extras.windDegrees = item.values.windDirection?.roundToInt() item.values.windSpeed?.let { speed -> - extras.windMph = ConversionMethods.msecToMph(speed).also { windMph = it } - extras.windKph = ConversionMethods.msecToKph(speed).also { windKph = it } + extras.windMph = ConversionMethods.msecToMph(speed) + extras.windKph = ConversionMethods.msecToKph(speed) } item.values.windGust?.let { diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt index ceb9257c..717571d8 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt @@ -164,10 +164,6 @@ fun createHourlyForecast(hour: HourItem, tzId: ZoneId): HourlyForecast { icon = weatherModule.weatherManager.getWeatherProvider(WeatherAPI.WEATHERAPI) .getWeatherIcon(hour.isDay == 0, hour.condition!!.code!!.toString()) - windMph = hour.windMph - windKph = hour.windKph - windDegrees = hour.windDegree - extras = ForecastExtras() extras.feelslikeF = hour.feelslikeF extras.feelslikeC = hour.feelslikeC @@ -183,9 +179,9 @@ fun createHourlyForecast(hour: HourItem, tzId: ZoneId): HourlyForecast { extras.qpfSnowIn = hour.snowCm?.let { ConversionMethods.mmToIn(it * 10) } extras.pressureIn = hour.pressureIn extras.pressureMb = hour.pressureMb - extras.windDegrees = windDegrees - extras.windMph = windMph - extras.windKph = windKph + extras.windDegrees = hour.windDegree + extras.windMph = hour.windMph + extras.windKph = hour.windKph extras.visibilityMi = hour.visMiles extras.visibilityKm = hour.visKm extras.windGustMph = hour.gustMph diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherbit/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherbit/WeatherData.kt index c333581e..1298a83a 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherbit/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherbit/WeatherData.kt @@ -180,12 +180,6 @@ fun createHourlyForecast(forecast: HourlyForecastDataItem): HourlyForecast { icon = weatherModule.weatherManager.getWeatherProvider(WeatherAPI.WEATHERBITIO) .getWeatherIcon(forecast.weather?.icon) - windDegrees = forecast.windDir - forecast.windSpd?.let { - windKph = ConversionMethods.msecToKph(it) - windMph = ConversionMethods.msecToMph(it) - } - // Extras extras = ForecastExtras() extras.humidity = forecast.rh diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherData.kt index ad331404..58a3497d 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherData.kt @@ -1,5 +1,6 @@ package com.thewizrd.weather_api.weatherkit +import com.thewizrd.shared_resources.R import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.ConversionMethods import com.thewizrd.shared_resources.utils.DateTimeUtils @@ -9,11 +10,17 @@ import com.thewizrd.shared_resources.weatherdata.model.* import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.MoonPhase.MoonPhaseType import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.shared_resources.R import com.thewizrd.weather_api.weatherModule import java.time.LocalDateTime import java.time.ZonedDateTime +import kotlin.apply +import kotlin.collections.ArrayList +import kotlin.collections.firstOrNull +import kotlin.collections.forEach +import kotlin.let import kotlin.math.roundToInt +import kotlin.run +import kotlin.runCatching fun createWeatherData(root: com.thewizrd.weather_api.weatherkit.Weather): Weather { return Weather().apply { @@ -145,10 +152,6 @@ fun createHourlyForecast(hour: HourWeatherConditions): HourlyForecast { condition = weatherModule.weatherManager.getWeatherProvider(WeatherAPI.APPLE) .getWeatherCondition(hour.conditionCode) - windKph = hour.windSpeed - windMph = ConversionMethods.kphTomph(hour.windSpeed) - windDegrees = hour.windDirection - extras = ForecastExtras().apply { feelslikeC = hour.temperatureApparent feelslikeF = ConversionMethods.CtoF(hour.temperatureApparent) @@ -176,7 +179,7 @@ fun createHourlyForecast(hour: HourWeatherConditions): HourlyForecast { pressureIn = ConversionMethods.mbToInHg(hour.pressure) windDegrees = hour.windDirection windKph = hour.windSpeed - windMph = ConversionMethods.kphToMsec(hour.windSpeed) + windMph = ConversionMethods.kphTomph(hour.windSpeed) visibilityKm = hour.visibility / 1000 visibilityMi = ConversionMethods.kmToMi(hour.visibility / 1000) windGustKph = hour.windGust diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherunlocked/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherunlocked/WeatherData.kt index 013e567e..65d910a6 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherunlocked/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherunlocked/WeatherData.kt @@ -144,19 +144,15 @@ fun createHourlyForecast(timeframe: TimeframesItem): HourlyForecast { condition = timeframe.wxDesc icon = timeframe.wxCode.toString() - windDegrees = timeframe.winddirDeg.roundToInt() - windMph = timeframe.windspdMph - windKph = timeframe.windspdKmh - // Extras extras = ForecastExtras() extras.humidity = timeframe.humidPct.roundToInt() extras.cloudiness = timeframe.cloudtotalPct.roundToInt() extras.pressureMb = timeframe.slpMb extras.pressureIn = timeframe.slpIn - extras.windDegrees = windDegrees - extras.windMph = windMph - extras.windKph = windKph + extras.windDegrees = timeframe.winddirDeg.roundToInt() + extras.windMph = timeframe.windspdMph + extras.windKph = timeframe.windspdKmh extras.dewpointF = timeframe.dewpointF extras.dewpointC = timeframe.dewpointC extras.feelslikeF = timeframe.feelslikeF From 3e2dbd14cc37f99d44387f0c5d9d911b9bc387b7 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sun, 31 May 2026 21:54:19 -0400 Subject: [PATCH 17/67] ForecastsNowViewModel: filter out past minutely data --- .../controls/viewmodels/ForecastsNowViewModel.kt | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastsNowViewModel.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastsNowViewModel.kt index d60ed05c..7e8bc1a4 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastsNowViewModel.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastsNowViewModel.kt @@ -39,7 +39,7 @@ class ForecastsNowViewModel(app: Application) : AndroidViewModel(app) { private val weatherDAO = WeatherDatabase.getWeatherDAO(app.applicationContext) - private var forecastData = MutableStateFlow??>(null) + private var forecastData = MutableStateFlow?>(null) private var hourlyForecastsData = MutableStateFlow?>(null) private var minutelyForecastData = MutableStateFlow?>(null) @@ -86,7 +86,7 @@ class ForecastsNowViewModel(app: Application) : AndroidViewModel(app) { flowScope?.launch { currentForecastsData.collect { forecastData.emit(it.forecast) - minutelyForecastData.emit(it.minForecast) + minutelyForecastData.emit(minForecastMapper.apply(it)) } } @@ -123,13 +123,12 @@ class ForecastsNowViewModel(app: Application) : AndroidViewModel(app) { input?.map { HourlyForecastNowViewModel(it) } ?: emptyList() } - private val precipMinGraphMapper = Function?> { input -> - val hrInterval = weatherModule.weatherManager.getHourlyForecastInterval() + private val minForecastMapper = Function?> { input -> val now = ZonedDateTime.now( locationData?.tzOffset ?: ZoneOffset.UTC - ).minusHours((hrInterval * 0.5).toLong()).truncatedTo(ChronoUnit.HOURS) - input?.minForecast?.filter { !it.date.isBefore(now) }?.takeUnless { it.isEmpty() }?.take(60) + ).truncatedTo(ChronoUnit.HOURS) + input?.minForecast?.filter { !it.date.isBefore(now) } } override fun onCleared() { From c1ab38e4679af8b7d8a4c732458c4c26d1b18aef Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sun, 31 May 2026 21:55:00 -0400 Subject: [PATCH 18/67] gradle: java 21 --- app/build.gradle | 8 ++++---- build.gradle | 4 ++-- common/build.gradle | 6 +++--- shared_resources/build.gradle | 6 +++--- wearapp/build.gradle | 6 +++--- weather-api/build.gradle | 6 +++--- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index a42a8929..0cbad4ac 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,7 +21,7 @@ android { versionName "5.13.0" vectorDrawables { - useSupportLibrary true + useSupportLibrary = true } } @@ -53,12 +53,12 @@ android { // Flag to enable support for the new language APIs coreLibraryDesugaringEnabled true // Sets Java compatibility to Java 8 - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 } kotlin { - jvmToolchain(17) + jvmToolchain(21) } sourceSets { diff --git a/build.gradle b/build.gradle index 61ef7560..3cf77e03 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ buildscript { repositories { mavenCentral() google() - maven { url 'https://jitpack.io' } + maven { url = 'https://jitpack.io' } } dependencies { @@ -27,7 +27,7 @@ allprojects { repositories { mavenCentral() google() - maven { url 'https://jitpack.io' } + maven { url = 'https://jitpack.io' } } } diff --git a/common/build.gradle b/common/build.gradle index 4c185d06..1e51e16b 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -32,12 +32,12 @@ android { compileOptions { // Flag to enable support for the new language APIs coreLibraryDesugaringEnabled true - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 } kotlin { - jvmToolchain(17) + jvmToolchain(21) } flavorDimensions 'gms' diff --git a/shared_resources/build.gradle b/shared_resources/build.gradle index 7ef8927c..23315215 100644 --- a/shared_resources/build.gradle +++ b/shared_resources/build.gradle @@ -43,12 +43,12 @@ android { // Flag to enable support for the new language APIs coreLibraryDesugaringEnabled true // Sets Java compatibility to Java 8 - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 } kotlin { - jvmToolchain(17) + jvmToolchain(21) } room { diff --git a/wearapp/build.gradle b/wearapp/build.gradle index d90eb272..407916bd 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -62,8 +62,8 @@ android { // Flag to enable support for the new language APIs coreLibraryDesugaringEnabled true // Sets Java compatibility to Java 8 - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 } composeOptions { @@ -71,7 +71,7 @@ android { } kotlin { - jvmToolchain(17) + jvmToolchain(21) } sourceSets { diff --git a/weather-api/build.gradle b/weather-api/build.gradle index 378373a5..6dcf5793 100644 --- a/weather-api/build.gradle +++ b/weather-api/build.gradle @@ -43,12 +43,12 @@ android { compileOptions { // Flag to enable support for the new language APIs coreLibraryDesugaringEnabled true - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 } kotlin { - jvmToolchain(17) + jvmToolchain(21) } room { From 13dcd61a68c69904c60d1f279f0a337a0a35ace4 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sun, 31 May 2026 21:59:35 -0400 Subject: [PATCH 19/67] gradle: update dependencies --- gradle/libs.versions.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0cd6202c..bd7ff0cb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,7 +10,7 @@ ksp_version = "2.3.6" desugar_version = '2.1.5' -firebase_version = "34.13.0" +firebase_version = "34.14.0" firebaseCrashlyticsGradleVersion = "3.0.7" firebasePerfPluginVersion = "2.0.2" gms_location_version = '21.3.0' @@ -47,12 +47,12 @@ google_truth_version = '1.4.5' espresso_core_version = "3.7.0" material_version = "1.14.0" -material_compose_version = "1.5.0-alpha19" +material_compose_version = "1.5.0-alpha20" compose_compiler_version = '1.5.15' -compose_bom_version = "2026.05.00" +compose_bom_version = "2026.05.01" wear_version = "1.4.0" -wear_compose_version = "1.6.1" +wear_compose_version = "1.6.2" wear_input_version = '1.2.0' wear_tiles_version = "1.6.0" wear_watchface_version = "1.3.0" @@ -66,7 +66,7 @@ moshi_version = '1.15.2' okhttp_version = "5.3.2" timber_version = '5.0.1' -revcat_version = "10.6.0" +revcat_version = "10.7.0" [libraries] com-google-devtools-ksp-gradle-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp_version" } From 3363f94a19e5d4ce52f3d07744147c9fcb00d330 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Mon, 1 Jun 2026 01:27:05 -0400 Subject: [PATCH 20/67] wear: fix precipitation panel --- .../thewizrd/shared_resources/SharedModule.kt | 8 ++- .../WeatherMinutelyForecastPanel.kt | 47 +++++++++----- .../viewmodels/ForecastPanelsViewModel.kt | 1 + .../viewmodels/MinutelyForecastViewModel.kt | 63 ++++++++++--------- 4 files changed, 73 insertions(+), 46 deletions(-) diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/SharedModule.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/SharedModule.kt index ba5e9287..7d71f910 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/SharedModule.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/SharedModule.kt @@ -28,7 +28,13 @@ abstract class SharedModule { GMSSecurityProvider.installAsync(context) // Initialize logger - Logger.init(context) + runCatching { + Logger.init(context) + }.getOrElse { + if (!BuildConfig.DEBUG) { + throw it + } + } } open val httpClient: OkHttpClient by lazy { diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherMinutelyForecastPanel.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherMinutelyForecastPanel.kt index 4df48348..d4a5bd99 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherMinutelyForecastPanel.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherMinutelyForecastPanel.kt @@ -24,12 +24,12 @@ import androidx.wear.compose.material3.Icon import androidx.wear.compose.material3.MaterialTheme import androidx.wear.compose.material3.Text import androidx.wear.tooling.preview.devices.WearDevices -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.viewmodels.MinutelyForecastViewModel import java.time.ZonedDateTime import java.time.format.DateTimeFormatter +import com.thewizrd.shared_resources.R as sharedRes @Composable fun WeatherMinutelyForecastPanel( @@ -37,14 +37,16 @@ fun WeatherMinutelyForecastPanel( ) { WeatherMinutelyForecastPanel( date = model.date, - rainAmount = model.rainAmount + precipAmount = model.precipAmount, + isSnow = model.isSnow ) } @Composable private fun WeatherMinutelyForecastPanel( date: String? = null, - rainAmount: String? = null + precipAmount: String? = null, + isSnow: Boolean = false ) { Row( modifier = Modifier @@ -56,13 +58,19 @@ private fun WeatherMinutelyForecastPanel( ), verticalAlignment = Alignment.CenterVertically ) { - Text( + Column( modifier = Modifier .weight(1f), - textAlign = TextAlign.Center, - text = date ?: WeatherIcons.EM_DASH, - style = MaterialTheme.typography.bodyLarge - ) + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Text( + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + text = date ?: WeatherIcons.EM_DASH, + style = MaterialTheme.typography.bodyLarge + ) + } Column( modifier = Modifier .weight(1f), @@ -71,18 +79,25 @@ private fun WeatherMinutelyForecastPanel( ) { Text( modifier = Modifier - .weight(1f, false), + .fillMaxWidth() + .defaultMinSize(minHeight = 20.dp), textAlign = TextAlign.Center, - text = rainAmount ?: WeatherIcons.PLACEHOLDER, + text = precipAmount ?: WeatherIcons.PLACEHOLDER, style = MaterialTheme.typography.bodyLarge ) Icon( - modifier = Modifier - .weight(1f, false) - .size(20.dp), - painter = painterResource(sharedRes.drawable.wi_raindrop), + modifier = Modifier.size(20.dp), + painter = if (isSnow) { + painterResource(sharedRes.drawable.wi_snowflake_cold) + } else { + painterResource(sharedRes.drawable.wi_raindrop) + }, contentDescription = null, - tint = colorResource(id = sharedRes.color.colorSecondaryDark) + tint = if (isSnow) { + colorResource(id = sharedRes.color.colorSecondaryLight) + } else { + colorResource(id = sharedRes.color.colorSecondaryDark) + } ) } } @@ -132,7 +147,7 @@ fun PreviewWeatherMinutelyForecastPanel() { WeatherMinutelyForecastPanel( date = ZonedDateTime.now().format(fmt), - rainAmount = "1.00 mm" + precipAmount = "1.00 mm" ) } } \ No newline at end of file diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ForecastPanelsViewModel.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ForecastPanelsViewModel.kt index d043add3..3b49e194 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ForecastPanelsViewModel.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ForecastPanelsViewModel.kt @@ -89,6 +89,7 @@ class ForecastPanelsViewModel(app: Application) : AndroidViewModel(app) { flowScope?.launch { currentForecastsData.collect { forecasts.emit(forecastMapper.apply(it)) + minutelyForecasts.emit(minForecastMapper.apply(it)) } } flowScope?.launch { diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/MinutelyForecastViewModel.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/MinutelyForecastViewModel.kt index 5beee127..0ffead67 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/MinutelyForecastViewModel.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/MinutelyForecastViewModel.kt @@ -4,7 +4,6 @@ import android.text.format.DateFormat import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.R import com.thewizrd.shared_resources.appLib -import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.shared_resources.utils.ConversionMethods import com.thewizrd.shared_resources.utils.DateTimeUtils import com.thewizrd.shared_resources.utils.LocaleUtils @@ -14,7 +13,8 @@ import java.text.DecimalFormat class MinutelyForecastViewModel(minutely: MinutelyForecast) { val date: String - val rainAmount: String + val precipAmount: String + val isSnow: Boolean init { val context = appLib.context @@ -33,35 +33,38 @@ class MinutelyForecastViewModel(minutely: MinutelyForecast) { } date = minutely.date.format(fmt) - if (minutely.rainMm != null) { - val unit = settingsMgr.getPrecipitationUnit() - val precipValue: Float - val precipUnit: String + val raimMm = minutely.rainMm ?: 0f + val snowMm = minutely.snowMm ?: 0f + isSnow = snowMm > raimMm + val precipValueMm = if (isSnow) snowMm else raimMm - when (unit) { - Units.INCHES -> { - precipValue = ConversionMethods.mmToIn(minutely.rainMm) - precipUnit = context.getString(R.string.unit_in) - } - Units.MILLIMETERS -> { - precipValue = minutely.rainMm - precipUnit = context.getString(R.string.unit_mm) - } - else -> { - precipValue = ConversionMethods.mmToIn(minutely.rainMm) - precipUnit = context.getString(R.string.unit_in) - } + val unit = settingsMgr.getPrecipitationUnit() + val precipValue: Float + val precipUnit: String + + when (unit) { + Units.INCHES -> { + precipValue = ConversionMethods.mmToIn(precipValueMm) + precipUnit = context.getString(R.string.unit_in) } - rainAmount = String.format( - LocaleUtils.getLocale(), - "%s %s", - df.format(precipValue.toDouble()), - precipUnit - ) - } else { - rainAmount = WeatherIcons.EM_DASH + Units.MILLIMETERS -> { + precipValue = precipValueMm + precipUnit = context.getString(R.string.unit_mm) + } + + else -> { + precipValue = ConversionMethods.mmToIn(precipValueMm) + precipUnit = context.getString(R.string.unit_in) + } } + + precipAmount = String.format( + LocaleUtils.getLocale(), + "%s %s", + df.format(precipValue.toDouble()), + precipUnit + ) } override fun equals(other: Any?): Boolean { @@ -71,14 +74,16 @@ class MinutelyForecastViewModel(minutely: MinutelyForecast) { other as MinutelyForecastViewModel if (date != other.date) return false - if (rainAmount != other.rainAmount) return false + if (precipAmount != other.precipAmount) return false + if (isSnow != other.isSnow) return false return true } override fun hashCode(): Int { var result = date.hashCode() - result = 31 * result + rainAmount.hashCode() + result = 31 * result + precipAmount.hashCode() + result = 31 * result + isSnow.hashCode() return result } } \ No newline at end of file From 627b10274d2cd46273c867bb89fdc54dc03cf420 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Mon, 1 Jun 2026 01:32:30 -0400 Subject: [PATCH 21/67] WeatherNowScreen: layout rearrange testing * Add feels like too --- .../ui/weather/WeatherNowScreen.kt | 214 +++++++++++++----- 1 file changed, 160 insertions(+), 54 deletions(-) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt index 06e0e3a1..3761dabe 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt @@ -21,6 +21,7 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredSize @@ -44,6 +45,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.rotate import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.dimensionResource @@ -77,6 +79,7 @@ import androidx.wear.compose.material3.ScreenScaffold import androidx.wear.compose.material3.Text import androidx.wear.compose.navigation.rememberSwipeDismissableNavController import com.google.android.horologist.compose.layout.fillMaxRectangle +import com.thewizrd.common.controls.DetailItemViewModel import com.thewizrd.common.controls.ForecastItemViewModel import com.thewizrd.common.controls.HourlyForecastItemViewModel import com.thewizrd.common.controls.WeatherAlertViewModel @@ -200,24 +203,17 @@ fun WeatherNowScreen( isGPSLocation = uiState.isGPSLocation ) // Icon + Temp - IconTempRow( + CurrentConditionPanel( + curCondition = weather.curCondition, weatherIcon = weather.weatherIcon, iconProvider = weather.iconProvider, curTemp = weather.curTemp, - tempUnit = weather.tempUnit + tempUnit = weather.tempUnit, + hiTemp = weather.hiTemp, + loTemp = weather.loTemp, + showHiLo = weather.isShowHiLo, + feelsLikeDetail = weather.weatherDetailsMap[WeatherDetailsType.FEELSLIKE] ) - // Condition - weather.curCondition?.let { condition -> - ConditionText(condition) - } - - // HiLo Layout - if (weather.isShowHiLo) { - HiLoLayout( - hiTemp = weather.hiTemp, - loTemp = weather.loTemp - ) - } // Condition Details ConditionDetails( @@ -476,7 +472,7 @@ private fun ColumnScope.WeatherLocation( .align(Alignment.CenterVertically), text = locationName ?: WeatherIcons.EM_DASH, textAlign = TextAlign.Center, - fontSize = 16.sp, + fontSize = 14.sp, style = MaterialTheme.typography.labelLarge, maxLines = 2, overflow = TextOverflow.Ellipsis @@ -485,40 +481,150 @@ private fun ColumnScope.WeatherLocation( } @Composable -private fun IconTempRow( +private fun CurrentConditionPanel( weatherIcon: String, curTemp: String?, tempUnit: String?, - iconProvider: String? = null + iconProvider: String? = null, + curCondition: String? = null, + hiTemp: String? = null, + loTemp: String? = null, + showHiLo: Boolean = false, + feelsLikeDetail: DetailItemViewModel? = null ) { - Row( - modifier = Modifier.fillMaxWidth() + val isRound = LocalConfiguration.current.isScreenRound + + Column( + modifier = Modifier + .fillMaxWidth() + .padding( + horizontal = if (showHiLo) { + if (isRound) 16.dp else 4.dp + } else { + 0.dp + } + ) ) { - WeatherIcon( - modifier = Modifier - .height(60.dp) - .weight(1f) - .align(Alignment.CenterVertically), - alignment = IconAlignment.End, - weatherIcon = weatherIcon, - iconProvider = iconProvider, - shouldAnimate = true - ) - Spacer(modifier = Modifier.size(8.dp)) - Text( - modifier = Modifier - .weight(1f) - .align(Alignment.CenterVertically), - text = curTemp ?: WeatherIcons.PLACEHOLDER, - textAlign = TextAlign.Start, - maxLines = 1, - fontSize = 42.sp, - fontWeight = FontWeight.Light, - color = tempTextColor( - temp = curTemp, - tempUnit = tempUnit + if (curCondition != null) { + Text( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp), + text = curCondition, + textAlign = TextAlign.Center, + overflow = TextOverflow.Ellipsis, + letterSpacing = 0.sp, + maxLines = 2, + style = MaterialTheme.typography.bodySmall, ) - ) + } + Row( + modifier = Modifier.fillMaxWidth() + ) { + WeatherIcon( + modifier = Modifier + .weight(1f) + .apply { + if (showHiLo) { + heightIn(min = 24.dp, max = 52.dp) + } else { + height(60.dp) + } + } + .align(Alignment.CenterVertically), + alignment = IconAlignment.End, + weatherIcon = weatherIcon, + iconProvider = iconProvider, + shouldAnimate = true + ) + Spacer(modifier = Modifier.size(8.dp)) + Text( + modifier = Modifier + .weight(if (showHiLo) 2f else 1.5f) + .align(Alignment.CenterVertically), + text = curTemp ?: WeatherIcons.PLACEHOLDER, + textAlign = if (showHiLo) TextAlign.Center else TextAlign.Start, + maxLines = 1, + fontSize = if (showHiLo) 28.sp else 36.sp, + fontWeight = FontWeight.Light, + color = tempTextColor( + temp = curTemp, + tempUnit = tempUnit + ) + ) + if (showHiLo) { + Spacer(modifier = Modifier.size(8.dp)) + Column( + modifier = Modifier + .weight(1f) + .align(Alignment.CenterVertically), + horizontalAlignment = Alignment.End + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.End + ) { + Text( + text = hiTemp ?: WeatherIcons.PLACEHOLDER, + style = MaterialTheme.typography.bodySmall, + textAlign = TextAlign.End, + maxLines = 1 + ) + Text( + modifier = Modifier.padding(horizontal = 4.dp), + text = "↑", + style = MaterialTheme.typography.bodyExtraSmall, + fontWeight = FontWeight.SemiBold, + textAlign = TextAlign.End, + maxLines = 1, + color = Color(0xFFFF4500), + ) + } + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.End + ) { + Text( + text = loTemp ?: WeatherIcons.PLACEHOLDER, + style = MaterialTheme.typography.bodySmall, + textAlign = TextAlign.End, + maxLines = 1 + ) + Text( + modifier = Modifier.padding(horizontal = 4.dp), + text = "↓", + style = MaterialTheme.typography.bodyExtraSmall, + fontWeight = FontWeight.SemiBold, + textAlign = TextAlign.End, + maxLines = 1, + color = Color(0xFF87CEFA), + ) + } + } + } + } + // FeelsLike + feelsLikeDetail?.let { detail -> + Row( + modifier = Modifier.fillMaxWidth() + ) { + Text( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 4.dp), + text = buildString { + append(detail.label) + append(": ") + append(detail.value) + }, + textAlign = TextAlign.Center, + overflow = TextOverflow.Ellipsis, + letterSpacing = 0.sp, + maxLines = 1, + style = MaterialTheme.typography.bodySmall, + ) + } + } } } @@ -999,6 +1105,9 @@ private fun PreviewWeatherNowScreen() { } }.toUiModel() } + val feelsLikeDetail = remember { + DetailItemViewModel(WeatherDetailsType.FEELSLIKE, "71°") + } CompositionLocalProvider( LocalContentColor provides Color.White, @@ -1031,20 +1140,17 @@ private fun PreviewWeatherNowScreen() { Box( modifier = Modifier.background(Color.White.copy(alpha = 0.1f)) ) { - IconTempRow( + CurrentConditionPanel( + curCondition = "Sunny", weatherIcon = WeatherIcons.DAY_SUNNY, - curTemp = "70°F", - tempUnit = "F" + curTemp = "120°F", + tempUnit = "F", + showHiLo = true, + hiTemp = "110°", + loTemp = "80°", + feelsLikeDetail = feelsLikeDetail ) } - // Condition - ConditionText("Sunny") - - // HiLo Layout - HiLoLayout( - hiTemp = "70°", - loTemp = "60°" - ) // Condition Details ConditionDetails( From 06de1ac9f107f16d258c1776f27c5f791b86e25c Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Mon, 1 Jun 2026 01:32:46 -0400 Subject: [PATCH 22/67] SimpleWeather: v5.14.0-build0 --- app/build.gradle | 4 ++-- wearapp/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 0cbad4ac..2ad2d5b1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,8 +17,8 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get().toInteger() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code (Android: 0, WearOS: 1) // ex) 345100131 = (34, 5.10, 013, 0) - versionCode 365130150 - versionName "5.13.0" + versionCode 365140000 + versionName "5.14.0" vectorDrawables { useSupportLibrary = true diff --git a/wearapp/build.gradle b/wearapp/build.gradle index 407916bd..59c70289 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -16,8 +16,8 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code [Android: 0, WearOS: 1]) // ex) 345100131 = (34, 5.10, 013, 1) - versionCode 365130151 - versionName "5.13.0" + versionCode 365140001 + versionName "5.14.0" vectorDrawables { useSupportLibrary true From 9eb08c0d2b935d124b2b0dc09cf49aefc0fe09ec Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Tue, 2 Jun 2026 23:26:54 -0400 Subject: [PATCH 23/67] SimpleWeather: v5.14.0-build1 * keep capability resource --- app/build.gradle | 2 +- app/src/fullgms/res/raw/wear_keep.xml | 2 ++ app/src/fullgms/res/values/wear.xml | 4 ++-- wearapp/build.gradle | 2 +- wearapp/src/main/res/raw/wear_keep.xml | 2 ++ wearapp/src/main/res/values/wear.xml | 2 +- 6 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 app/src/fullgms/res/raw/wear_keep.xml create mode 100644 wearapp/src/main/res/raw/wear_keep.xml diff --git a/app/build.gradle b/app/build.gradle index 2ad2d5b1..4dedffda 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get().toInteger() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code (Android: 0, WearOS: 1) // ex) 345100131 = (34, 5.10, 013, 0) - versionCode 365140000 + versionCode 365140010 versionName "5.14.0" vectorDrawables { diff --git a/app/src/fullgms/res/raw/wear_keep.xml b/app/src/fullgms/res/raw/wear_keep.xml new file mode 100644 index 00000000..dd32bc1f --- /dev/null +++ b/app/src/fullgms/res/raw/wear_keep.xml @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/app/src/fullgms/res/values/wear.xml b/app/src/fullgms/res/values/wear.xml index 97a0b428..a8a910d5 100644 --- a/app/src/fullgms/res/values/wear.xml +++ b/app/src/fullgms/res/values/wear.xml @@ -1,6 +1,6 @@ - - + + com.thewizrd.simpleweather_phone_app \ No newline at end of file diff --git a/wearapp/build.gradle b/wearapp/build.gradle index 59c70289..a5a1c1e8 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -16,7 +16,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code [Android: 0, WearOS: 1]) // ex) 345100131 = (34, 5.10, 013, 1) - versionCode 365140001 + versionCode 365140011 versionName "5.14.0" vectorDrawables { diff --git a/wearapp/src/main/res/raw/wear_keep.xml b/wearapp/src/main/res/raw/wear_keep.xml new file mode 100644 index 00000000..dd32bc1f --- /dev/null +++ b/wearapp/src/main/res/raw/wear_keep.xml @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/wearapp/src/main/res/values/wear.xml b/wearapp/src/main/res/values/wear.xml index 5ab1ffd6..f9e36dcf 100644 --- a/wearapp/src/main/res/values/wear.xml +++ b/wearapp/src/main/res/values/wear.xml @@ -1,5 +1,5 @@ - + com.thewizrd.simpleweather_wear_app From 408799c2bc33b0f5dccc96100138ca0a44fca28b Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 6 Jun 2026 19:44:24 -0400 Subject: [PATCH 24/67] gradle: update dependencies --- gradle/libs.versions.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bd7ff0cb..cc3584a4 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,7 +24,7 @@ annotation_version = "1.10.0" activity_version = "1.13.0" appcompat_version = '1.7.1' constraintlayout_version = '2.2.1' -core_version = "1.18.0" +core_version = "1.19.0" arch_core_runtime_version = '2.2.0' fragment_version = '1.8.9' lifecycle_version = "2.10.0" @@ -47,7 +47,7 @@ google_truth_version = '1.4.5' espresso_core_version = "3.7.0" material_version = "1.14.0" -material_compose_version = "1.5.0-alpha20" +material_compose_version = "1.5.0-alpha21" compose_compiler_version = '1.5.15' compose_bom_version = "2026.05.01" @@ -66,7 +66,7 @@ moshi_version = '1.15.2' okhttp_version = "5.3.2" timber_version = '5.0.1' -revcat_version = "10.7.0" +revcat_version = "10.8.0" [libraries] com-google-devtools-ksp-gradle-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp_version" } From 7c373527e1bc92acaa1513e9fc32584adc6db2f3 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 6 Jun 2026 21:18:21 -0400 Subject: [PATCH 25/67] OpenMeteoWeatherProvider: fix --- .../openmeteo/OpenMeteoWeatherProvider.kt | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/OpenMeteoWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/OpenMeteoWeatherProvider.kt index 4ad8ecd2..2fdfdec0 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/OpenMeteoWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/OpenMeteoWeatherProvider.kt @@ -85,7 +85,7 @@ class OpenMeteoWeatherProvider : WeatherProviderImpl(), PollenProvider { } override fun isKeyRequired(): Boolean { - return !BuildConfig.IS_NONGMS + return BuildConfig.IS_NONGMS } override fun getAuthType(): AuthType { @@ -171,7 +171,7 @@ class OpenMeteoWeatherProvider : WeatherProviderImpl(), PollenProvider { // If were under rate limit, deny request checkRateLimit() - if (isKeyRequired() && key.isNullOrBlank()) { + if ((isKeyRequired() || getAuthType() == AuthType.INTERNAL) && key.isNullOrBlank()) { throw WeatherException(ErrorStatus.INVALIDAPIKEY) } @@ -210,14 +210,18 @@ class OpenMeteoWeatherProvider : WeatherProviderImpl(), PollenProvider { .appendQueryParameter("timeformat", "unixtime") .appendQueryParameter("timezone", "auto") .apply { - if (isKeyRequired()) { + if (isKeyRequired() || getAuthType() == AuthType.INTERNAL) { this.appendQueryParameter("apikey", key) } } .build() val forecastRequest = Request.Builder() - .cacheRequestIfNeeded(isKeyRequired(), 30, TimeUnit.MINUTES) + .cacheRequestIfNeeded( + (isKeyRequired() || getAuthType() == AuthType.INTERNAL), + 30, + TimeUnit.MINUTES + ) .url(forecastRequestUri.toString()) .header("Accept", "application/json") .build() @@ -232,14 +236,18 @@ class OpenMeteoWeatherProvider : WeatherProviderImpl(), PollenProvider { .appendQueryParameter("timeformat", "unixtime") .appendQueryParameter("timezone", "auto") .apply { - if (isKeyRequired()) { + if (isKeyRequired() || getAuthType() == AuthType.INTERNAL) { this.appendQueryParameter("apikey", key) } } .build() val aqiRequest = Request.Builder() - .cacheRequestIfNeeded(isKeyRequired(), 20, TimeUnit.MINUTES) + .cacheRequestIfNeeded( + (isKeyRequired() || getAuthType() == AuthType.INTERNAL), + 20, + TimeUnit.MINUTES + ) .url(aqiRequestUri.toString()) .header("Accept", "application/json") .build() @@ -310,7 +318,7 @@ class OpenMeteoWeatherProvider : WeatherProviderImpl(), PollenProvider { // If were under rate limit, deny request checkRateLimit() - if (isKeyRequired() && key.isNullOrBlank()) { + if ((isKeyRequired() || getAuthType() == AuthType.INTERNAL) && key.isNullOrBlank()) { throw WeatherException(ErrorStatus.INVALIDAPIKEY) } @@ -333,14 +341,18 @@ class OpenMeteoWeatherProvider : WeatherProviderImpl(), PollenProvider { .appendQueryParameter("timeformat", "unixtime") .appendQueryParameter("timezone", "auto") .apply { - if (isKeyRequired()) { + if (isKeyRequired() || getAuthType() == AuthType.INTERNAL) { this.appendQueryParameter("apikey", key) } } .build() val request = Request.Builder() - .cacheRequestIfNeeded(isKeyRequired(), 20, TimeUnit.MINUTES) + .cacheRequestIfNeeded( + isKeyRequired() || getAuthType() == AuthType.INTERNAL, + 20, + TimeUnit.MINUTES + ) .url(requestUri.toString()) .header("Accept", "application/json") .build() From 097a4378e052ee18ce27278b7db9cc731245e08f Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 6 Jun 2026 21:29:04 -0400 Subject: [PATCH 26/67] WeatherUnlockedProvider: services will be shutting down June 30th, 2026 --- app/src/main/res/xml/pref_credits.xml | 8 -------- .../src/fullgms/res/xml/remote_config_defaults.xml | 4 ++-- .../thewizrd/shared_resources/weatherdata/WeatherAPI.kt | 4 ---- wearapp/src/main/res/xml/pref_credits.xml | 5 ----- .../weatherunlocked/WeatherUnlockedProvider.kt | 1 + 5 files changed, 3 insertions(+), 19 deletions(-) diff --git a/app/src/main/res/xml/pref_credits.xml b/app/src/main/res/xml/pref_credits.xml index 89897671..850f6a8e 100644 --- a/app/src/main/res/xml/pref_credits.xml +++ b/app/src/main/res/xml/pref_credits.xml @@ -61,14 +61,6 @@ android:data="https://aqicn.org" /> - - - - diff --git a/shared_resources/src/fullgms/res/xml/remote_config_defaults.xml b/shared_resources/src/fullgms/res/xml/remote_config_defaults.xml index c21573b3..45e3378a 100644 --- a/shared_resources/src/fullgms/res/xml/remote_config_defaults.xml +++ b/shared_resources/src/fullgms/res/xml/remote_config_defaults.xml @@ -64,9 +64,9 @@ wunlocked { - "enabled": true, + "enabled": false, "locSource": "android", - "newWeatherSource": "" + "newWeatherSource": "weatherapi" } diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/WeatherAPI.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/WeatherAPI.kt index b308af6e..1ee33e69 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/WeatherAPI.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/weatherdata/WeatherAPI.kt @@ -156,10 +156,6 @@ object WeatherAPI { ProviderEntry( "Weatherbit.io", WEATHERBITIO, "https://www.weatherbit.io/", "https://www.weatherbit.io/pricing" - ), - ProviderEntry( - "WeatherUnlocked", WEATHERUNLOCKED, - "https://developer.weatherunlocked.com/", "https://developer.weatherunlocked.com/" ) ) } diff --git a/wearapp/src/main/res/xml/pref_credits.xml b/wearapp/src/main/res/xml/pref_credits.xml index cf865827..c4802601 100644 --- a/wearapp/src/main/res/xml/pref_credits.xml +++ b/wearapp/src/main/res/xml/pref_credits.xml @@ -41,11 +41,6 @@ android:widgetLayout="@layout/credit_waqi"> - - - diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherunlocked/WeatherUnlockedProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherunlocked/WeatherUnlockedProvider.kt index 4a8bd9fb..587114d3 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherunlocked/WeatherUnlockedProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherunlocked/WeatherUnlockedProvider.kt @@ -42,6 +42,7 @@ import java.time.ZonedDateTime import java.util.Locale import java.util.concurrent.TimeUnit +@Deprecated("Weather Unlocked API Services will be closing down on June 30th, 2026") class WeatherUnlockedProvider : WeatherProviderImpl() { companion object { private const val BASE_URL = "http://api.weatherunlocked.com/api/" From 4591ed909e4e11eb7ce3f7c74eb260b34c2d391c Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 6 Jun 2026 22:19:41 -0400 Subject: [PATCH 27/67] WeatherNowScreen: revert layout changes * Update divider * Keep feelsLike --- .../ui/components/WearDivider.kt | 15 +- .../ui/weather/WeatherNowScreen.kt | 239 ++++++------------ 2 files changed, 93 insertions(+), 161 deletions(-) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WearDivider.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WearDivider.kt index 2f4f73a7..5887671e 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WearDivider.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WearDivider.kt @@ -11,6 +11,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.PathEffect +import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -27,19 +28,21 @@ fun WearDivider() { .height(24.dp), contentAlignment = Alignment.Center ) { - val pathEffect = PathEffect.dashPathEffect(floatArrayOf(ctx.dpToPx(2f), ctx.dpToPx(4f))) + val strokeWidth = ctx.dpToPx(3f) + val pathEffect = PathEffect.dashPathEffect(floatArrayOf(0f, strokeWidth * 2)) Canvas( modifier = Modifier .width(48.dp) - .height(1.dp) + .height(4.dp) ) { drawLine( color = Color.White, - strokeWidth = ctx.dpToPx(2f), - start = Offset(0f, 0f), - end = Offset(size.width, 0f), - pathEffect = pathEffect + strokeWidth = strokeWidth, + start = Offset(0f, size.height / 2f), + end = Offset(size.width, size.height / 2f), + cap = StrokeCap.Round, + pathEffect = pathEffect, ) } } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt index 3761dabe..24f3d818 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt @@ -21,7 +21,6 @@ import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredSize @@ -45,7 +44,6 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.rotate import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.dimensionResource @@ -203,17 +201,28 @@ fun WeatherNowScreen( isGPSLocation = uiState.isGPSLocation ) // Icon + Temp - CurrentConditionPanel( - curCondition = weather.curCondition, + IconTempRow( weatherIcon = weather.weatherIcon, iconProvider = weather.iconProvider, curTemp = weather.curTemp, - tempUnit = weather.tempUnit, - hiTemp = weather.hiTemp, - loTemp = weather.loTemp, - showHiLo = weather.isShowHiLo, - feelsLikeDetail = weather.weatherDetailsMap[WeatherDetailsType.FEELSLIKE] + tempUnit = weather.tempUnit ) + // FeelsLike + weather.weatherDetailsMap[WeatherDetailsType.FEELSLIKE]?.let { + FeelsLikeText(it) + } + // Condition + weather.curCondition?.let { condition -> + ConditionText(condition) + } + + // HiLo Layout + if (weather.isShowHiLo) { + HiLoLayout( + hiTemp = weather.hiTemp, + loTemp = weather.loTemp + ) + } // Condition Details ConditionDetails( @@ -472,7 +481,7 @@ private fun ColumnScope.WeatherLocation( .align(Alignment.CenterVertically), text = locationName ?: WeatherIcons.EM_DASH, textAlign = TextAlign.Center, - fontSize = 14.sp, + fontSize = 16.sp, style = MaterialTheme.typography.labelLarge, maxLines = 2, overflow = TextOverflow.Ellipsis @@ -481,151 +490,66 @@ private fun ColumnScope.WeatherLocation( } @Composable -private fun CurrentConditionPanel( +private fun IconTempRow( weatherIcon: String, curTemp: String?, tempUnit: String?, - iconProvider: String? = null, - curCondition: String? = null, - hiTemp: String? = null, - loTemp: String? = null, - showHiLo: Boolean = false, - feelsLikeDetail: DetailItemViewModel? = null + iconProvider: String? = null ) { - val isRound = LocalConfiguration.current.isScreenRound + Row( + modifier = Modifier.fillMaxWidth() + ) { + WeatherIcon( + modifier = Modifier + .height(60.dp) + .weight(1f) + .align(Alignment.CenterVertically), + alignment = IconAlignment.End, + weatherIcon = weatherIcon, + iconProvider = iconProvider, + shouldAnimate = true + ) + Spacer(modifier = Modifier.size(8.dp)) + Text( + modifier = Modifier + .weight(1f) + .align(Alignment.CenterVertically), + text = curTemp ?: WeatherIcons.PLACEHOLDER, + textAlign = TextAlign.Start, + maxLines = 1, + fontSize = 42.sp, + fontWeight = FontWeight.Light, + color = tempTextColor( + temp = curTemp, + tempUnit = tempUnit + ) + ) + } +} - Column( +@Composable +private fun FeelsLikeText( + detail: DetailItemViewModel +) { + Text( modifier = Modifier .fillMaxWidth() .padding( - horizontal = if (showHiLo) { - if (isRound) 16.dp else 4.dp - } else { - 0.dp - } - ) - ) { - if (curCondition != null) { - Text( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 4.dp), - text = curCondition, - textAlign = TextAlign.Center, - overflow = TextOverflow.Ellipsis, - letterSpacing = 0.sp, - maxLines = 2, - style = MaterialTheme.typography.bodySmall, - ) - } - Row( - modifier = Modifier.fillMaxWidth() - ) { - WeatherIcon( - modifier = Modifier - .weight(1f) - .apply { - if (showHiLo) { - heightIn(min = 24.dp, max = 52.dp) - } else { - height(60.dp) - } - } - .align(Alignment.CenterVertically), - alignment = IconAlignment.End, - weatherIcon = weatherIcon, - iconProvider = iconProvider, - shouldAnimate = true - ) - Spacer(modifier = Modifier.size(8.dp)) - Text( - modifier = Modifier - .weight(if (showHiLo) 2f else 1.5f) - .align(Alignment.CenterVertically), - text = curTemp ?: WeatherIcons.PLACEHOLDER, - textAlign = if (showHiLo) TextAlign.Center else TextAlign.Start, - maxLines = 1, - fontSize = if (showHiLo) 28.sp else 36.sp, - fontWeight = FontWeight.Light, - color = tempTextColor( - temp = curTemp, - tempUnit = tempUnit - ) - ) - if (showHiLo) { - Spacer(modifier = Modifier.size(8.dp)) - Column( - modifier = Modifier - .weight(1f) - .align(Alignment.CenterVertically), - horizontalAlignment = Alignment.End - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.End - ) { - Text( - text = hiTemp ?: WeatherIcons.PLACEHOLDER, - style = MaterialTheme.typography.bodySmall, - textAlign = TextAlign.End, - maxLines = 1 - ) - Text( - modifier = Modifier.padding(horizontal = 4.dp), - text = "↑", - style = MaterialTheme.typography.bodyExtraSmall, - fontWeight = FontWeight.SemiBold, - textAlign = TextAlign.End, - maxLines = 1, - color = Color(0xFFFF4500), - ) - } - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.End - ) { - Text( - text = loTemp ?: WeatherIcons.PLACEHOLDER, - style = MaterialTheme.typography.bodySmall, - textAlign = TextAlign.End, - maxLines = 1 - ) - Text( - modifier = Modifier.padding(horizontal = 4.dp), - text = "↓", - style = MaterialTheme.typography.bodyExtraSmall, - fontWeight = FontWeight.SemiBold, - textAlign = TextAlign.End, - maxLines = 1, - color = Color(0xFF87CEFA), - ) - } - } - } - } - // FeelsLike - feelsLikeDetail?.let { detail -> - Row( - modifier = Modifier.fillMaxWidth() - ) { - Text( - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 4.dp), - text = buildString { - append(detail.label) - append(": ") - append(detail.value) - }, - textAlign = TextAlign.Center, - overflow = TextOverflow.Ellipsis, - letterSpacing = 0.sp, - maxLines = 1, - style = MaterialTheme.typography.bodySmall, - ) - } - } - } + horizontal = dimensionResource(id = R.dimen.wnow_horizontal_padding), + vertical = 4.dp + ), + text = buildString { + append(detail.label) + append(": ") + append(detail.value) + }, + color = LocalContentColor.current.copy(alpha = 0.75f), + textAlign = TextAlign.Center, + overflow = TextOverflow.Ellipsis, + letterSpacing = 0.sp, + maxLines = 1, + style = MaterialTheme.typography.bodySmall + ) } @Composable @@ -1140,17 +1064,22 @@ private fun PreviewWeatherNowScreen() { Box( modifier = Modifier.background(Color.White.copy(alpha = 0.1f)) ) { - CurrentConditionPanel( - curCondition = "Sunny", + IconTempRow( weatherIcon = WeatherIcons.DAY_SUNNY, - curTemp = "120°F", - tempUnit = "F", - showHiLo = true, - hiTemp = "110°", - loTemp = "80°", - feelsLikeDetail = feelsLikeDetail + curTemp = "70°F", + tempUnit = "F" ) } + // FeelsLike + FeelsLikeText(feelsLikeDetail) + // Condition + ConditionText("Sunny") + + // HiLo Layout + HiLoLayout( + hiTemp = "70°", + loTemp = "60°" + ) // Condition Details ConditionDetails( From 577ea4960b849c7065fdbbfefc35c7b07e3d2c9f Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 6 Jun 2026 23:36:15 -0400 Subject: [PATCH 28/67] WeatherApiProvider: astro fixes --- .../weatherapi/weather/WeatherApiProvider.kt | 43 +++++++++++++++++++ .../weatherapi/weather/WeatherData.kt | 26 +++++++---- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt index 54a7a780..552ae6e8 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt @@ -10,6 +10,7 @@ import com.thewizrd.shared_resources.okhttp3.OkHttp3Utils.await import com.thewizrd.shared_resources.okhttp3.OkHttp3Utils.getStream import com.thewizrd.shared_resources.remoteconfig.remoteConfigService import com.thewizrd.shared_resources.sharedDeps +import com.thewizrd.shared_resources.utils.DateTimeUtils import com.thewizrd.shared_resources.utils.JSONParser import com.thewizrd.shared_resources.utils.LocaleUtils import com.thewizrd.shared_resources.utils.Logger @@ -23,6 +24,8 @@ import com.thewizrd.shared_resources.weatherdata.model.isNullOrInvalid import com.thewizrd.weather_api.extras.cacheRequestIfNeeded import com.thewizrd.weather_api.keys.Keys import com.thewizrd.weather_api.locationiq.LocationIQProvider +import com.thewizrd.weather_api.nws.SolCalcAstroProvider +import com.thewizrd.weather_api.smc.SunMoonCalcProvider import com.thewizrd.weather_api.utils.APIRequestUtils.checkForErrors import com.thewizrd.weather_api.utils.APIRequestUtils.checkRateLimit import com.thewizrd.weather_api.utils.APIRequestUtils.throwIfRateLimited @@ -296,6 +299,46 @@ class WeatherApiProvider : WeatherProviderImpl(), WeatherAlertProvider { @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { super.updateWeatherData(location, weather) + + val newAstro = try { + SunMoonCalcProvider().getAstronomyData(location, weather.condition!!.observationTime) + } catch (e: WeatherException) { + Logger.writeLine(Log.ERROR, e, "Error") + SolCalcAstroProvider().getAstronomyData(location, weather.condition!!.observationTime) + } + + if (weather.astronomy != null) { + runCatching { + if (weather.astronomy!!.sunrise == null || DateTimeUtils.LOCALDATETIME_MIN.isEqual( + weather.astronomy!!.sunrise + ) + ) { + weather.astronomy!!.sunrise = newAstro.sunrise + } + if (weather.astronomy!!.sunset == null || DateTimeUtils.LOCALDATETIME_MIN.isEqual( + weather.astronomy!!.sunset + ) + ) { + weather.astronomy!!.sunset = newAstro.sunset + } + if (weather.astronomy!!.moonrise == null || DateTimeUtils.LOCALDATETIME_MIN.isEqual( + weather.astronomy!!.moonrise + ) + ) { + weather.astronomy!!.moonrise = newAstro.moonrise + } + if (weather.astronomy!!.moonset == null || DateTimeUtils.LOCALDATETIME_MIN.isEqual( + weather.astronomy!!.moonset + ) + ) { + weather.astronomy!!.moonset = newAstro.moonset + } + }.getOrElse { + weather.astronomy = newAstro + } + } else { + weather.astronomy = newAstro + } } override suspend fun updateLocationQuery(weather: Weather): String { diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt index 717571d8..c3b1d91f 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt @@ -1,5 +1,6 @@ package com.thewizrd.weather_api.weatherapi.weather +import android.annotation.SuppressLint import com.thewizrd.shared_resources.utils.AirQualityUtils.AQICO import com.thewizrd.shared_resources.utils.AirQualityUtils.AQINO2 import com.thewizrd.shared_resources.utils.AirQualityUtils.AQIO3 @@ -43,6 +44,7 @@ import java.time.ZonedDateTime import java.time.format.DateTimeFormatter import kotlin.math.roundToInt +@SuppressLint("VisibleForTests") fun createWeatherData(root: ForecastResponse): Weather { return Weather().apply { location = createLocation(root.location!!) @@ -61,11 +63,11 @@ fun createWeatherData(root: ForecastResponse): Weather { // Forecast for (day in root.forecast!!.forecastday!!) { - val fcast = createForecast(day, tzid) + val fcast = createForecast(day) day.hour?.forEach { hour -> val date = ZonedDateTime.ofInstant( - Instant.ofEpochSecond(hour.timeEpoch!!.toLong()), + Instant.ofEpochSecond(hour.timeEpoch!!), ZoneOffset.UTC ) @@ -87,7 +89,7 @@ fun createWeatherData(root: ForecastResponse): Weather { precipitation = createPrecipitation(root.current!!) ttl = 180 - if ((condition!!.highF == null || condition!!.highC == null) && forecast!!.size > 0) { + if ((condition!!.highF == null || condition!!.highC == null) && forecast!!.isNotEmpty()) { condition!!.highF = forecast!![0].highF condition!!.highC = forecast!![0].highC condition!!.lowF = forecast!![0].lowF @@ -104,13 +106,13 @@ fun createLocation(location: com.thewizrd.weather_api.weatherapi.weather.Locatio return Location().apply { /* Use name from location provider */ //name = location.name - latitude = location.lat!!.toFloat() - longitude = location.lon!!.toFloat() + latitude = location.lat!! + longitude = location.lon!! tzLong = location.tzId!! } } -fun createForecast(day: ForecastdayItem, tzid: ZoneId): Forecast { +fun createForecast(day: ForecastdayItem): Forecast { return Forecast().apply { date = day.dateEpoch?.let { ZonedDateTime.ofInstant(Instant.ofEpochSecond(it), ZoneOffset.UTC) @@ -247,6 +249,10 @@ fun createAstronomy(astro: Astro): Astronomy { runCatching { sunrise = LocalTime.parse(astro.sunrise, DateTimeFormatter.ofPattern("hh:mm a")).atDate(now) + }.getOrElse { + if (astro.sunrise == "Polar Day" || astro.sunrise == "Polar Night") { + sunrise = LocalDateTime.now().plusYears(1).minusNanos(1) + } } runCatching { @@ -257,6 +263,10 @@ fun createAstronomy(astro: Astro): Astronomy { sunset = LocalTime.parse(astro.sunset, DateTimeFormatter.ofPattern("hh:mm a")) .atDate(now.plusDays(1)) } + }.getOrElse { + if (astro.sunset == "Polar Day" || astro.sunset == "Polar Night") { + sunset = LocalDateTime.now().plusYears(1).minusNanos(1) + } } runCatching { @@ -280,10 +290,10 @@ fun createAstronomy(astro: Astro): Astronomy { // If the sun won't set/rise, set time to the future if (sunrise == null) { - sunrise = LocalDateTime.now().plusYears(1).minusNanos(1) + sunrise = DateTimeUtils.LOCALDATETIME_MIN } if (sunset == null) { - sunset = LocalDateTime.now().plusYears(1).minusNanos(1) + sunset = DateTimeUtils.LOCALDATETIME_MIN } if (moonrise == null) { moonrise = DateTimeUtils.LOCALDATETIME_MIN From d1c6220488f61c61d7e344720a278fec6a4cc0b5 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 6 Jun 2026 21:42:18 -0400 Subject: [PATCH 29/67] gradle: targetSdk 37 (Android 17) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cc3584a4..69118edb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] compileSdkVersion = "37" minSdkVersion = "23" -targetSdkVersion = "36" +targetSdkVersion = "37" gradleVersion = "9.2.1" kotlin_version = "2.3.21" From 056b53c56fd42cb179f1369e6a27a18c4c4b0efa Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 6 Jun 2026 21:43:46 -0400 Subject: [PATCH 30/67] SimpleWeather: v5.14.0-build2 --- app/build.gradle | 2 +- wearapp/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 4dedffda..657bcb01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get().toInteger() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code (Android: 0, WearOS: 1) // ex) 345100131 = (34, 5.10, 013, 0) - versionCode 365140010 + versionCode 375140020 versionName "5.14.0" vectorDrawables { diff --git a/wearapp/build.gradle b/wearapp/build.gradle index a5a1c1e8..edfd268d 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -16,7 +16,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code [Android: 0, WearOS: 1]) // ex) 345100131 = (34, 5.10, 013, 1) - versionCode 365140011 + versionCode 375140021 versionName "5.14.0" vectorDrawables { From d69f9a3b949f4c59512c3c7ed18ed42113a3a6be Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 6 Jun 2026 23:54:27 -0400 Subject: [PATCH 31/67] SimpleWeather: v5.14.0-build3 * targetSdk 37 not yet supported for wear? --- app/build.gradle | 2 +- gradle/libs.versions.toml | 1 + wearapp/build.gradle | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 657bcb01..72d0bc75 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get().toInteger() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code (Android: 0, WearOS: 1) // ex) 345100131 = (34, 5.10, 013, 0) - versionCode 375140020 + versionCode 375140030 versionName "5.14.0" vectorDrawables { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 69118edb..4ac9dd0e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,6 +2,7 @@ compileSdkVersion = "37" minSdkVersion = "23" targetSdkVersion = "37" +wearTargetSdkVersion = "36" gradleVersion = "9.2.1" kotlin_version = "2.3.21" diff --git a/wearapp/build.gradle b/wearapp/build.gradle index edfd268d..892ca61f 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -13,10 +13,10 @@ android { // Specifies the fully-qualified class name of the test instrumentation runner. testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" minSdkVersion 26 - targetSdkVersion libs.versions.targetSdkVersion.get() + targetSdkVersion libs.versions.wearTargetSdkVersion.get() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code [Android: 0, WearOS: 1]) // ex) 345100131 = (34, 5.10, 013, 1) - versionCode 375140021 + versionCode 365140031 versionName "5.14.0" vectorDrawables { From dc02361fff151fa8ca908abbb9c4fbfaf5234655 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Mon, 8 Jun 2026 00:17:36 -0400 Subject: [PATCH 32/67] WeatherApiProvider: additional data * Pollen now included --- .../weatherapi/weather/ForecastResponse.kt | 270 ++++++++++-------- .../weatherapi/weather/WeatherApiProvider.kt | 102 ++++++- .../weatherapi/weather/WeatherData.kt | 37 +++ .../weatherdata/WeatherProviderImpl.kt | 5 + 4 files changed, 291 insertions(+), 123 deletions(-) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/ForecastResponse.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/ForecastResponse.kt index 4bc8f485..35252b76 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/ForecastResponse.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/ForecastResponse.kt @@ -7,161 +7,161 @@ import com.squareup.moshi.JsonClass data class ForecastResponse( @field:Json(name = "alerts") - var alerts: Alerts? = null, + var alerts: Alerts? = null, @field:Json(name = "current") - var current: Current? = null, + var current: Current? = null, @field:Json(name = "location") - var location: Location? = null, + var location: Location? = null, @field:Json(name = "forecast") - var forecast: Forecast? = null + var forecast: Forecast? = null ) @JsonClass(generateAdapter = true) data class AlertItem( @field:Json(name = "severity") - var severity: String? = null, + var severity: String? = null, @field:Json(name = "note") - var note: String? = null, + var note: String? = null, @field:Json(name = "expires") - var expires: String? = null, + var expires: String? = null, @field:Json(name = "certainty") - var certainty: String? = null, + var certainty: String? = null, @field:Json(name = "areas") - var areas: String? = null, + var areas: String? = null, @field:Json(name = "effective") - var effective: String? = null, + var effective: String? = null, @field:Json(name = "urgency") - var urgency: String? = null, + var urgency: String? = null, @field:Json(name = "instruction") - var instruction: String? = null, + var instruction: String? = null, @field:Json(name = "category") - var category: String? = null, + var category: String? = null, @field:Json(name = "event") - var event: String? = null, + var event: String? = null, @field:Json(name = "headline") - var headline: String? = null, + var headline: String? = null, @field:Json(name = "msgtype") - var msgtype: String? = null, + var msgtype: String? = null, @field:Json(name = "desc") - var desc: String? = null + var desc: String? = null ) @JsonClass(generateAdapter = true) data class HourItem( @field:Json(name = "feelslike_c") - var feelslikeC: Float? = null, + var feelslikeC: Float? = null, @field:Json(name = "feelslike_f") - var feelslikeF: Float? = null, + var feelslikeF: Float? = null, @field:Json(name = "wind_degree") - var windDegree: Int? = null, + var windDegree: Int? = null, @field:Json(name = "windchill_f") - var windchillF: Float? = null, + var windchillF: Float? = null, @field:Json(name = "windchill_c") - var windchillC: Float? = null, + var windchillC: Float? = null, @field:Json(name = "temp_c") - var tempC: Float? = null, + var tempC: Float? = null, @field:Json(name = "temp_f") - var tempF: Float? = null, + var tempF: Float? = null, @field:Json(name = "cloud") - var cloud: Int? = null, + var cloud: Int? = null, @field:Json(name = "wind_kph") - var windKph: Float? = null, + var windKph: Float? = null, @field:Json(name = "wind_mph") - var windMph: Float? = null, + var windMph: Float? = null, @field:Json(name = "humidity") - var humidity: Int? = null, + var humidity: Int? = null, @field:Json(name = "dewpoint_f") - var dewpointF: Float? = null, + var dewpointF: Float? = null, @field:Json(name = "will_it_rain") - var willItRain: Int? = null, + var willItRain: Int? = null, @field:Json(name = "uv") - var uv: Float? = null, + var uv: Float? = null, @field:Json(name = "heatindex_f") - var heatindexF: Float? = null, + var heatindexF: Float? = null, @field:Json(name = "dewpoint_c") - var dewpointC: Float? = null, + var dewpointC: Float? = null, @field:Json(name = "is_day") @get:JvmName("getIsDay") - @set:JvmName("setIsDay") - var isDay: Int? = null, + @set:JvmName("setIsDay") + var isDay: Int? = null, @field:Json(name = "precip_in") - var precipIn: Float? = null, + var precipIn: Float? = null, @field:Json(name = "heatindex_c") - var heatindexC: Float? = null, + var heatindexC: Float? = null, @field:Json(name = "wind_dir") - var windDir: String? = null, + var windDir: String? = null, @field:Json(name = "gust_mph") - var gustMph: Float? = null, + var gustMph: Float? = null, @field:Json(name = "pressure_in") - var pressureIn: Float? = null, + var pressureIn: Float? = null, @field:Json(name = "chance_of_rain") - var chanceOfRain: String? = null, + var chanceOfRain: String? = null, @field:Json(name = "gust_kph") - var gustKph: Float? = null, + var gustKph: Float? = null, @field:Json(name = "precip_mm") - var precipMm: Float? = null, + var precipMm: Float? = null, @field:Json(name = "condition") - var condition: Condition? = null, + var condition: Condition? = null, @field:Json(name = "will_it_snow") - var willItSnow: Int? = null, + var willItSnow: Int? = null, @field:Json(name = "vis_km") - var visKm: Float? = null, + var visKm: Float? = null, @field:Json(name = "time_epoch") var timeEpoch: Long? = null, @field:Json(name = "time") - var time: String? = null, + var time: String? = null, @field:Json(name = "chance_of_snow") - var chanceOfSnow: String? = null, + var chanceOfSnow: String? = null, @field:Json(name = "pressure_mb") - var pressureMb: Float? = null, + var pressureMb: Float? = null, @field:Json(name = "vis_miles") var visMiles: Float? = null, @@ -174,87 +174,87 @@ data class HourItem( data class Astro( @field:Json(name = "moonset") - var moonset: String? = null, + var moonset: String? = null, @field:Json(name = "moon_illumination") - var moonIllumination: String? = null, + var moonIllumination: String? = null, @field:Json(name = "sunrise") - var sunrise: String? = null, + var sunrise: String? = null, @field:Json(name = "moon_phase") - var moonPhase: String? = null, + var moonPhase: String? = null, @field:Json(name = "sunset") - var sunset: String? = null, + var sunset: String? = null, @field:Json(name = "moonrise") - var moonrise: String? = null + var moonrise: String? = null ) @JsonClass(generateAdapter = true) data class Alerts( @field:Json(name = "alert") - var alert: List? = null + var alert: List? = null ) @JsonClass(generateAdapter = true) data class Day( @field:Json(name = "avgvis_km") - var avgvisKm: Float? = null, + var avgvisKm: Float? = null, @field:Json(name = "uv") - var uv: Float? = null, + var uv: Float? = null, @field:Json(name = "avgtemp_f") - var avgtempF: Float? = null, + var avgtempF: Float? = null, @field:Json(name = "avgtemp_c") - var avgtempC: Float? = null, + var avgtempC: Float? = null, @field:Json(name = "daily_chance_of_snow") - var dailyChanceOfSnow: String? = null, + var dailyChanceOfSnow: String? = null, @field:Json(name = "maxtemp_c") - var maxtempC: Float? = null, + var maxtempC: Float? = null, @field:Json(name = "maxtemp_f") - var maxtempF: Float? = null, + var maxtempF: Float? = null, @field:Json(name = "mintemp_c") - var mintempC: Float? = null, + var mintempC: Float? = null, @field:Json(name = "avgvis_miles") - var avgvisMiles: Float? = null, + var avgvisMiles: Float? = null, @field:Json(name = "daily_will_it_rain") - var dailyWillItRain: Int? = null, + var dailyWillItRain: Int? = null, @field:Json(name = "mintemp_f") - var mintempF: Float? = null, + var mintempF: Float? = null, @field:Json(name = "totalprecip_in") - var totalprecipIn: Float? = null, + var totalprecipIn: Float? = null, @field:Json(name = "avghumidity") - var avghumidity: Float? = null, + var avghumidity: Float? = null, @field:Json(name = "condition") - var condition: Condition? = null, + var condition: Condition? = null, @field:Json(name = "maxwind_kph") - var maxwindKph: Float? = null, + var maxwindKph: Float? = null, @field:Json(name = "maxwind_mph") - var maxwindMph: Float? = null, + var maxwindMph: Float? = null, @field:Json(name = "daily_chance_of_rain") - var dailyChanceOfRain: String? = null, + var dailyChanceOfRain: String? = null, @field:Json(name = "totalprecip_mm") - var totalprecipMm: Float? = null, + var totalprecipMm: Float? = null, @field:Json(name = "daily_will_it_snow") var dailyWillItSnow: Int? = null, @@ -267,171 +267,199 @@ data class Day( data class Forecast( @field:Json(name = "forecastday") - var forecastday: List? = null + var forecastday: List? = null ) @JsonClass(generateAdapter = true) data class Current( @field:Json(name = "feelslike_c") - var feelslikeC: Float? = null, + var feelslikeC: Float? = null, @field:Json(name = "uv") - var uv: Float? = null, + var uv: Float? = null, @field:Json(name = "last_updated") - var lastUpdated: String? = null, + var lastUpdated: String? = null, @field:Json(name = "feelslike_f") - var feelslikeF: Float? = null, + var feelslikeF: Float? = null, @field:Json(name = "wind_degree") - var windDegree: Int? = null, + var windDegree: Int? = null, @field:Json(name = "last_updated_epoch") var lastUpdatedEpoch: Long? = null, @field:Json(name = "is_day") @get:JvmName("getIsDay") - @set:JvmName("setIsDay") - var isDay: Int? = null, + @set:JvmName("setIsDay") + var isDay: Int? = null, @field:Json(name = "precip_in") - var precipIn: Float? = null, + var precipIn: Float? = null, @field:Json(name = "air_quality") - var airQuality: AirQuality? = null, + var airQuality: AirQuality? = null, @field:Json(name = "wind_dir") - var windDir: String? = null, + var windDir: String? = null, @field:Json(name = "gust_mph") - var gustMph: Float? = null, + var gustMph: Float? = null, @field:Json(name = "temp_c") - var tempC: Float? = null, + var tempC: Float? = null, @field:Json(name = "pressure_in") - var pressureIn: Float? = null, + var pressureIn: Float? = null, @field:Json(name = "gust_kph") - var gustKph: Float? = null, + var gustKph: Float? = null, @field:Json(name = "temp_f") - var tempF: Float? = null, + var tempF: Float? = null, @field:Json(name = "precip_mm") - var precipMm: Float? = null, + var precipMm: Float? = null, @field:Json(name = "cloud") - var cloud: Int? = null, + var cloud: Int? = null, @field:Json(name = "wind_kph") - var windKph: Float? = null, + var windKph: Float? = null, @field:Json(name = "condition") - var condition: Condition? = null, + var condition: Condition? = null, @field:Json(name = "wind_mph") - var windMph: Float? = null, + var windMph: Float? = null, @field:Json(name = "vis_km") - var visKm: Float? = null, + var visKm: Float? = null, @field:Json(name = "humidity") - var humidity: Int? = null, + var humidity: Int? = null, @field:Json(name = "pressure_mb") - var pressureMb: Float? = null, + var pressureMb: Float? = null, @field:Json(name = "vis_miles") - var visMiles: Float? = null + var visMiles: Float? = null, + + @field:Json(name = "pollen") + var pollen: Pollen? = null, ) @JsonClass(generateAdapter = true) data class Condition( @field:Json(name = "code") - var code: Int? = null, + var code: Int? = null, @field:Json(name = "icon") - var icon: String? = null, + var icon: String? = null, @field:Json(name = "text") - var text: String? = null + var text: String? = null ) @JsonClass(generateAdapter = true) data class ForecastdayItem( @field:Json(name = "date") - var date: String? = null, + var date: String? = null, @field:Json(name = "astro") - var astro: Astro? = null, + var astro: Astro? = null, @field:Json(name = "date_epoch") var dateEpoch: Long? = null, @field:Json(name = "hour") - var hour: List? = null, + var hour: List? = null, @field:Json(name = "day") - var day: Day? = null + var day: Day? = null ) @JsonClass(generateAdapter = true) data class Location( @field:Json(name = "localtime") - var localtime: String? = null, + var localtime: String? = null, @field:Json(name = "country") - var country: String? = null, + var country: String? = null, @field:Json(name = "localtime_epoch") var localtimeEpoch: Long? = null, @field:Json(name = "name") - var name: String? = null, + var name: String? = null, @field:Json(name = "lon") - var lon: Float? = null, + var lon: Float? = null, @field:Json(name = "region") - var region: String? = null, + var region: String? = null, @field:Json(name = "lat") - var lat: Float? = null, + var lat: Float? = null, @field:Json(name = "tz_id") - var tzId: String? = null + var tzId: String? = null ) @JsonClass(generateAdapter = true) data class AirQuality( @field:Json(name = "no2") - var no2: Double? = null, + var no2: Double? = null, @field:Json(name = "o3") - var o3: Double? = null, + var o3: Double? = null, @field:Json(name = "us-epa-index") - var usEpaIndex: Int? = null, + var usEpaIndex: Int? = null, @field:Json(name = "so2") - var so2: Double? = null, + var so2: Double? = null, @field:Json(name = "pm2_5") - var pm25: Double? = null, + var pm25: Double? = null, @field:Json(name = "pm10") - var pm10: Double? = null, + var pm10: Double? = null, @field:Json(name = "co") - var co: Double? = null, + var co: Double? = null, @field:Json(name = "gb-defra-index") - var gbDefraIndex: Int? = null + var gbDefraIndex: Int? = null +) + +@JsonClass(generateAdapter = true) +data class Pollen( + + @field:Json(name = "Alder") + var alder: Double? = null, + + @field:Json(name = "Birch") + var birch: Double? = null, + + @field:Json(name = "Mugwort") + var mugwort: Double? = null, + + @field:Json(name = "Oak") + var oak: Double? = null, + + @field:Json(name = "Grass") + var grass: Double? = null, + + @field:Json(name = "Hazel") + var hazel: Double? = null, + + @field:Json(name = "Ragweed") + var ragweed: Double? = null ) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt index 552ae6e8..309475a6 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt @@ -15,9 +15,11 @@ import com.thewizrd.shared_resources.utils.JSONParser import com.thewizrd.shared_resources.utils.LocaleUtils import com.thewizrd.shared_resources.utils.Logger import com.thewizrd.shared_resources.utils.ZoneIdCompat +import com.thewizrd.shared_resources.weatherdata.PollenProvider import com.thewizrd.shared_resources.weatherdata.WeatherAPI import com.thewizrd.shared_resources.weatherdata.WeatherAlertProvider import com.thewizrd.shared_resources.weatherdata.auth.AuthType +import com.thewizrd.shared_resources.weatherdata.model.Pollen import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.shared_resources.weatherdata.model.WeatherAlert import com.thewizrd.shared_resources.weatherdata.model.isNullOrInvalid @@ -48,14 +50,16 @@ import java.time.ZonedDateTime import java.util.Locale import java.util.concurrent.TimeUnit -class WeatherApiProvider : WeatherProviderImpl(), WeatherAlertProvider { +class WeatherApiProvider : WeatherProviderImpl(), WeatherAlertProvider, PollenProvider { companion object { private const val BASE_URL = "https://api.weatherapi.com/v1/" private const val KEYCHECK_QUERY_URL = BASE_URL + "forecast.json?key=%s" private const val WEATHER_QUERY_URL = - BASE_URL + "forecast.json?q=%s&days=10&aqi=yes&alerts=yes&lang=%s&key=%s" + BASE_URL + "forecast.json?q=%s&days=10&aqi=yes&pollen=yes&alerts=yes&lang=%s&key=%s" private const val ALERTS_QUERY_URL = BASE_URL + "forecast.json?q=%s&days=1&hour=6&aqi=no&alerts=yes&lang=%s&key=%s" + private const val POLLEN_QUERY_URL = + BASE_URL + "current.json?q=%s&pollen=yes&key=%s" } init { @@ -296,6 +300,100 @@ class WeatherApiProvider : WeatherProviderImpl(), WeatherAlertProvider { return@withContext alerts } + override suspend fun getPollenData(location: LocationData): Pollen? = + withContext(Dispatchers.IO) { + var pollenData: Pollen? = null + + val key = getProviderKey() + + val client = sharedDeps.httpClient + var response: Response? = null + + try { + // If were under rate limit, deny request + checkRateLimit() + + if (key.isNullOrBlank()) { + throw WeatherException(ErrorStatus.INVALIDAPIKEY) + } + + val request = Request.Builder() + .cacheRequestIfNeeded(isKeyRequired(), 30, TimeUnit.MINUTES) + .url( + String.format( + POLLEN_QUERY_URL, + updateLocationQuery(location), + key + ) + ) + .build() + + // Connect to webstream + response = client.newCall(request).await() + checkForErrors(response) + + val stream = response.getStream() + + // Load weather + val root = JSONParser.deserializer( + stream, + ForecastResponse::class.java + ) + + // End Stream + stream.closeQuietly() + + requireNotNull(root) + + root.current?.pollen?.let { currentPollen -> + val treePollenValue = maxOf( + currentPollen.hazel ?: 0.0, + currentPollen.alder ?: 0.0, + currentPollen.birch ?: 0.0, + currentPollen.oak ?: 0.0 + ) + val grassPollenValue = currentPollen.grass ?: 0.0 + val ragweedPollenValue = + maxOf(currentPollen.ragweed ?: 0.0, currentPollen.mugwort ?: 0.0) + + pollenData = Pollen().apply { + treePollenCount = when { + treePollenValue in 1.0..20.0 -> Pollen.PollenCount.LOW + treePollenValue in 20.0..100.0 -> Pollen.PollenCount.MODERATE + treePollenValue in 100.0..300.0 -> Pollen.PollenCount.HIGH + treePollenValue >= 300.0 -> Pollen.PollenCount.LOW + else -> Pollen.PollenCount.UNKNOWN + } + grassPollenCount = when { + grassPollenValue in 1.0..20.0 -> Pollen.PollenCount.LOW + grassPollenValue in 20.0..100.0 -> Pollen.PollenCount.MODERATE + grassPollenValue in 100.0..300.0 -> Pollen.PollenCount.HIGH + grassPollenValue >= 300.0 -> Pollen.PollenCount.LOW + else -> Pollen.PollenCount.UNKNOWN + } + ragweedPollenCount = when { + ragweedPollenValue in 1.0..20.0 -> Pollen.PollenCount.LOW + ragweedPollenValue in 20.0..100.0 -> Pollen.PollenCount.MODERATE + ragweedPollenValue in 100.0..300.0 -> Pollen.PollenCount.HIGH + ragweedPollenValue >= 300.0 -> Pollen.PollenCount.LOW + else -> Pollen.PollenCount.UNKNOWN + } + } + } + } catch (ex: Exception) { + pollenData = null + Logger.writeLine( + Log.ERROR, + ex, + "WeatherApiProvider: error getting weather alert data" + ) + } finally { + response?.closeQuietly() + } + + return@withContext pollenData + } + @Throws(WeatherException::class) override suspend fun updateWeatherData(location: LocationData, weather: Weather) { super.updateWeatherData(location, weather) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt index c3b1d91f..476927f5 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt @@ -30,6 +30,7 @@ import com.thewizrd.shared_resources.weatherdata.model.ForecastExtras import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.Location import com.thewizrd.shared_resources.weatherdata.model.MoonPhase +import com.thewizrd.shared_resources.weatherdata.model.Pollen import com.thewizrd.shared_resources.weatherdata.model.Precipitation import com.thewizrd.shared_resources.weatherdata.model.UV import com.thewizrd.shared_resources.weatherdata.model.Weather @@ -216,6 +217,42 @@ fun createCondition(current: Current, tzId: ZoneId): Condition { airQuality = createAirQuality(current.airQuality) + current.pollen?.let { currentPollen -> + val treePollenValue = maxOf( + currentPollen.hazel ?: 0.0, + currentPollen.alder ?: 0.0, + currentPollen.birch ?: 0.0, + currentPollen.oak ?: 0.0 + ) + val grassPollenValue = currentPollen.grass ?: 0.0 + val ragweedPollenValue = + maxOf(currentPollen.ragweed ?: 0.0, currentPollen.mugwort ?: 0.0) + + pollen = Pollen().apply { + treePollenCount = when { + treePollenValue in 1.0..20.0 -> Pollen.PollenCount.LOW + treePollenValue in 20.0..100.0 -> Pollen.PollenCount.MODERATE + treePollenValue in 100.0..300.0 -> Pollen.PollenCount.HIGH + treePollenValue >= 300.0 -> Pollen.PollenCount.LOW + else -> Pollen.PollenCount.UNKNOWN + } + grassPollenCount = when { + grassPollenValue in 1.0..20.0 -> Pollen.PollenCount.LOW + grassPollenValue in 20.0..100.0 -> Pollen.PollenCount.MODERATE + grassPollenValue in 100.0..300.0 -> Pollen.PollenCount.HIGH + grassPollenValue >= 300.0 -> Pollen.PollenCount.LOW + else -> Pollen.PollenCount.UNKNOWN + } + ragweedPollenCount = when { + ragweedPollenValue in 1.0..20.0 -> Pollen.PollenCount.LOW + ragweedPollenValue in 20.0..100.0 -> Pollen.PollenCount.MODERATE + ragweedPollenValue in 100.0..300.0 -> Pollen.PollenCount.HIGH + ragweedPollenValue >= 300.0 -> Pollen.PollenCount.LOW + else -> Pollen.PollenCount.UNKNOWN + } + } + } + observationTime = current.lastUpdatedEpoch?.let { ZonedDateTime.ofInstant(Instant.ofEpochSecond(it), ZoneOffset.UTC) .withZoneSameInstant(tzId) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt index 166f2452..e4318123 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt @@ -216,6 +216,11 @@ abstract class WeatherProviderImpl : WeatherProvider, RateLimitedRequest { OpenMeteoWeatherProvider().getPollenData(location)?.apply { attribution = context.getString(R.string.api_openmeteo) } + } else if (remoteConfigService.isProviderEnabled(WeatherAPI.WEATHERAPI) && !BuildConfig.IS_NONGMS) { + weather.condition!!.pollen = + WeatherApiProvider().getPollenData(location)?.apply { + attribution = context.getString(R.string.api_weatherapi) + } } } } From ac8117801efe7c32946dd2fb4ac0abf8e5cdb746 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Mon, 8 Jun 2026 00:19:07 -0400 Subject: [PATCH 33/67] SimpleWeather: v5.14.0-build4 --- app/build.gradle | 2 +- wearapp/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 72d0bc75..5fb7defa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get().toInteger() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code (Android: 0, WearOS: 1) // ex) 345100131 = (34, 5.10, 013, 0) - versionCode 375140030 + versionCode 375140040 versionName "5.14.0" vectorDrawables { diff --git a/wearapp/build.gradle b/wearapp/build.gradle index 892ca61f..f28dc655 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -16,7 +16,7 @@ android { targetSdkVersion libs.versions.wearTargetSdkVersion.get() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code [Android: 0, WearOS: 1]) // ex) 345100131 = (34, 5.10, 013, 1) - versionCode 365140031 + versionCode 365140041 versionName "5.14.0" vectorDrawables { From b9a2e588b619dbd61d2d2b7b10057ffe47dd2a95 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Wed, 10 Jun 2026 00:14:55 -0400 Subject: [PATCH 34/67] weather-api: update for missing icons --- .../brightsky/BrightSkyProvider.kt | 4 +- .../weather/MeteoFranceProvider.kt | 14 ++----- .../meteofrance/weather/WeatherData.kt | 8 ++-- .../tomorrow/TomorrowIOWeatherProvider.kt | 4 +- .../weatherapi/weather/WeatherApiProvider.kt | 40 +++++++++++++++++++ 5 files changed, 52 insertions(+), 18 deletions(-) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/brightsky/BrightSkyProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/brightsky/BrightSkyProvider.kt index e80cb7e8..7f08826f 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/brightsky/BrightSkyProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/brightsky/BrightSkyProvider.kt @@ -262,7 +262,7 @@ class BrightSkyProvider : WeatherProviderImpl() { for (forecast in weather.forecast!!) { forecast.icon.let { forecast.icon = getWeatherIcon(it) - forecast.condition = getWeatherCondition(it) + forecast.condition = getWeatherCondition(forecast.icon) } } @@ -277,7 +277,7 @@ class BrightSkyProvider : WeatherProviderImpl() { hrfLocalTime.isBefore(sunrise) || hrfLocalTime.isAfter(sunset), it ) - hr_forecast.condition = getWeatherCondition(it) + hr_forecast.condition = getWeatherCondition(hr_forecast.icon) } } diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt index a1a832bb..36846836 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt @@ -249,25 +249,17 @@ class MeteoFranceProvider : WeatherProviderImpl() { } // Update icons - val now = ZonedDateTime.now(ZoneOffset.UTC).withZoneSameInstant(offset).toLocalTime() - val sunrise = weather.astronomy!!.sunrise.toLocalTime() - val sunset = weather.astronomy!!.sunset.toLocalTime() - - weather.condition!!.icon = - getWeatherIcon(now.isBefore(sunrise) || now.isAfter(sunset), weather.condition!!.icon) + weather.condition!!.icon = getWeatherIcon(weather.condition!!.icon) for (forecast in weather.forecast!!) { forecast.date = forecast.date.plusSeconds(offset.totalSeconds.toLong()) + forecast.icon = getWeatherIcon(false, forecast.icon) } for (hr_forecast in weather.hrForecast!!) { val hrf_date = hr_forecast.date.withZoneSameInstant(offset) hr_forecast.date = hrf_date - val hrf_localTime = hrf_date.toLocalTime() - hr_forecast.icon = getWeatherIcon( - hrf_localTime.isBefore(sunrise) || hrf_localTime.isAfter(sunset), - hr_forecast.icon - ) + hr_forecast.icon = getWeatherIcon(hr_forecast.icon) } if (!weather.weatherAlerts.isNullOrEmpty()) { diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/WeatherData.kt index 5e69c73b..fd96331d 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/WeatherData.kt @@ -124,9 +124,9 @@ fun createForecast(day: DailyForecastItem): Forecast { ) { day.weather12H?.desc } else { - provider.getWeatherCondition(day.weather12H?.icon) + provider.getWeatherCondition(provider.getWeatherIcon(false, day.weather12H?.icon)) } - icon = provider.getWeatherIcon(false, day.weather12H?.icon) + icon = day.weather12H?.icon // Extras extras = ForecastExtras() @@ -167,7 +167,7 @@ fun createHourlyForecast(forecast: ForecastItem, ) { forecast.weather?.desc } else { - provider.getWeatherCondition(forecast.weather?.icon) + provider.getWeatherCondition(provider.getWeatherIcon(forecast.weather?.icon)) } icon = forecast.weather?.icon @@ -306,7 +306,7 @@ fun createCondition(currRoot: CurrentsResponse): Condition { ) { currRoot.observation?.weather?.desc } else { - provider.getWeatherCondition(currRoot.observation?.weather?.icon) + provider.getWeatherCondition(provider.getWeatherIcon(currRoot.observation?.weather?.icon)) } icon = currRoot.observation?.weather?.icon diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt index 29d02ebf..a31f2a1a 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/tomorrow/TomorrowIOWeatherProvider.kt @@ -1007,7 +1007,9 @@ class TomorrowIOWeatherProvider : WeatherProviderImpl(), PollenProvider { 4210, 42100, 42101 -> context.getString(R.string.weather_rain) /* Heavy Rain */ 4201, 42010, 42011, - 4211, 42110, 42111 -> context.getString(R.string.weather_heavyrain) + 4211, 42110, 42111, + 4202, 42020, 42021, + 4212, 42120, 42121 -> context.getString(R.string.weather_heavyrain) /* Flurries */ 5001, 50010, 50011, 5115, 51150, 51151, diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt index 309475a6..6dd2aac2 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt @@ -510,6 +510,30 @@ class WeatherApiProvider : WeatherProviderImpl(), WeatherAlertProvider, PollenPr weatherIcon = WeatherIcons.OVERCAST } + /* Haze */ + 1012 -> { + weatherIcon = WeatherIcons.HAZE + } + + /* + * 1015: Dust Haze + * 1018: Blowing dust + * 1021: Dust storm + * 1045: Saharan dust + * 1048: Dust + */ + 1015, 1018, 1021, 1045, 1048 -> { + weatherIcon = WeatherIcons.DUST + } + + /* + * 1024: Sandstorm + * 1027: Severe sandstorm + */ + 1024, 1027 -> { + weatherIcon = WeatherIcons.SANDSTORM + } + /* * 1030: Mist * 1135: Fog @@ -519,6 +543,22 @@ class WeatherApiProvider : WeatherProviderImpl(), WeatherAlertProvider, PollenPr weatherIcon = WeatherIcons.FOG } + /* + * 1033: Smoke + * 1036: Smoky haze + */ + 1033, 1036 -> { + weatherIcon = WeatherIcons.SMOKE + } + + /* + * 1039: Smog + * 1042: Severe smog + */ + 1039, 1042 -> { + weatherIcon = WeatherIcons.SMOG + } + /* * 1063: Patchy rain possible * 1186: Moderate rain at times From 4acb2bd80c99957ad93ce4a01332987c909a9bec Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Wed, 10 Jun 2026 00:18:05 -0400 Subject: [PATCH 35/67] SimpleWeather: v5.14.0-build5 --- app/build.gradle | 2 +- wearapp/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 5fb7defa..2484c15c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get().toInteger() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code (Android: 0, WearOS: 1) // ex) 345100131 = (34, 5.10, 013, 0) - versionCode 375140040 + versionCode 375140050 versionName "5.14.0" vectorDrawables { diff --git a/wearapp/build.gradle b/wearapp/build.gradle index f28dc655..ad5ed1fd 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -16,7 +16,7 @@ android { targetSdkVersion libs.versions.wearTargetSdkVersion.get() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code [Android: 0, WearOS: 1]) // ex) 345100131 = (34, 5.10, 013, 1) - versionCode 365140041 + versionCode 365140051 versionName "5.14.0" vectorDrawables { From 2229daf886b049b49bc92d7f4da9f1d04d539c9a Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Mon, 15 Jun 2026 23:49:28 -0400 Subject: [PATCH 36/67] SimpleWeather: roundup bug fixes --- .../viewmodels/AirQualityForecastViewModel.kt | 4 +- .../controls/viewmodels/ChartsViewModel.kt | 4 +- .../viewmodels/ForecastsNowViewModel.kt | 4 +- .../shared_resources/database/WeatherDAO.kt | 2 +- .../shared_resources/json/NaNToNullAdapter.kt | 33 ++++++++++++++++ .../shared_resources/utils/JSONParser.kt | 4 ++ .../viewmodels/ConfirmationViewModel.kt | 2 + .../viewmodels/ForecastPanelsViewModel.kt | 4 +- .../thewizrd/weather_api/aqicn/AQICNData.kt | 2 +- .../com/thewizrd/weather_api/aqicn/Data.kt | 2 +- .../weather/MeteoFranceProvider.kt | 16 +++++--- .../openmeteo/OpenMeteoWeatherProvider.kt | 3 +- .../weatherapi/weather/WeatherAlerts.kt | 14 ++++--- .../weatherapi/weather/WeatherData.kt | 39 +++++++++++-------- 14 files changed, 97 insertions(+), 36 deletions(-) create mode 100644 shared_resources/src/main/java/com/thewizrd/shared_resources/json/NaNToNullAdapter.kt diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/AirQualityForecastViewModel.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/AirQualityForecastViewModel.kt index d5a89273..a089cf69 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/AirQualityForecastViewModel.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/AirQualityForecastViewModel.kt @@ -19,6 +19,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.launch class AirQualityForecastViewModel(app: Application) : AndroidViewModel(app) { @@ -46,7 +47,8 @@ class AirQualityForecastViewModel(app: Application) : AndroidViewModel(app) { flowScope?.cancel() currentForecastsData = - weatherDAO.getLiveForecastData(location.query).distinctUntilChanged() + weatherDAO.getLiveForecastData(location.query).filterNotNull() + .distinctUntilChanged() flowScope = CoroutineScope(SupervisorJob()) flowScope?.launch { diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ChartsViewModel.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ChartsViewModel.kt index f3fb3b0b..a29b6543 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ChartsViewModel.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ChartsViewModel.kt @@ -22,6 +22,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combineTransform import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.launch import java.time.ZoneOffset import java.time.ZonedDateTime @@ -60,7 +61,8 @@ class ChartsViewModel(app: Application) : AndroidViewModel(app) { ZonedDateTime.now(location.tzOffset).truncatedTo(ChronoUnit.HOURS) ).distinctUntilChanged() currentForecastsData = - weatherDAO.getLiveForecastData(location.query).distinctUntilChanged() + weatherDAO.getLiveForecastData(location.query).filterNotNull() + .distinctUntilChanged() flowScope = CoroutineScope(SupervisorJob()) flowScope?.launch { diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastsNowViewModel.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastsNowViewModel.kt index 7e8bc1a4..c759f32e 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastsNowViewModel.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ForecastsNowViewModel.kt @@ -25,6 +25,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.last import kotlinx.coroutines.launch import java.time.ZoneOffset @@ -81,7 +82,8 @@ class ForecastsNowViewModel(app: Application) : AndroidViewModel(app) { iconProvider = settingsManager.getIconsProvider() currentForecastsData = - weatherDAO.getLiveForecastData(location.query).distinctUntilChanged() + weatherDAO.getLiveForecastData(location.query).filterNotNull() + .distinctUntilChanged() flowScope?.launch { currentForecastsData.collect { diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/database/WeatherDAO.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/database/WeatherDAO.kt index e7abd511..97196aa8 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/database/WeatherDAO.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/database/WeatherDAO.kt @@ -97,7 +97,7 @@ interface WeatherDAO { suspend fun getForecastData(query: String): Forecasts? @Query("SELECT * FROM forecasts WHERE `query` = :query") - fun getLiveForecastData(query: String): Flow + fun getLiveForecastData(query: String): Flow @Query("SELECT COUNT(*) FROM forecasts GROUP BY `query`") suspend fun getForecastDataCountGroupedByQuery(): Int diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/json/NaNToNullAdapter.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/json/NaNToNullAdapter.kt new file mode 100644 index 00000000..4d37005f --- /dev/null +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/json/NaNToNullAdapter.kt @@ -0,0 +1,33 @@ +package com.thewizrd.shared_resources.json + +import com.squareup.moshi.JsonAdapter +import com.squareup.moshi.JsonReader +import com.squareup.moshi.JsonWriter + +val doubleNaNToNullAdapter = object : JsonAdapter() { + override fun fromJson(reader: JsonReader): Double? { + return reader.readJsonValue() as? Double + } + + override fun toJson(writer: JsonWriter, value: Double?) { + if (value == null || value.isNaN() || value.isInfinite()) { + writer.nullValue() // Replaces invalid values with null + } else { + writer.value(value) + } + } +} + +val floatNaNToNullAdapter = object : JsonAdapter() { + override fun fromJson(reader: JsonReader): Float? { + return reader.readJsonValue() as? Float + } + + override fun toJson(writer: JsonWriter, value: Float?) { + if (value == null || value.isNaN() || value.isInfinite()) { + writer.nullValue() // Replaces invalid values with null + } else { + writer.value(value) + } + } +} \ No newline at end of file diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/JSONParser.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/JSONParser.kt index e7a5333e..d54c7afe 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/JSONParser.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/JSONParser.kt @@ -11,6 +11,8 @@ import com.thewizrd.shared_resources.json.CustomJsonConverter import com.thewizrd.shared_resources.json.DateConverter import com.thewizrd.shared_resources.json.LocalDateTimeConverter import com.thewizrd.shared_resources.json.ZonedDateTimeConverter +import com.thewizrd.shared_resources.json.doubleNaNToNullAdapter +import com.thewizrd.shared_resources.json.floatNaNToNullAdapter import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.weatherdata.model.AirQuality import com.thewizrd.shared_resources.weatherdata.model.Astronomy @@ -68,6 +70,8 @@ object JSONParser { .add(Pollen::class.java, CustomJsonConverter(Pollen::class.java)) .add(WeatherAlert::class.java, CustomJsonConverter(WeatherAlert::class.java)) .add(KotlinJsonAdapterFactory()) + .add(Double::class.java, doubleNaNToNullAdapter) + .add(Float::class.java, floatNaNToNullAdapter) .build() } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ConfirmationViewModel.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ConfirmationViewModel.kt index 1f4483e4..2428d3ba 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ConfirmationViewModel.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ConfirmationViewModel.kt @@ -4,6 +4,7 @@ import androidx.annotation.DrawableRes import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.wear.compose.material3.ConfirmationDialogDefaults +import com.squareup.moshi.JsonClass import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.distinctUntilChanged @@ -61,6 +62,7 @@ class ConfirmationViewModel : ViewModel() { } } +@JsonClass(generateAdapter = true) data class ConfirmationData( val message: String? = null, @DrawableRes val iconResId: Int? = null, diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ForecastPanelsViewModel.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ForecastPanelsViewModel.kt index 3b49e194..3b0adba6 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ForecastPanelsViewModel.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/viewmodels/ForecastPanelsViewModel.kt @@ -25,6 +25,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.lastOrNull import kotlinx.coroutines.launch import java.time.ZoneOffset @@ -75,7 +76,8 @@ class ForecastPanelsViewModel(app: Application) : AndroidViewModel(app) { flowScope?.cancel() currentForecastsData = - weatherDAO.getLiveForecastData(location.query).distinctUntilChanged() + weatherDAO.getLiveForecastData(location.query).filterNotNull() + .distinctUntilChanged() val hrInterval = weatherModule.weatherManager.getHourlyForecastInterval() currentHrForecastsData = diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/aqicn/AQICNData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/aqicn/AQICNData.kt index dcfb7195..39e9d52a 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/aqicn/AQICNData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/aqicn/AQICNData.kt @@ -19,7 +19,7 @@ class AQICNData internal constructor(root: Rootobject) : AirQualityData() { pm10 = root.data?.iaqi?.pm10?.v?.roundToInt() co = root.data?.iaqi?.co?.v?.roundToInt() - index = root.data?.aqi ?: getIndexFromData() + index = root.data?.aqi?.toIntOrNull() ?: getIndexFromData() } aqiForecast = root.createAQIForecasts() } diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/aqicn/Data.kt b/weather-api/src/main/java/com/thewizrd/weather_api/aqicn/Data.kt index 79ac2ceb..6fb6db46 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/aqicn/Data.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/aqicn/Data.kt @@ -15,7 +15,7 @@ data class Data( var city: City? = null, @Json(name = "aqi") - var aqi: Int? = null, + var aqi: String? = null, @Json(name = "forecast") var forecast: Forecast? = null, diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt index 36846836..6414acdb 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt @@ -182,12 +182,16 @@ class MeteoFranceProvider : WeatherProviderImpl() { .url(String.format(ALERTS_QUERY_URL, foreRoot.position!!.dept, key)) .build() - alertsResponse = client.newCall(alertsRequest).await() - alertStream = alertsResponse.getStream() - alertsRoot = JSONParser.deserializer( - alertStream, - AlertsResponse::class.java - ) + runCatching { + alertsResponse = client.newCall(alertsRequest).await() + alertStream = alertsResponse.getStream() + alertsRoot = JSONParser.deserializer( + alertStream, + AlertsResponse::class.java + ) + }.getOrElse { + Logger.warn("MeteoFranceProvider", it, "Error fetching alerts") + } } // End Stream diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/OpenMeteoWeatherProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/OpenMeteoWeatherProvider.kt index 2fdfdec0..fdc9851b 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/OpenMeteoWeatherProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/OpenMeteoWeatherProvider.kt @@ -524,8 +524,7 @@ class OpenMeteoWeatherProvider : WeatherProviderImpl(), PollenProvider { * 3: overcast */ 3 -> { - weatherIcon = - if (isNight) WeatherIcons.NIGHT_OVERCAST else WeatherIcons.DAY_SUNNY_OVERCAST + weatherIcon = WeatherIcons.OVERCAST } /* diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherAlerts.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherAlerts.kt index 0463ef17..11b05339 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherAlerts.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherAlerts.kt @@ -1,5 +1,6 @@ package com.thewizrd.weather_api.weatherapi.weather +import android.annotation.SuppressLint import com.thewizrd.shared_resources.weatherdata.model.WeatherAlert import com.thewizrd.shared_resources.weatherdata.model.WeatherAlertSeverity import com.thewizrd.shared_resources.weatherdata.model.WeatherAlertType @@ -9,7 +10,7 @@ import java.time.format.DateTimeFormatter fun createWeatherAlerts(alerts: Alerts?): Collection? { if (alerts?.alert.isNullOrEmpty()) return null - val weatherAlerts = ArrayList(alerts!!.alert!!.size) + val weatherAlerts = ArrayList(alerts.alert!!.size) for (alert in alerts.alert!!) { weatherAlerts.add(createWeatherAlert(alert)) @@ -18,6 +19,7 @@ fun createWeatherAlerts(alerts: Alerts?): Collection? { return weatherAlerts } +@SuppressLint("VisibleForTests") fun createWeatherAlert(alert: AlertItem): WeatherAlert { return WeatherAlert().apply { type = when { @@ -52,9 +54,11 @@ fun createWeatherAlert(alert: AlertItem): WeatherAlert { attribution = alert.note ?: "WeatherAPI.com" - date = ZonedDateTime.parse(alert.effective, - DateTimeFormatter.ISO_ZONED_DATE_TIME) - expiresDate = ZonedDateTime.parse(alert.expires, - DateTimeFormatter.ISO_ZONED_DATE_TIME) + date = + alert.effective?.let { ZonedDateTime.parse(it, DateTimeFormatter.ISO_ZONED_DATE_TIME) } + ?: ZonedDateTime.now() + expiresDate = + alert.expires?.let { ZonedDateTime.parse(it, DateTimeFormatter.ISO_ZONED_DATE_TIME) } + ?: date.plusDays(1) } } \ No newline at end of file diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt index 476927f5..066e5958 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt @@ -55,15 +55,19 @@ fun createWeatherData(root: ForecastResponse): Weather { .withZoneSameInstant(tzid) } ?: ZonedDateTime.now(tzid) - forecast = ArrayList(root.forecast!!.forecastday!!.size) + forecast = ArrayList().apply { + root.forecast?.forecastday?.size?.let { + ensureCapacity(it) + } + } hrForecast = ArrayList().apply { - root.forecast!!.forecastday?.firstOrNull()?.hour?.size?.let { + root.forecast?.forecastday?.firstOrNull()?.hour?.size?.let { ensureCapacity(it) } } // Forecast - for (day in root.forecast!!.forecastday!!) { + root.forecast?.forecastday?.forEach { day -> val fcast = createForecast(day) day.hour?.forEach { hour -> @@ -82,10 +86,10 @@ fun createWeatherData(root: ForecastResponse): Weather { condition = createCondition(root.current!!, tzid) atmosphere = createAtmosphere(root.current!!) - if (root.forecast!!.forecastday!![0].date == condition!!.observationTime.toLocalDate() + if (root.forecast?.forecastday?.getOrNull(0)?.date == condition!!.observationTime.toLocalDate() .format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) ) { - astronomy = createAstronomy(root.forecast!!.forecastday!![0].astro!!) + astronomy = createAstronomy(root.forecast?.forecastday?.getOrNull(0)?.astro) } precipitation = createPrecipitation(root.current!!) ttl = 180 @@ -210,10 +214,10 @@ fun createCondition(current: Current, tzId: ZoneId): Condition { feelslikeC = current.feelslikeC icon = weatherModule.weatherManager.getWeatherProvider(WeatherAPI.WEATHERAPI) - .getWeatherIcon(current.isDay == 0, current.condition!!.code!!.toString()) + .getWeatherIcon(current.isDay == 0, current.condition?.code?.toString()) beaufort = Beaufort(getBeaufortScale(windMph.toInt())) - uv = UV(current.uv!!) + uv = current.uv?.let { UV(it) } airQuality = createAirQuality(current.airQuality) @@ -280,41 +284,44 @@ fun createAtmosphere(current: Current): Atmosphere { } } -fun createAstronomy(astro: Astro): Astronomy { +fun createAstronomy(astro: Astro?): Astronomy { return Astronomy().apply { val now = LocalDate.now() runCatching { - sunrise = LocalTime.parse(astro.sunrise, DateTimeFormatter.ofPattern("hh:mm a")).atDate(now) + sunrise = + LocalTime.parse(astro?.sunrise, DateTimeFormatter.ofPattern("hh:mm a")).atDate(now) }.getOrElse { - if (astro.sunrise == "Polar Day" || astro.sunrise == "Polar Night") { + if (astro?.sunrise == "Polar Day" || astro?.sunrise == "Polar Night") { sunrise = LocalDateTime.now().plusYears(1).minusNanos(1) } } runCatching { sunset = - LocalTime.parse(astro.sunset, DateTimeFormatter.ofPattern("hh:mm a")).atDate(now) + LocalTime.parse(astro?.sunset, DateTimeFormatter.ofPattern("hh:mm a")).atDate(now) if (sunrise != null && sunset.isBefore(sunrise)) { // Is next day - sunset = LocalTime.parse(astro.sunset, DateTimeFormatter.ofPattern("hh:mm a")) + sunset = LocalTime.parse(astro?.sunset, DateTimeFormatter.ofPattern("hh:mm a")) .atDate(now.plusDays(1)) } }.getOrElse { - if (astro.sunset == "Polar Day" || astro.sunset == "Polar Night") { + if (astro?.sunset == "Polar Day" || astro?.sunset == "Polar Night") { sunset = LocalDateTime.now().plusYears(1).minusNanos(1) } } runCatching { - moonrise = LocalTime.parse(astro.moonrise, DateTimeFormatter.ofPattern("hh:mm a")).atDate(now) + moonrise = + LocalTime.parse(astro?.moonrise, DateTimeFormatter.ofPattern("hh:mm a")).atDate(now) } runCatching { - moonset = LocalTime.parse(astro.moonset, DateTimeFormatter.ofPattern("hh:mm a")).atDate(now) + moonset = + LocalTime.parse(astro?.moonset, DateTimeFormatter.ofPattern("hh:mm a")).atDate(now) } - when (astro.moonPhase) { + when (astro?.moonPhase) { "New Moon" -> moonPhase = MoonPhase(MoonPhase.MoonPhaseType.NEWMOON) "Waxing Crescent" -> moonPhase = MoonPhase(MoonPhase.MoonPhaseType.WAXING_CRESCENT) "First Quarter" -> moonPhase = MoonPhase(MoonPhase.MoonPhaseType.FIRST_QTR) From 6fc27e649eae33a6e033303b00340407c4f556cd Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Fri, 19 Jun 2026 15:38:43 -0400 Subject: [PATCH 37/67] WeatherIconicProvider: update icons * update from v2.2 and add color variant --- .../icons/WeatherIconicProvider.kt | 256 +++++++++--------- .../icons/WeatherIconsManager.kt | 4 +- .../src/main/res/drawable/wic_barometer.xml | 20 +- .../src/main/res/drawable/wic_celsius.xml | 19 +- .../src/main/res/drawable/wic_cloud.xml | 9 +- .../src/main/res/drawable/wic_cloud_fog.xml | 25 +- .../src/main/res/drawable/wic_cloud_hail.xml | 29 ++ .../src/main/res/drawable/wic_cloud_haze.xml | 27 ++ .../src/main/res/drawable/wic_cloud_rain.xml | 28 +- .../main/res/drawable/wic_cloud_rain_alt.xml | 29 ++ .../res/drawable/wic_cloud_rain_single.xml | 20 -- .../src/main/res/drawable/wic_cloud_sleet.xml | 29 ++ .../src/main/res/drawable/wic_cloud_smog.xml | 29 ++ .../src/main/res/drawable/wic_cloud_snow.xml | 40 ++- .../main/res/drawable/wic_cloud_snow_alt.xml | 29 ++ .../src/main/res/drawable/wic_cloud_wind.xml | 26 +- .../src/main/res/drawable/wic_clouds.xml | 23 +- .../src/main/res/drawable/wic_clouds_alt.xml | 27 ++ .../main/res/drawable/wic_color_barometer.xml | 29 ++ .../main/res/drawable/wic_color_celsius.xml | 29 ++ .../src/main/res/drawable/wic_color_cloud.xml | 18 ++ .../main/res/drawable/wic_color_cloud_fog.xml | 29 ++ .../res/drawable/wic_color_cloud_hail.xml | 29 ++ .../res/drawable/wic_color_cloud_haze.xml | 27 ++ .../res/drawable/wic_color_cloud_rain.xml | 29 ++ .../res/drawable/wic_color_cloud_rain_alt.xml | 29 ++ .../res/drawable/wic_color_cloud_sleet.xml | 29 ++ .../res/drawable/wic_color_cloud_smog.xml | 29 ++ .../res/drawable/wic_color_cloud_snow.xml | 29 ++ .../res/drawable/wic_color_cloud_snow_alt.xml | 29 ++ .../res/drawable/wic_color_cloud_wind.xml | 29 ++ .../main/res/drawable/wic_color_clouds.xml | 29 ++ .../res/drawable/wic_color_clouds_alt.xml | 27 ++ .../main/res/drawable/wic_color_compass.xml | 29 ++ .../res/drawable/wic_color_fahrenheit.xml | 29 ++ .../src/main/res/drawable/wic_color_fire.xml | 25 ++ .../src/main/res/drawable/wic_color_flood.xml | 29 ++ .../src/main/res/drawable/wic_color_fog.xml | 29 ++ .../main/res/drawable/wic_color_humidity.xml | 18 ++ .../main/res/drawable/wic_color_hurricane.xml | 31 +++ .../src/main/res/drawable/wic_color_info.xml | 31 +++ .../main/res/drawable/wic_color_lightning.xml | 29 ++ .../src/main/res/drawable/wic_color_moon.xml | 18 ++ .../res/drawable/wic_color_moon_cloud.xml | 29 ++ .../res/drawable/wic_color_moon_cloud_fog.xml | 29 ++ .../drawable/wic_color_moon_cloud_hail.xml | 29 ++ .../drawable/wic_color_moon_cloud_haze.xml | 29 ++ .../wic_color_moon_cloud_lightning.xml | 29 ++ .../drawable/wic_color_moon_cloud_rain.xml | 29 ++ .../wic_color_moon_cloud_rain_alt.xml | 29 ++ .../drawable/wic_color_moon_cloud_sleet.xml | 29 ++ .../drawable/wic_color_moon_cloud_snow.xml | 29 ++ .../wic_color_moon_cloud_snow_alt.xml | 29 ++ .../drawable/wic_color_moon_cloud_wind.xml | 29 ++ .../drawable/wic_color_moon_first_quarter.xml | 29 ++ .../main/res/drawable/wic_color_moon_fog.xml | 29 ++ .../res/drawable/wic_color_moon_fullmoon.xml | 18 ++ .../drawable/wic_color_moon_last_quarter.xml | 29 ++ .../res/drawable/wic_color_moon_newmoon.xml | 18 ++ .../wic_color_moon_waning_crescent.xml | 29 ++ .../wic_color_moon_waning_gibbous.xml | 29 ++ .../wic_color_moon_waxing_crescent.xml | 29 ++ .../wic_color_moon_waxing_gibbous.xml | 29 ++ .../main/res/drawable/wic_color_moonrise.xml | 27 ++ .../main/res/drawable/wic_color_moonset.xml | 29 ++ .../src/main/res/drawable/wic_color_na.xml | 18 ++ .../main/res/drawable/wic_color_pollen.xml | 18 ++ .../main/res/drawable/wic_color_raindrop.xml | 29 ++ .../main/res/drawable/wic_color_sandstorm.xml | 29 ++ .../main/res/drawable/wic_color_snowflake.xml | 18 ++ .../src/main/res/drawable/wic_color_sun.xml | 18 ++ .../main/res/drawable/wic_color_sun_cloud.xml | 29 ++ .../res/drawable/wic_color_sun_cloud_fog.xml | 29 ++ .../res/drawable/wic_color_sun_cloud_hail.xml | 29 ++ .../res/drawable/wic_color_sun_cloud_haze.xml | 29 ++ .../wic_color_sun_cloud_lightning.xml | 29 ++ .../res/drawable/wic_color_sun_cloud_rain.xml | 29 ++ .../drawable/wic_color_sun_cloud_rain_alt.xml | 29 ++ .../drawable/wic_color_sun_cloud_sleet.xml | 29 ++ .../res/drawable/wic_color_sun_cloud_snow.xml | 29 ++ .../drawable/wic_color_sun_cloud_snow_alt.xml | 29 ++ .../res/drawable/wic_color_sun_cloud_wind.xml | 29 ++ .../main/res/drawable/wic_color_sun_fog.xml | 29 ++ .../main/res/drawable/wic_color_sunrise.xml | 27 ++ .../main/res/drawable/wic_color_sunset.xml | 27 ++ .../drawable/wic_color_thermometer_cold.xml | 29 ++ .../drawable/wic_color_thermometer_freeze.xml | 29 ++ .../drawable/wic_color_thermometer_heat.xml | 18 ++ .../drawable/wic_color_thermometer_hot.xml | 29 ++ .../drawable/wic_color_thermometer_medium.xml | 29 ++ .../main/res/drawable/wic_color_tornado.xml | 27 ++ .../main/res/drawable/wic_color_umbrella.xml | 29 ++ .../src/main/res/drawable/wic_color_wind.xml | 29 ++ .../main/res/drawable/wic_color_wind_high.xml | 29 ++ .../src/main/res/drawable/wic_compass.xml | 22 +- .../src/main/res/drawable/wic_fahrenheit.xml | 22 +- .../src/main/res/drawable/wic_fire.xml | 25 ++ .../src/main/res/drawable/wic_flood.xml | 29 ++ .../src/main/res/drawable/wic_fog.xml | 31 ++- .../src/main/res/drawable/wic_hail.xml | 28 -- .../src/main/res/drawable/wic_humidity.xml | 18 ++ .../src/main/res/drawable/wic_hurricane.xml | 31 +++ .../src/main/res/drawable/wic_info.xml | 31 +++ .../src/main/res/drawable/wic_lightning.xml | 22 +- .../src/main/res/drawable/wic_moon.xml | 12 +- .../src/main/res/drawable/wic_moon_cloud.xml | 23 +- .../main/res/drawable/wic_moon_cloud_fog.xml | 29 ++ .../main/res/drawable/wic_moon_cloud_hail.xml | 29 ++ .../main/res/drawable/wic_moon_cloud_haze.xml | 29 ++ .../res/drawable/wic_moon_cloud_lightning.xml | 22 +- .../main/res/drawable/wic_moon_cloud_rain.xml | 29 +- .../res/drawable/wic_moon_cloud_rain_alt.xml | 29 ++ .../res/drawable/wic_moon_cloud_sleet.xml | 29 ++ .../main/res/drawable/wic_moon_cloud_snow.xml | 40 ++- .../res/drawable/wic_moon_cloud_snow_alt.xml | 29 ++ .../main/res/drawable/wic_moon_cloud_wind.xml | 25 +- .../res/drawable/wic_moon_first_quarter.xml | 23 +- .../src/main/res/drawable/wic_moon_fog.xml | 24 +- .../main/res/drawable/wic_moon_fullmoon.xml | 12 +- .../res/drawable/wic_moon_last_quarter.xml | 24 +- .../main/res/drawable/wic_moon_newmoon.xml | 13 +- .../res/drawable/wic_moon_waning_crescent.xml | 23 +- .../res/drawable/wic_moon_waning_gibbous.xml | 23 +- .../res/drawable/wic_moon_waxing_crescent.xml | 24 +- .../res/drawable/wic_moon_waxing_gibbous.xml | 24 +- .../src/main/res/drawable/wic_moonrise.xml | 27 ++ .../src/main/res/drawable/wic_moonset.xml | 29 ++ .../src/main/res/drawable/wic_na.xml | 18 ++ .../src/main/res/drawable/wic_pollen.xml | 18 ++ .../src/main/res/drawable/wic_raindrop.xml | 22 +- .../src/main/res/drawable/wic_sandstorm.xml | 29 ++ .../src/main/res/drawable/wic_snowflake.xml | 13 +- .../src/main/res/drawable/wic_sun.xml | 36 +-- .../src/main/res/drawable/wic_sun_cloud.xml | 32 +-- .../main/res/drawable/wic_sun_cloud_fog.xml | 29 ++ .../main/res/drawable/wic_sun_cloud_hail.xml | 29 ++ .../main/res/drawable/wic_sun_cloud_haze.xml | 29 ++ .../res/drawable/wic_sun_cloud_lightning.xml | 35 ++- .../main/res/drawable/wic_sun_cloud_rain.xml | 41 ++- .../res/drawable/wic_sun_cloud_rain_alt.xml | 29 ++ .../main/res/drawable/wic_sun_cloud_sleet.xml | 29 ++ .../main/res/drawable/wic_sun_cloud_snow.xml | 53 ++-- .../res/drawable/wic_sun_cloud_snow_alt.xml | 29 ++ .../main/res/drawable/wic_sun_cloud_wind.xml | 38 ++- .../src/main/res/drawable/wic_sun_fog.xml | 28 +- .../src/main/res/drawable/wic_sunrise.xml | 40 ++- .../src/main/res/drawable/wic_sunset.xml | 40 ++- .../res/drawable/wic_thermometer_cold.xml | 29 ++ .../res/drawable/wic_thermometer_freeze.xml | 29 ++ .../res/drawable/wic_thermometer_heat.xml | 18 ++ .../main/res/drawable/wic_thermometer_hot.xml | 23 +- .../res/drawable/wic_thermometer_medium.xml | 23 +- .../src/main/res/drawable/wic_tornado.xml | 26 +- .../src/main/res/drawable/wic_umbrella.xml | 24 +- .../src/main/res/drawable/wic_wind.xml | 26 +- .../src/main/res/drawable/wic_wind_high.xml | 29 +- 156 files changed, 3771 insertions(+), 654 deletions(-) create mode 100644 shared_resources/src/main/res/drawable/wic_cloud_hail.xml create mode 100644 shared_resources/src/main/res/drawable/wic_cloud_haze.xml create mode 100644 shared_resources/src/main/res/drawable/wic_cloud_rain_alt.xml delete mode 100644 shared_resources/src/main/res/drawable/wic_cloud_rain_single.xml create mode 100644 shared_resources/src/main/res/drawable/wic_cloud_sleet.xml create mode 100644 shared_resources/src/main/res/drawable/wic_cloud_smog.xml create mode 100644 shared_resources/src/main/res/drawable/wic_cloud_snow_alt.xml create mode 100644 shared_resources/src/main/res/drawable/wic_clouds_alt.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_barometer.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_celsius.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_cloud.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_cloud_fog.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_cloud_hail.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_cloud_haze.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_cloud_rain.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_cloud_rain_alt.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_cloud_sleet.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_cloud_smog.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_cloud_snow.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_cloud_snow_alt.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_cloud_wind.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_clouds.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_clouds_alt.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_compass.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_fahrenheit.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_fire.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_flood.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_fog.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_humidity.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_hurricane.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_info.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_lightning.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_cloud.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_cloud_fog.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_cloud_hail.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_cloud_haze.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_cloud_lightning.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_cloud_rain.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_cloud_rain_alt.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_cloud_sleet.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_cloud_snow.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_cloud_snow_alt.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_cloud_wind.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_first_quarter.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_fog.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_fullmoon.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_last_quarter.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_newmoon.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_waning_crescent.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_waning_gibbous.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_waxing_crescent.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moon_waxing_gibbous.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moonrise.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_moonset.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_na.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_pollen.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_raindrop.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sandstorm.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_snowflake.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sun.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sun_cloud.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sun_cloud_fog.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sun_cloud_hail.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sun_cloud_haze.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sun_cloud_lightning.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sun_cloud_rain.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sun_cloud_rain_alt.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sun_cloud_sleet.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sun_cloud_snow.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sun_cloud_snow_alt.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sun_cloud_wind.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sun_fog.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sunrise.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_sunset.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_thermometer_cold.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_thermometer_freeze.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_thermometer_heat.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_thermometer_hot.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_thermometer_medium.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_tornado.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_umbrella.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_wind.xml create mode 100644 shared_resources/src/main/res/drawable/wic_color_wind_high.xml create mode 100644 shared_resources/src/main/res/drawable/wic_fire.xml create mode 100644 shared_resources/src/main/res/drawable/wic_flood.xml delete mode 100644 shared_resources/src/main/res/drawable/wic_hail.xml create mode 100644 shared_resources/src/main/res/drawable/wic_humidity.xml create mode 100644 shared_resources/src/main/res/drawable/wic_hurricane.xml create mode 100644 shared_resources/src/main/res/drawable/wic_info.xml create mode 100644 shared_resources/src/main/res/drawable/wic_moon_cloud_fog.xml create mode 100644 shared_resources/src/main/res/drawable/wic_moon_cloud_hail.xml create mode 100644 shared_resources/src/main/res/drawable/wic_moon_cloud_haze.xml create mode 100644 shared_resources/src/main/res/drawable/wic_moon_cloud_rain_alt.xml create mode 100644 shared_resources/src/main/res/drawable/wic_moon_cloud_sleet.xml create mode 100644 shared_resources/src/main/res/drawable/wic_moon_cloud_snow_alt.xml create mode 100644 shared_resources/src/main/res/drawable/wic_moonrise.xml create mode 100644 shared_resources/src/main/res/drawable/wic_moonset.xml create mode 100644 shared_resources/src/main/res/drawable/wic_na.xml create mode 100644 shared_resources/src/main/res/drawable/wic_pollen.xml create mode 100644 shared_resources/src/main/res/drawable/wic_sandstorm.xml create mode 100644 shared_resources/src/main/res/drawable/wic_sun_cloud_fog.xml create mode 100644 shared_resources/src/main/res/drawable/wic_sun_cloud_hail.xml create mode 100644 shared_resources/src/main/res/drawable/wic_sun_cloud_haze.xml create mode 100644 shared_resources/src/main/res/drawable/wic_sun_cloud_rain_alt.xml create mode 100644 shared_resources/src/main/res/drawable/wic_sun_cloud_sleet.xml create mode 100644 shared_resources/src/main/res/drawable/wic_sun_cloud_snow_alt.xml create mode 100644 shared_resources/src/main/res/drawable/wic_thermometer_cold.xml create mode 100644 shared_resources/src/main/res/drawable/wic_thermometer_freeze.xml create mode 100644 shared_resources/src/main/res/drawable/wic_thermometer_heat.xml diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconicProvider.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconicProvider.kt index db0ca050..3b419936 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconicProvider.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconicProvider.kt @@ -3,130 +3,130 @@ package com.thewizrd.shared_resources.icons import androidx.annotation.DrawableRes import com.thewizrd.shared_resources.R -class WeatherIconicProvider : WeatherIconProvider() { +class WeatherIconicProvider(private val isColored: Boolean = false) : WeatherIconProvider() { override fun getKey(): String { - return "w-iconic-jackd248" + return "w-iconic-jackd248" + if (isColored) "-multicolor" else "" } override fun getDisplayName(): String { - return "Weather Iconic" + return "Weather Iconic" + if (isColored) " (Multi-Color)" else "" } override fun getAuthorName(): String { - return "jackd248" + return "konradmichalik" } override fun getAttributionLink(): String { - return "https://github.com/jackd248/weather-iconic" + return "https://konradmichalik.github.io/weather-iconic/" } override fun isFontIcon(): Boolean { - return true + return !isColored } @DrawableRes override fun getWeatherIconResource(icon: String): Int { var weatherIcon = when (icon) { - WeatherIcons.DAY_SUNNY -> R.drawable.wic_sun - WeatherIcons.DAY_CLOUDY -> R.drawable.wic_sun_cloud - WeatherIcons.DAY_CLOUDY_GUSTS -> R.drawable.wic_sun_cloud_wind - WeatherIcons.DAY_CLOUDY_WINDY -> R.drawable.wic_sun_cloud_wind - WeatherIcons.DAY_FOG -> R.drawable.wic_sun_fog - WeatherIcons.DAY_HAIL -> R.drawable.wic_hail - WeatherIcons.DAY_HAZE -> R.drawable.wic_sun_fog - WeatherIcons.DAY_LIGHTNING -> R.drawable.wic_sun_cloud_lightning - WeatherIcons.DAY_PARTLY_CLOUDY -> R.drawable.wic_sun_cloud - WeatherIcons.DAY_RAIN -> R.drawable.wic_sun_cloud_rain - WeatherIcons.DAY_RAIN_MIX -> R.drawable.wic_sun_cloud_rain - WeatherIcons.DAY_RAIN_WIND -> R.drawable.wic_sun_cloud_rain - WeatherIcons.DAY_SHOWERS -> R.drawable.wic_sun_cloud_rain - WeatherIcons.DAY_SLEET -> R.drawable.wic_sun_cloud_rain - WeatherIcons.DAY_SLEET_STORM -> R.drawable.wic_sun_cloud_rain - WeatherIcons.DAY_SNOW -> R.drawable.wic_sun_cloud_snow - WeatherIcons.DAY_SNOW_THUNDERSTORM -> R.drawable.wic_sun_cloud_snow - WeatherIcons.DAY_SNOW_WIND -> R.drawable.wic_sun_cloud_snow - WeatherIcons.DAY_SPRINKLE -> R.drawable.wic_sun_cloud_rain - WeatherIcons.DAY_STORM_SHOWERS -> R.drawable.wic_sun_cloud_lightning - WeatherIcons.DAY_SUNNY_OVERCAST -> R.drawable.wic_sun_cloud - WeatherIcons.DAY_THUNDERSTORM -> R.drawable.wic_sun_cloud_lightning - WeatherIcons.DAY_WINDY -> R.drawable.wic_wind - WeatherIcons.DAY_HOT -> R.drawable.wic_sun - WeatherIcons.DAY_CLOUDY_HIGH -> R.drawable.wic_sun_cloud - WeatherIcons.DAY_LIGHT_WIND -> R.drawable.wic_wind - - WeatherIcons.NIGHT_CLEAR -> R.drawable.wic_moon - WeatherIcons.NIGHT_ALT_CLOUDY -> R.drawable.wic_moon_cloud - WeatherIcons.NIGHT_ALT_CLOUDY_GUSTS -> R.drawable.wic_moon_cloud_wind - WeatherIcons.NIGHT_ALT_CLOUDY_WINDY -> R.drawable.wic_moon_cloud_wind - WeatherIcons.NIGHT_ALT_HAIL -> R.drawable.wic_hail - WeatherIcons.NIGHT_ALT_LIGHTNING -> R.drawable.wic_moon_cloud_lightning - WeatherIcons.NIGHT_ALT_RAIN -> R.drawable.wic_moon_cloud_rain - WeatherIcons.NIGHT_ALT_RAIN_MIX -> R.drawable.wic_moon_cloud_rain - WeatherIcons.NIGHT_ALT_RAIN_WIND -> R.drawable.wic_moon_cloud_rain - WeatherIcons.NIGHT_ALT_SHOWERS -> R.drawable.wic_moon_cloud_rain - WeatherIcons.NIGHT_ALT_SLEET -> R.drawable.wic_moon_cloud_rain - WeatherIcons.NIGHT_ALT_SLEET_STORM -> R.drawable.wic_moon_cloud_rain - WeatherIcons.NIGHT_ALT_SNOW -> R.drawable.wic_moon_cloud_snow - WeatherIcons.NIGHT_ALT_SNOW_THUNDERSTORM -> R.drawable.wic_moon_cloud_snow - WeatherIcons.NIGHT_ALT_SNOW_WIND -> R.drawable.wic_moon_cloud_snow - WeatherIcons.NIGHT_ALT_SPRINKLE -> R.drawable.wic_moon_cloud_rain - WeatherIcons.NIGHT_ALT_STORM_SHOWERS -> R.drawable.wic_moon_cloud_lightning - WeatherIcons.NIGHT_ALT_THUNDERSTORM -> R.drawable.wic_moon_cloud_lightning - WeatherIcons.NIGHT_ALT_PARTLY_CLOUDY -> R.drawable.wic_moon_cloud - WeatherIcons.NIGHT_ALT_CLOUDY_HIGH -> R.drawable.wic_moon_cloud - WeatherIcons.NIGHT_FOG -> R.drawable.wic_moon_fog - WeatherIcons.NIGHT_OVERCAST -> R.drawable.wic_moon_cloud - WeatherIcons.NIGHT_HAZE -> R.drawable.wic_moon_fog - WeatherIcons.NIGHT_WINDY -> R.drawable.wic_wind - WeatherIcons.NIGHT_HOT -> R.drawable.wic_moon - WeatherIcons.NIGHT_LIGHT_WIND -> R.drawable.wic_wind - - WeatherIcons.CLOUD -> R.drawable.wic_cloud - WeatherIcons.CLOUDY -> R.drawable.wic_clouds - WeatherIcons.CLOUDY_GUSTS -> R.drawable.wic_cloud_wind - WeatherIcons.CLOUDY_WINDY -> R.drawable.wic_cloud_wind - WeatherIcons.FOG -> R.drawable.wic_fog - WeatherIcons.HAIL -> R.drawable.wic_hail - WeatherIcons.HAZE -> R.drawable.wic_fog - WeatherIcons.HOT -> R.drawable.wic_thermometer_hot - WeatherIcons.LIGHT_WIND -> R.drawable.wic_wind - WeatherIcons.RAIN -> R.drawable.wic_cloud_rain - WeatherIcons.RAIN_MIX -> R.drawable.wic_cloud_rain - WeatherIcons.RAIN_WIND -> R.drawable.wic_cloud_rain - WeatherIcons.OVERCAST -> R.drawable.wic_clouds - WeatherIcons.SHOWERS -> R.drawable.wic_cloud_rain - WeatherIcons.SLEET -> R.drawable.wic_cloud_rain - WeatherIcons.SLEET_STORM -> R.drawable.wic_cloud_rain - WeatherIcons.SNOW -> R.drawable.wic_cloud_snow - WeatherIcons.SNOW_THUNDERSTORM -> R.drawable.wic_cloud_snow - WeatherIcons.SPRINKLE -> R.drawable.wic_cloud_rain_single - WeatherIcons.STORM_SHOWERS -> R.drawable.wic_lightning - WeatherIcons.THUNDERSTORM -> R.drawable.wic_lightning - WeatherIcons.SNOW_WIND -> R.drawable.wic_cloud_snow - WeatherIcons.SMOG -> R.drawable.wi_smog + WeatherIcons.DAY_SUNNY -> if (isColored) R.drawable.wic_color_sun else R.drawable.wic_sun + WeatherIcons.DAY_CLOUDY -> if (isColored) R.drawable.wic_color_sun_cloud else R.drawable.wic_sun_cloud + WeatherIcons.DAY_CLOUDY_GUSTS -> if (isColored) R.drawable.wic_color_sun_cloud_wind else R.drawable.wic_sun_cloud_wind + WeatherIcons.DAY_CLOUDY_WINDY -> if (isColored) R.drawable.wic_color_sun_cloud_wind else R.drawable.wic_sun_cloud_wind + WeatherIcons.DAY_FOG -> if (isColored) R.drawable.wic_color_sun_fog else R.drawable.wic_sun_fog + WeatherIcons.DAY_HAIL -> if (isColored) R.drawable.wic_color_sun_cloud_hail else R.drawable.wic_sun_cloud_hail + WeatherIcons.DAY_HAZE -> if (isColored) R.drawable.wic_color_sun_cloud_haze else R.drawable.wic_sun_cloud_haze + WeatherIcons.DAY_LIGHTNING -> if (isColored) R.drawable.wic_color_sun_cloud_lightning else R.drawable.wic_sun_cloud_lightning + WeatherIcons.DAY_PARTLY_CLOUDY -> if (isColored) R.drawable.wic_color_sun_cloud else R.drawable.wic_sun_cloud + WeatherIcons.DAY_RAIN -> if (isColored) R.drawable.wic_color_sun_cloud_rain else R.drawable.wic_sun_cloud_rain + WeatherIcons.DAY_RAIN_MIX -> if (isColored) R.drawable.wic_color_sun_cloud_rain else R.drawable.wic_sun_cloud_rain + WeatherIcons.DAY_RAIN_WIND -> if (isColored) R.drawable.wic_color_sun_cloud_rain else R.drawable.wic_sun_cloud_rain + WeatherIcons.DAY_SHOWERS -> if (isColored) R.drawable.wic_color_sun_cloud_rain else R.drawable.wic_sun_cloud_rain + WeatherIcons.DAY_SLEET -> if (isColored) R.drawable.wic_color_sun_cloud_rain else R.drawable.wic_sun_cloud_rain + WeatherIcons.DAY_SLEET_STORM -> if (isColored) R.drawable.wic_color_sun_cloud_rain else R.drawable.wic_sun_cloud_rain + WeatherIcons.DAY_SNOW -> if (isColored) R.drawable.wic_color_sun_cloud_snow_alt else R.drawable.wic_sun_cloud_snow_alt + WeatherIcons.DAY_SNOW_THUNDERSTORM -> if (isColored) R.drawable.wic_color_sun_cloud_snow else R.drawable.wic_sun_cloud_snow + WeatherIcons.DAY_SNOW_WIND -> if (isColored) R.drawable.wic_color_sun_cloud_snow else R.drawable.wic_sun_cloud_snow + WeatherIcons.DAY_SPRINKLE -> if (isColored) R.drawable.wic_color_sun_cloud_rain_alt else R.drawable.wic_sun_cloud_rain_alt + WeatherIcons.DAY_STORM_SHOWERS -> if (isColored) R.drawable.wic_color_sun_cloud_lightning else R.drawable.wic_sun_cloud_lightning + WeatherIcons.DAY_SUNNY_OVERCAST -> if (isColored) R.drawable.wic_color_sun_cloud else R.drawable.wic_sun_cloud + WeatherIcons.DAY_THUNDERSTORM -> if (isColored) R.drawable.wic_color_sun_cloud_lightning else R.drawable.wic_sun_cloud_lightning + WeatherIcons.DAY_WINDY -> if (isColored) R.drawable.wic_color_wind else R.drawable.wic_wind + WeatherIcons.DAY_HOT -> if (isColored) R.drawable.wic_color_sun else R.drawable.wic_sun + WeatherIcons.DAY_CLOUDY_HIGH -> if (isColored) R.drawable.wic_color_sun_cloud else R.drawable.wic_sun_cloud + WeatherIcons.DAY_LIGHT_WIND -> if (isColored) R.drawable.wic_color_wind else R.drawable.wic_wind + + WeatherIcons.NIGHT_CLEAR -> if (isColored) R.drawable.wic_color_moon else R.drawable.wic_moon + WeatherIcons.NIGHT_ALT_CLOUDY -> if (isColored) R.drawable.wic_color_moon_cloud else R.drawable.wic_moon_cloud + WeatherIcons.NIGHT_ALT_CLOUDY_GUSTS -> if (isColored) R.drawable.wic_color_moon_cloud_wind else R.drawable.wic_moon_cloud_wind + WeatherIcons.NIGHT_ALT_CLOUDY_WINDY -> if (isColored) R.drawable.wic_color_moon_cloud_wind else R.drawable.wic_moon_cloud_wind + WeatherIcons.NIGHT_ALT_HAIL -> if (isColored) R.drawable.wic_color_moon_cloud_hail else R.drawable.wic_moon_cloud_hail + WeatherIcons.NIGHT_ALT_LIGHTNING -> if (isColored) R.drawable.wic_color_moon_cloud_lightning else R.drawable.wic_moon_cloud_lightning + WeatherIcons.NIGHT_ALT_RAIN -> if (isColored) R.drawable.wic_color_moon_cloud_rain else R.drawable.wic_moon_cloud_rain + WeatherIcons.NIGHT_ALT_RAIN_MIX -> if (isColored) R.drawable.wic_color_moon_cloud_rain else R.drawable.wic_moon_cloud_rain + WeatherIcons.NIGHT_ALT_RAIN_WIND -> if (isColored) R.drawable.wic_color_moon_cloud_rain else R.drawable.wic_moon_cloud_rain + WeatherIcons.NIGHT_ALT_SHOWERS -> if (isColored) R.drawable.wic_color_moon_cloud_rain else R.drawable.wic_moon_cloud_rain + WeatherIcons.NIGHT_ALT_SLEET -> if (isColored) R.drawable.wic_color_moon_cloud_sleet else R.drawable.wic_moon_cloud_sleet + WeatherIcons.NIGHT_ALT_SLEET_STORM -> if (isColored) R.drawable.wic_color_moon_cloud_sleet else R.drawable.wic_moon_cloud_sleet + WeatherIcons.NIGHT_ALT_SNOW -> if (isColored) R.drawable.wic_color_moon_cloud_snow_alt else R.drawable.wic_moon_cloud_snow_alt + WeatherIcons.NIGHT_ALT_SNOW_THUNDERSTORM -> if (isColored) R.drawable.wic_color_moon_cloud_snow else R.drawable.wic_moon_cloud_snow + WeatherIcons.NIGHT_ALT_SNOW_WIND -> if (isColored) R.drawable.wic_color_moon_cloud_snow else R.drawable.wic_moon_cloud_snow + WeatherIcons.NIGHT_ALT_SPRINKLE -> if (isColored) R.drawable.wic_color_moon_cloud_rain_alt else R.drawable.wic_moon_cloud_rain_alt + WeatherIcons.NIGHT_ALT_STORM_SHOWERS -> if (isColored) R.drawable.wic_color_moon_cloud_lightning else R.drawable.wic_moon_cloud_lightning + WeatherIcons.NIGHT_ALT_THUNDERSTORM -> if (isColored) R.drawable.wic_color_moon_cloud_lightning else R.drawable.wic_moon_cloud_lightning + WeatherIcons.NIGHT_ALT_PARTLY_CLOUDY -> if (isColored) R.drawable.wic_color_moon_cloud else R.drawable.wic_moon_cloud + WeatherIcons.NIGHT_ALT_CLOUDY_HIGH -> if (isColored) R.drawable.wic_color_moon_cloud else R.drawable.wic_moon_cloud + WeatherIcons.NIGHT_FOG -> if (isColored) R.drawable.wic_color_moon_fog else R.drawable.wic_moon_fog + WeatherIcons.NIGHT_OVERCAST -> if (isColored) R.drawable.wic_color_moon_cloud else R.drawable.wic_moon_cloud + WeatherIcons.NIGHT_HAZE -> if (isColored) R.drawable.wic_color_moon_cloud_haze else R.drawable.wic_moon_cloud_haze + WeatherIcons.NIGHT_WINDY -> if (isColored) R.drawable.wic_color_wind else R.drawable.wic_wind + WeatherIcons.NIGHT_HOT -> if (isColored) R.drawable.wic_color_moon else R.drawable.wic_moon + WeatherIcons.NIGHT_LIGHT_WIND -> if (isColored) R.drawable.wic_color_wind else R.drawable.wic_wind + + WeatherIcons.CLOUD -> if (isColored) R.drawable.wic_color_cloud else R.drawable.wic_cloud + WeatherIcons.CLOUDY -> if (isColored) R.drawable.wic_color_clouds else R.drawable.wic_clouds + WeatherIcons.CLOUDY_GUSTS -> if (isColored) R.drawable.wic_color_cloud_wind else R.drawable.wic_cloud_wind + WeatherIcons.CLOUDY_WINDY -> if (isColored) R.drawable.wic_color_cloud_wind else R.drawable.wic_cloud_wind + WeatherIcons.FOG -> if (isColored) R.drawable.wic_color_fog else R.drawable.wic_fog + WeatherIcons.HAIL -> if (isColored) R.drawable.wic_color_cloud_hail else R.drawable.wic_cloud_hail + WeatherIcons.HAZE -> if (isColored) R.drawable.wic_color_cloud_haze else R.drawable.wic_cloud_haze + WeatherIcons.HOT -> if (isColored) R.drawable.wic_color_thermometer_heat else R.drawable.wic_thermometer_heat + WeatherIcons.LIGHT_WIND -> if (isColored) R.drawable.wic_color_wind else R.drawable.wic_wind + WeatherIcons.RAIN -> if (isColored) R.drawable.wic_color_cloud_rain else R.drawable.wic_cloud_rain + WeatherIcons.RAIN_MIX -> if (isColored) R.drawable.wic_color_cloud_sleet else R.drawable.wic_cloud_sleet + WeatherIcons.RAIN_WIND -> if (isColored) R.drawable.wic_color_cloud_rain else R.drawable.wic_cloud_rain + WeatherIcons.OVERCAST -> if (isColored) R.drawable.wic_color_clouds_alt else R.drawable.wic_clouds_alt + WeatherIcons.SHOWERS -> if (isColored) R.drawable.wic_color_cloud_rain else R.drawable.wic_cloud_rain + WeatherIcons.SLEET -> if (isColored) R.drawable.wic_color_cloud_sleet else R.drawable.wic_cloud_sleet + WeatherIcons.SLEET_STORM -> if (isColored) R.drawable.wic_color_cloud_sleet else R.drawable.wic_cloud_sleet + WeatherIcons.SNOW -> if (isColored) R.drawable.wic_color_cloud_snow_alt else R.drawable.wic_cloud_snow_alt + WeatherIcons.SNOW_THUNDERSTORM -> if (isColored) R.drawable.wic_color_cloud_snow else R.drawable.wic_cloud_snow + WeatherIcons.SPRINKLE -> if (isColored) R.drawable.wic_color_cloud_rain_alt else R.drawable.wic_cloud_rain_alt + WeatherIcons.STORM_SHOWERS -> if (isColored) R.drawable.wic_color_lightning else R.drawable.wic_lightning + WeatherIcons.THUNDERSTORM -> if (isColored) R.drawable.wic_color_lightning else R.drawable.wic_lightning + WeatherIcons.SNOW_WIND -> if (isColored) R.drawable.wic_color_cloud_snow else R.drawable.wic_cloud_snow + WeatherIcons.SMOG -> if (isColored) R.drawable.wic_color_cloud_smog else R.drawable.wic_cloud_smog WeatherIcons.SMOKE -> R.drawable.wi_smoke - WeatherIcons.LIGHTNING -> R.drawable.wic_lightning + WeatherIcons.LIGHTNING -> if (isColored) R.drawable.wic_color_lightning else R.drawable.wic_lightning WeatherIcons.DUST -> R.drawable.wi_dust - WeatherIcons.SNOWFLAKE_COLD -> R.drawable.wic_snowflake - WeatherIcons.WINDY -> R.drawable.wic_wind - WeatherIcons.STRONG_WIND -> R.drawable.wic_wind_high - WeatherIcons.SANDSTORM -> R.drawable.wi_sandstorm - WeatherIcons.HURRICANE -> R.drawable.wi_hurricane - WeatherIcons.TORNADO -> R.drawable.wic_tornado - WeatherIcons.FIRE -> R.drawable.wi_fire - WeatherIcons.FLOOD -> R.drawable.wi_flood + WeatherIcons.SNOWFLAKE_COLD -> if (isColored) R.drawable.wic_color_snowflake else R.drawable.wic_snowflake + WeatherIcons.WINDY -> if (isColored) R.drawable.wic_color_wind else R.drawable.wic_wind + WeatherIcons.STRONG_WIND -> if (isColored) R.drawable.wic_color_wind_high else R.drawable.wic_wind_high + WeatherIcons.SANDSTORM -> if (isColored) R.drawable.wic_color_sandstorm else R.drawable.wic_sandstorm + WeatherIcons.HURRICANE -> if (isColored) R.drawable.wic_color_hurricane else R.drawable.wic_hurricane + WeatherIcons.TORNADO -> if (isColored) R.drawable.wic_color_tornado else R.drawable.wic_tornado + WeatherIcons.FIRE -> if (isColored) R.drawable.wic_color_fire else R.drawable.wic_fire + WeatherIcons.FLOOD -> if (isColored) R.drawable.wic_color_flood else R.drawable.wic_flood WeatherIcons.VOLCANO -> R.drawable.wi_volcano - WeatherIcons.BAROMETER -> R.drawable.wic_barometer - WeatherIcons.HUMIDITY -> R.drawable.wic_raindrop - WeatherIcons.MOONRISE -> R.drawable.wi_moonrise - WeatherIcons.MOONSET -> R.drawable.wi_moonset - WeatherIcons.RAINDROP -> R.drawable.wi_raindrop + WeatherIcons.BAROMETER -> if (isColored) R.drawable.wic_color_barometer else R.drawable.wic_barometer + WeatherIcons.HUMIDITY -> if (isColored) R.drawable.wic_color_humidity else R.drawable.wic_humidity + WeatherIcons.MOONRISE -> if (isColored) R.drawable.wic_color_moonrise else R.drawable.wic_moonrise + WeatherIcons.MOONSET -> if (isColored) R.drawable.wic_color_moonset else R.drawable.wic_moonset + WeatherIcons.RAINDROP -> if (isColored) R.drawable.wic_color_raindrop else R.drawable.wic_raindrop WeatherIcons.RAINDROPS -> R.drawable.wi_raindrops - WeatherIcons.SUNRISE -> R.drawable.wic_sunrise - WeatherIcons.SUNSET -> R.drawable.wic_sunset - WeatherIcons.THERMOMETER -> R.drawable.wic_thermometer_medium - WeatherIcons.UMBRELLA -> R.drawable.wic_umbrella - WeatherIcons.WIND_DIRECTION -> R.drawable.wic_compass + WeatherIcons.SUNRISE -> if (isColored) R.drawable.wic_color_sunrise else R.drawable.wic_sunrise + WeatherIcons.SUNSET -> if (isColored) R.drawable.wic_color_sunset else R.drawable.wic_sunset + WeatherIcons.THERMOMETER -> if (isColored) R.drawable.wic_color_thermometer_medium else R.drawable.wic_thermometer_medium + WeatherIcons.UMBRELLA -> if (isColored) R.drawable.wic_color_umbrella else R.drawable.wic_umbrella + WeatherIcons.WIND_DIRECTION -> if (isColored) R.drawable.wic_color_compass else R.drawable.wic_compass WeatherIcons.DIRECTION_UP -> R.drawable.wi_direction_up WeatherIcons.DIRECTION_DOWN -> R.drawable.wi_direction_down @@ -144,26 +144,26 @@ class WeatherIconicProvider : WeatherIconProvider() { WeatherIcons.WIND_BEAUFORT_11 -> R.drawable.wi_wind_beaufort_11 WeatherIcons.WIND_BEAUFORT_12 -> R.drawable.wi_wind_beaufort_12 - WeatherIcons.MOON_NEW -> R.drawable.wic_moon_fullmoon - WeatherIcons.MOON_WAXING_CRESCENT_3 -> R.drawable.wic_moon_waxing_crescent - WeatherIcons.MOON_FIRST_QUARTER -> R.drawable.wic_moon_first_quarter - WeatherIcons.MOON_WAXING_GIBBOUS_3 -> R.drawable.wic_moon_waxing_gibbous - WeatherIcons.MOON_FULL -> R.drawable.wic_moon_newmoon - WeatherIcons.MOON_WANING_GIBBOUS_3 -> R.drawable.wic_moon_waning_gibbous - WeatherIcons.MOON_THIRD_QUARTER -> R.drawable.wic_moon_last_quarter - WeatherIcons.MOON_WANING_CRESCENT_3 -> R.drawable.wic_moon_waning_crescent - - WeatherIcons.MOON_ALT_NEW -> R.drawable.wic_moon_fullmoon - WeatherIcons.MOON_ALT_WAXING_CRESCENT_3 -> R.drawable.wic_moon_waxing_crescent - WeatherIcons.MOON_ALT_FIRST_QUARTER -> R.drawable.wic_moon_first_quarter - WeatherIcons.MOON_ALT_WAXING_GIBBOUS_3 -> R.drawable.wic_moon_waxing_gibbous - WeatherIcons.MOON_ALT_FULL -> R.drawable.wic_moon_newmoon - WeatherIcons.MOON_ALT_WANING_GIBBOUS_3 -> R.drawable.wic_moon_waning_gibbous - WeatherIcons.MOON_ALT_THIRD_QUARTER -> R.drawable.wic_moon_last_quarter - WeatherIcons.MOON_ALT_WANING_CRESCENT_3 -> R.drawable.wic_moon_waning_crescent - - WeatherIcons.FAHRENHEIT -> R.drawable.wic_fahrenheit - WeatherIcons.CELSIUS -> R.drawable.wic_celsius + WeatherIcons.MOON_NEW -> if (isColored) R.drawable.wic_color_moon_fullmoon else R.drawable.wic_moon_fullmoon + WeatherIcons.MOON_WAXING_CRESCENT_3 -> if (isColored) R.drawable.wic_color_moon_waxing_crescent else R.drawable.wic_moon_waxing_crescent + WeatherIcons.MOON_FIRST_QUARTER -> if (isColored) R.drawable.wic_color_moon_first_quarter else R.drawable.wic_moon_first_quarter + WeatherIcons.MOON_WAXING_GIBBOUS_3 -> if (isColored) R.drawable.wic_color_moon_waxing_gibbous else R.drawable.wic_moon_waxing_gibbous + WeatherIcons.MOON_FULL -> if (isColored) R.drawable.wic_color_moon_newmoon else R.drawable.wic_moon_newmoon + WeatherIcons.MOON_WANING_GIBBOUS_3 -> if (isColored) R.drawable.wic_color_moon_waning_gibbous else R.drawable.wic_moon_waning_gibbous + WeatherIcons.MOON_THIRD_QUARTER -> if (isColored) R.drawable.wic_color_moon_last_quarter else R.drawable.wic_moon_last_quarter + WeatherIcons.MOON_WANING_CRESCENT_3 -> if (isColored) R.drawable.wic_color_moon_waning_crescent else R.drawable.wic_moon_waning_crescent + + WeatherIcons.MOON_ALT_NEW -> if (isColored) R.drawable.wic_color_moon_fullmoon else R.drawable.wic_moon_fullmoon + WeatherIcons.MOON_ALT_WAXING_CRESCENT_3 -> if (isColored) R.drawable.wic_color_moon_waxing_crescent else R.drawable.wic_moon_waxing_crescent + WeatherIcons.MOON_ALT_FIRST_QUARTER -> if (isColored) R.drawable.wic_color_moon_first_quarter else R.drawable.wic_moon_first_quarter + WeatherIcons.MOON_ALT_WAXING_GIBBOUS_3 -> if (isColored) R.drawable.wic_color_moon_waxing_gibbous else R.drawable.wic_moon_waxing_gibbous + WeatherIcons.MOON_ALT_FULL -> if (isColored) R.drawable.wic_color_moon_newmoon else R.drawable.wic_moon_newmoon + WeatherIcons.MOON_ALT_WANING_GIBBOUS_3 -> if (isColored) R.drawable.wic_color_moon_waning_gibbous else R.drawable.wic_moon_waning_gibbous + WeatherIcons.MOON_ALT_THIRD_QUARTER -> if (isColored) R.drawable.wic_color_moon_last_quarter else R.drawable.wic_moon_last_quarter + WeatherIcons.MOON_ALT_WANING_CRESCENT_3 -> if (isColored) R.drawable.wic_color_moon_waning_crescent else R.drawable.wic_moon_waning_crescent + + WeatherIcons.FAHRENHEIT -> if (isColored) R.drawable.wic_color_fahrenheit else R.drawable.wic_fahrenheit + WeatherIcons.CELSIUS -> if (isColored) R.drawable.wic_color_celsius else R.drawable.wic_celsius WeatherIcons.UV_INDEX, WeatherIcons.UV_INDEX_1, @@ -176,20 +176,20 @@ class WeatherIconicProvider : WeatherIconProvider() { WeatherIcons.UV_INDEX_8, WeatherIcons.UV_INDEX_9, WeatherIcons.UV_INDEX_10, - WeatherIcons.UV_INDEX_11 -> R.drawable.wic_sun + WeatherIcons.UV_INDEX_11 -> if (isColored) R.drawable.wic_color_sun else R.drawable.wic_sun WeatherIcons.TREE_POLLEN -> R.drawable.ic_outline_tree WeatherIcons.GRASS_POLLEN -> R.drawable.ic_baseline_grass - WeatherIcons.RAGWEED_POLLEN -> R.drawable.ic_ragweed_pollen + WeatherIcons.RAGWEED_POLLEN -> if (isColored) R.drawable.wic_color_pollen else R.drawable.wic_pollen - WeatherIcons.NA -> R.drawable.wui_unknown + WeatherIcons.NA -> if (isColored) R.drawable.wic_color_na else R.drawable.wic_na - else -> -1 + else -> 0 } - if (weatherIcon == -1) { + if (weatherIcon == 0) { // Not Available - weatherIcon = R.drawable.wui_unknown + weatherIcon = if (isColored) R.drawable.wic_color_na else R.drawable.wic_na } return weatherIcon diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt index a0d2c15f..3e1f8d5d 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt @@ -13,6 +13,7 @@ class WeatherIconsManager internal constructor() : WeatherIconsProvider { defaultIconMap.addIconProvider(WeatherIconsEFProvider()) defaultIconMap.addIconProvider(WUndergroundIconsProvider()) defaultIconMap.addIconProvider(WeatherIconicProvider()) + defaultIconMap.addIconProvider(WeatherIconicProvider(isColored = true)) defaultIconMap.addIconProvider(JDWIIconsProvider()) defaultIconMap.addIconProvider(GoogleWeatherIconsProvider()) defaultIconProviders = Collections.unmodifiableMap(defaultIconMap) @@ -96,7 +97,8 @@ class WeatherIconsManager internal constructor() : WeatherIconsProvider { "pixeden-icons_set-weather" -> true "meteocons-basmilius", - "wci_sliu_iconfinder" -> false + "wci_sliu_iconfinder", + "w-iconic-jackd248-multicolor" -> false else -> true } diff --git a/shared_resources/src/main/res/drawable/wic_barometer.xml b/shared_resources/src/main/res/drawable/wic_barometer.xml index 557db641..e99c343d 100644 --- a/shared_resources/src/main/res/drawable/wic_barometer.xml +++ b/shared_resources/src/main/res/drawable/wic_barometer.xml @@ -1,15 +1,29 @@ + + + + diff --git a/shared_resources/src/main/res/drawable/wic_celsius.xml b/shared_resources/src/main/res/drawable/wic_celsius.xml index 79a2e4cf..42532df8 100644 --- a/shared_resources/src/main/res/drawable/wic_celsius.xml +++ b/shared_resources/src/main/res/drawable/wic_celsius.xml @@ -1,18 +1,29 @@ + + + diff --git a/shared_resources/src/main/res/drawable/wic_cloud.xml b/shared_resources/src/main/res/drawable/wic_cloud.xml index 45eaa251..bfabbba0 100644 --- a/shared_resources/src/main/res/drawable/wic_cloud.xml +++ b/shared_resources/src/main/res/drawable/wic_cloud.xml @@ -1,15 +1,18 @@ + diff --git a/shared_resources/src/main/res/drawable/wic_cloud_fog.xml b/shared_resources/src/main/res/drawable/wic_cloud_fog.xml index 34e83a24..c5f95ef3 100644 --- a/shared_resources/src/main/res/drawable/wic_cloud_fog.xml +++ b/shared_resources/src/main/res/drawable/wic_cloud_fog.xml @@ -1,24 +1,29 @@ + - - + + diff --git a/shared_resources/src/main/res/drawable/wic_cloud_hail.xml b/shared_resources/src/main/res/drawable/wic_cloud_hail.xml new file mode 100644 index 00000000..23d13829 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_cloud_hail.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_cloud_haze.xml b/shared_resources/src/main/res/drawable/wic_cloud_haze.xml new file mode 100644 index 00000000..da8db9f7 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_cloud_haze.xml @@ -0,0 +1,27 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_cloud_rain.xml b/shared_resources/src/main/res/drawable/wic_cloud_rain.xml index d14e8860..30c53c06 100644 --- a/shared_resources/src/main/res/drawable/wic_cloud_rain.xml +++ b/shared_resources/src/main/res/drawable/wic_cloud_rain.xml @@ -1,25 +1,29 @@ + + android:scaleY="1.5"> - - + + diff --git a/shared_resources/src/main/res/drawable/wic_cloud_rain_alt.xml b/shared_resources/src/main/res/drawable/wic_cloud_rain_alt.xml new file mode 100644 index 00000000..6bc33dd8 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_cloud_rain_alt.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_cloud_rain_single.xml b/shared_resources/src/main/res/drawable/wic_cloud_rain_single.xml deleted file mode 100644 index 912bbbf3..00000000 --- a/shared_resources/src/main/res/drawable/wic_cloud_rain_single.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/shared_resources/src/main/res/drawable/wic_cloud_sleet.xml b/shared_resources/src/main/res/drawable/wic_cloud_sleet.xml new file mode 100644 index 00000000..8e7d706a --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_cloud_sleet.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_cloud_smog.xml b/shared_resources/src/main/res/drawable/wic_cloud_smog.xml new file mode 100644 index 00000000..124cba82 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_cloud_smog.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_cloud_snow.xml b/shared_resources/src/main/res/drawable/wic_cloud_snow.xml index ec7af9ca..8c2d316b 100644 --- a/shared_resources/src/main/res/drawable/wic_cloud_snow.xml +++ b/shared_resources/src/main/res/drawable/wic_cloud_snow.xml @@ -1,37 +1,29 @@ + + android:scaleY="1.5"> - - - - - - + + diff --git a/shared_resources/src/main/res/drawable/wic_cloud_snow_alt.xml b/shared_resources/src/main/res/drawable/wic_cloud_snow_alt.xml new file mode 100644 index 00000000..93468f36 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_cloud_snow_alt.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_cloud_wind.xml b/shared_resources/src/main/res/drawable/wic_cloud_wind.xml index d8983e2a..c23fa295 100644 --- a/shared_resources/src/main/res/drawable/wic_cloud_wind.xml +++ b/shared_resources/src/main/res/drawable/wic_cloud_wind.xml @@ -1,23 +1,29 @@ + + android:scaleY="1.25"> - + + diff --git a/shared_resources/src/main/res/drawable/wic_clouds.xml b/shared_resources/src/main/res/drawable/wic_clouds.xml index 4954e829..60aca659 100644 --- a/shared_resources/src/main/res/drawable/wic_clouds.xml +++ b/shared_resources/src/main/res/drawable/wic_clouds.xml @@ -1,16 +1,29 @@ + + android:scaleY="1.25"> + + + diff --git a/shared_resources/src/main/res/drawable/wic_clouds_alt.xml b/shared_resources/src/main/res/drawable/wic_clouds_alt.xml new file mode 100644 index 00000000..5884c23f --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_clouds_alt.xml @@ -0,0 +1,27 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_barometer.xml b/shared_resources/src/main/res/drawable/wic_color_barometer.xml new file mode 100644 index 00000000..daa799df --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_barometer.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_celsius.xml b/shared_resources/src/main/res/drawable/wic_color_celsius.xml new file mode 100644 index 00000000..247c9f1b --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_celsius.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_cloud.xml b/shared_resources/src/main/res/drawable/wic_color_cloud.xml new file mode 100644 index 00000000..bfabbba0 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_cloud.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_cloud_fog.xml b/shared_resources/src/main/res/drawable/wic_color_cloud_fog.xml new file mode 100644 index 00000000..708699ae --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_cloud_fog.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_cloud_hail.xml b/shared_resources/src/main/res/drawable/wic_color_cloud_hail.xml new file mode 100644 index 00000000..4164edbe --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_cloud_hail.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_cloud_haze.xml b/shared_resources/src/main/res/drawable/wic_color_cloud_haze.xml new file mode 100644 index 00000000..638a150f --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_cloud_haze.xml @@ -0,0 +1,27 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_cloud_rain.xml b/shared_resources/src/main/res/drawable/wic_color_cloud_rain.xml new file mode 100644 index 00000000..065dfd85 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_cloud_rain.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_cloud_rain_alt.xml b/shared_resources/src/main/res/drawable/wic_color_cloud_rain_alt.xml new file mode 100644 index 00000000..be9852bb --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_cloud_rain_alt.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_cloud_sleet.xml b/shared_resources/src/main/res/drawable/wic_color_cloud_sleet.xml new file mode 100644 index 00000000..8a663fff --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_cloud_sleet.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_cloud_smog.xml b/shared_resources/src/main/res/drawable/wic_color_cloud_smog.xml new file mode 100644 index 00000000..d05801a3 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_cloud_smog.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_cloud_snow.xml b/shared_resources/src/main/res/drawable/wic_color_cloud_snow.xml new file mode 100644 index 00000000..0f7389c0 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_cloud_snow.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_cloud_snow_alt.xml b/shared_resources/src/main/res/drawable/wic_color_cloud_snow_alt.xml new file mode 100644 index 00000000..4961acfb --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_cloud_snow_alt.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_cloud_wind.xml b/shared_resources/src/main/res/drawable/wic_color_cloud_wind.xml new file mode 100644 index 00000000..6aa9cdac --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_cloud_wind.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_clouds.xml b/shared_resources/src/main/res/drawable/wic_color_clouds.xml new file mode 100644 index 00000000..6af5ec32 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_clouds.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_clouds_alt.xml b/shared_resources/src/main/res/drawable/wic_color_clouds_alt.xml new file mode 100644 index 00000000..5884c23f --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_clouds_alt.xml @@ -0,0 +1,27 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_compass.xml b/shared_resources/src/main/res/drawable/wic_color_compass.xml new file mode 100644 index 00000000..fc779ba4 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_compass.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_fahrenheit.xml b/shared_resources/src/main/res/drawable/wic_color_fahrenheit.xml new file mode 100644 index 00000000..a6b730b8 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_fahrenheit.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_fire.xml b/shared_resources/src/main/res/drawable/wic_color_fire.xml new file mode 100644 index 00000000..8e159a70 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_fire.xml @@ -0,0 +1,25 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_flood.xml b/shared_resources/src/main/res/drawable/wic_color_flood.xml new file mode 100644 index 00000000..4b2685b6 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_flood.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_fog.xml b/shared_resources/src/main/res/drawable/wic_color_fog.xml new file mode 100644 index 00000000..c83aa55b --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_fog.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_humidity.xml b/shared_resources/src/main/res/drawable/wic_color_humidity.xml new file mode 100644 index 00000000..9d4dea9d --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_humidity.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_hurricane.xml b/shared_resources/src/main/res/drawable/wic_color_hurricane.xml new file mode 100644 index 00000000..6a2be557 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_hurricane.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_info.xml b/shared_resources/src/main/res/drawable/wic_color_info.xml new file mode 100644 index 00000000..40def648 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_info.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_lightning.xml b/shared_resources/src/main/res/drawable/wic_color_lightning.xml new file mode 100644 index 00000000..0ba57521 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_lightning.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon.xml b/shared_resources/src/main/res/drawable/wic_color_moon.xml new file mode 100644 index 00000000..a92613f0 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_cloud.xml b/shared_resources/src/main/res/drawable/wic_color_moon_cloud.xml new file mode 100644 index 00000000..3d1db01f --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_cloud.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_cloud_fog.xml b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_fog.xml new file mode 100644 index 00000000..7caf0bab --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_fog.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_cloud_hail.xml b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_hail.xml new file mode 100644 index 00000000..ff0ce367 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_hail.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_cloud_haze.xml b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_haze.xml new file mode 100644 index 00000000..507266cc --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_haze.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_cloud_lightning.xml b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_lightning.xml new file mode 100644 index 00000000..4dc76a6e --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_lightning.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_cloud_rain.xml b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_rain.xml new file mode 100644 index 00000000..f0c3f172 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_rain.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_cloud_rain_alt.xml b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_rain_alt.xml new file mode 100644 index 00000000..0c28192a --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_rain_alt.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_cloud_sleet.xml b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_sleet.xml new file mode 100644 index 00000000..3f2334fc --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_sleet.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_cloud_snow.xml b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_snow.xml new file mode 100644 index 00000000..524985b4 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_snow.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_cloud_snow_alt.xml b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_snow_alt.xml new file mode 100644 index 00000000..808bbf75 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_snow_alt.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_cloud_wind.xml b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_wind.xml new file mode 100644 index 00000000..e7ea870c --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_cloud_wind.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_first_quarter.xml b/shared_resources/src/main/res/drawable/wic_color_moon_first_quarter.xml new file mode 100644 index 00000000..721bb5dd --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_first_quarter.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_fog.xml b/shared_resources/src/main/res/drawable/wic_color_moon_fog.xml new file mode 100644 index 00000000..58db6f8b --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_fog.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_fullmoon.xml b/shared_resources/src/main/res/drawable/wic_color_moon_fullmoon.xml new file mode 100644 index 00000000..d51ac69b --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_fullmoon.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_last_quarter.xml b/shared_resources/src/main/res/drawable/wic_color_moon_last_quarter.xml new file mode 100644 index 00000000..0d14d322 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_last_quarter.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_newmoon.xml b/shared_resources/src/main/res/drawable/wic_color_moon_newmoon.xml new file mode 100644 index 00000000..01b51814 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_newmoon.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_waning_crescent.xml b/shared_resources/src/main/res/drawable/wic_color_moon_waning_crescent.xml new file mode 100644 index 00000000..911b7461 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_waning_crescent.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_waning_gibbous.xml b/shared_resources/src/main/res/drawable/wic_color_moon_waning_gibbous.xml new file mode 100644 index 00000000..ac8f6a11 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_waning_gibbous.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_waxing_crescent.xml b/shared_resources/src/main/res/drawable/wic_color_moon_waxing_crescent.xml new file mode 100644 index 00000000..4753d342 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_waxing_crescent.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moon_waxing_gibbous.xml b/shared_resources/src/main/res/drawable/wic_color_moon_waxing_gibbous.xml new file mode 100644 index 00000000..a22141b1 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moon_waxing_gibbous.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moonrise.xml b/shared_resources/src/main/res/drawable/wic_color_moonrise.xml new file mode 100644 index 00000000..5c78f30b --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moonrise.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_moonset.xml b/shared_resources/src/main/res/drawable/wic_color_moonset.xml new file mode 100644 index 00000000..876b2b03 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_moonset.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_na.xml b/shared_resources/src/main/res/drawable/wic_color_na.xml new file mode 100644 index 00000000..a6aa69f8 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_na.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_pollen.xml b/shared_resources/src/main/res/drawable/wic_color_pollen.xml new file mode 100644 index 00000000..5b518290 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_pollen.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_raindrop.xml b/shared_resources/src/main/res/drawable/wic_color_raindrop.xml new file mode 100644 index 00000000..85d37b54 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_raindrop.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sandstorm.xml b/shared_resources/src/main/res/drawable/wic_color_sandstorm.xml new file mode 100644 index 00000000..8920e60a --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sandstorm.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_snowflake.xml b/shared_resources/src/main/res/drawable/wic_color_snowflake.xml new file mode 100644 index 00000000..24714bc9 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_snowflake.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sun.xml b/shared_resources/src/main/res/drawable/wic_color_sun.xml new file mode 100644 index 00000000..023e3c82 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sun.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sun_cloud.xml b/shared_resources/src/main/res/drawable/wic_color_sun_cloud.xml new file mode 100644 index 00000000..bc9c9a92 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sun_cloud.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sun_cloud_fog.xml b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_fog.xml new file mode 100644 index 00000000..d0807565 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_fog.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sun_cloud_hail.xml b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_hail.xml new file mode 100644 index 00000000..4d360e7c --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_hail.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sun_cloud_haze.xml b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_haze.xml new file mode 100644 index 00000000..52db66a0 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_haze.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sun_cloud_lightning.xml b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_lightning.xml new file mode 100644 index 00000000..1f5212a4 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_lightning.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sun_cloud_rain.xml b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_rain.xml new file mode 100644 index 00000000..0da59b15 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_rain.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sun_cloud_rain_alt.xml b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_rain_alt.xml new file mode 100644 index 00000000..d3e681f1 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_rain_alt.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sun_cloud_sleet.xml b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_sleet.xml new file mode 100644 index 00000000..485ac5c1 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_sleet.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sun_cloud_snow.xml b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_snow.xml new file mode 100644 index 00000000..9a3f6b1a --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_snow.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sun_cloud_snow_alt.xml b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_snow_alt.xml new file mode 100644 index 00000000..54c019e7 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_snow_alt.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sun_cloud_wind.xml b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_wind.xml new file mode 100644 index 00000000..61ce5e84 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sun_cloud_wind.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sun_fog.xml b/shared_resources/src/main/res/drawable/wic_color_sun_fog.xml new file mode 100644 index 00000000..39348b19 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sun_fog.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sunrise.xml b/shared_resources/src/main/res/drawable/wic_color_sunrise.xml new file mode 100644 index 00000000..8f88ed90 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sunrise.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_sunset.xml b/shared_resources/src/main/res/drawable/wic_color_sunset.xml new file mode 100644 index 00000000..acebe7ca --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_sunset.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_thermometer_cold.xml b/shared_resources/src/main/res/drawable/wic_color_thermometer_cold.xml new file mode 100644 index 00000000..1df70911 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_thermometer_cold.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_thermometer_freeze.xml b/shared_resources/src/main/res/drawable/wic_color_thermometer_freeze.xml new file mode 100644 index 00000000..67677eb9 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_thermometer_freeze.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_thermometer_heat.xml b/shared_resources/src/main/res/drawable/wic_color_thermometer_heat.xml new file mode 100644 index 00000000..01fc5a9d --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_thermometer_heat.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_thermometer_hot.xml b/shared_resources/src/main/res/drawable/wic_color_thermometer_hot.xml new file mode 100644 index 00000000..c9bb701a --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_thermometer_hot.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_thermometer_medium.xml b/shared_resources/src/main/res/drawable/wic_color_thermometer_medium.xml new file mode 100644 index 00000000..f3e9074e --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_thermometer_medium.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_tornado.xml b/shared_resources/src/main/res/drawable/wic_color_tornado.xml new file mode 100644 index 00000000..68501b9a --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_tornado.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_umbrella.xml b/shared_resources/src/main/res/drawable/wic_color_umbrella.xml new file mode 100644 index 00000000..92de210b --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_umbrella.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_wind.xml b/shared_resources/src/main/res/drawable/wic_color_wind.xml new file mode 100644 index 00000000..91e80fed --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_wind.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_color_wind_high.xml b/shared_resources/src/main/res/drawable/wic_color_wind_high.xml new file mode 100644 index 00000000..19c41713 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_color_wind_high.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_compass.xml b/shared_resources/src/main/res/drawable/wic_compass.xml index b757db6c..d57bd14b 100644 --- a/shared_resources/src/main/res/drawable/wic_compass.xml +++ b/shared_resources/src/main/res/drawable/wic_compass.xml @@ -1,19 +1,29 @@ + + android:scaleY="1.5"> + + diff --git a/shared_resources/src/main/res/drawable/wic_fahrenheit.xml b/shared_resources/src/main/res/drawable/wic_fahrenheit.xml index b8948458..511abc76 100644 --- a/shared_resources/src/main/res/drawable/wic_fahrenheit.xml +++ b/shared_resources/src/main/res/drawable/wic_fahrenheit.xml @@ -1,19 +1,29 @@ + + android:scaleY="1.5"> + + diff --git a/shared_resources/src/main/res/drawable/wic_fire.xml b/shared_resources/src/main/res/drawable/wic_fire.xml new file mode 100644 index 00000000..c5ee581d --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_fire.xml @@ -0,0 +1,25 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_flood.xml b/shared_resources/src/main/res/drawable/wic_flood.xml new file mode 100644 index 00000000..784bb59a --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_flood.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_fog.xml b/shared_resources/src/main/res/drawable/wic_fog.xml index 32db1d8a..050c49ca 100644 --- a/shared_resources/src/main/res/drawable/wic_fog.xml +++ b/shared_resources/src/main/res/drawable/wic_fog.xml @@ -1,28 +1,29 @@ + + android:scaleY="1.5"> - - - + + diff --git a/shared_resources/src/main/res/drawable/wic_hail.xml b/shared_resources/src/main/res/drawable/wic_hail.xml deleted file mode 100644 index 5df922df..00000000 --- a/shared_resources/src/main/res/drawable/wic_hail.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - diff --git a/shared_resources/src/main/res/drawable/wic_humidity.xml b/shared_resources/src/main/res/drawable/wic_humidity.xml new file mode 100644 index 00000000..88e28a7e --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_humidity.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_hurricane.xml b/shared_resources/src/main/res/drawable/wic_hurricane.xml new file mode 100644 index 00000000..471660ae --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_hurricane.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_info.xml b/shared_resources/src/main/res/drawable/wic_info.xml new file mode 100644 index 00000000..1b3ac07d --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_info.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_lightning.xml b/shared_resources/src/main/res/drawable/wic_lightning.xml index 7d9dee98..8865e0e4 100644 --- a/shared_resources/src/main/res/drawable/wic_lightning.xml +++ b/shared_resources/src/main/res/drawable/wic_lightning.xml @@ -1,19 +1,29 @@ + + android:scaleY="1.5"> + + diff --git a/shared_resources/src/main/res/drawable/wic_moon.xml b/shared_resources/src/main/res/drawable/wic_moon.xml index 67b321e4..a92613f0 100644 --- a/shared_resources/src/main/res/drawable/wic_moon.xml +++ b/shared_resources/src/main/res/drawable/wic_moon.xml @@ -1,16 +1,18 @@ + + android:scaleY="1.75"> diff --git a/shared_resources/src/main/res/drawable/wic_moon_cloud.xml b/shared_resources/src/main/res/drawable/wic_moon_cloud.xml index b3c3f6cf..1dfc1ecc 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_cloud.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_cloud.xml @@ -1,16 +1,29 @@ + + android:scaleY="1.5"> + + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_cloud_fog.xml b/shared_resources/src/main/res/drawable/wic_moon_cloud_fog.xml new file mode 100644 index 00000000..f7819b94 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_moon_cloud_fog.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_cloud_hail.xml b/shared_resources/src/main/res/drawable/wic_moon_cloud_hail.xml new file mode 100644 index 00000000..bf929e51 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_moon_cloud_hail.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_cloud_haze.xml b/shared_resources/src/main/res/drawable/wic_moon_cloud_haze.xml new file mode 100644 index 00000000..c8a35a73 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_moon_cloud_haze.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_cloud_lightning.xml b/shared_resources/src/main/res/drawable/wic_moon_cloud_lightning.xml index c2b52528..839309a8 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_cloud_lightning.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_cloud_lightning.xml @@ -1,19 +1,29 @@ + + android:scaleY="1.5"> + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_cloud_rain.xml b/shared_resources/src/main/res/drawable/wic_moon_cloud_rain.xml index 136a7201..1d476722 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_cloud_rain.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_cloud_rain.xml @@ -1,26 +1,29 @@ + + android:scaleY="1.5"> - - + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_cloud_rain_alt.xml b/shared_resources/src/main/res/drawable/wic_moon_cloud_rain_alt.xml new file mode 100644 index 00000000..2eaa6922 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_moon_cloud_rain_alt.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_cloud_sleet.xml b/shared_resources/src/main/res/drawable/wic_moon_cloud_sleet.xml new file mode 100644 index 00000000..3223928e --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_moon_cloud_sleet.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_cloud_snow.xml b/shared_resources/src/main/res/drawable/wic_moon_cloud_snow.xml index 96f9731d..5bba76d2 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_cloud_snow.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_cloud_snow.xml @@ -1,37 +1,29 @@ + + android:scaleY="1.5"> - - - - - - + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_cloud_snow_alt.xml b/shared_resources/src/main/res/drawable/wic_moon_cloud_snow_alt.xml new file mode 100644 index 00000000..eb6d6654 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_moon_cloud_snow_alt.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_cloud_wind.xml b/shared_resources/src/main/res/drawable/wic_moon_cloud_wind.xml index ddd3c751..ff144327 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_cloud_wind.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_cloud_wind.xml @@ -1,22 +1,29 @@ + + android:scaleY="1.25"> - + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_first_quarter.xml b/shared_resources/src/main/res/drawable/wic_moon_first_quarter.xml index 00e688e0..01c5a2b8 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_first_quarter.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_first_quarter.xml @@ -1,16 +1,29 @@ + + android:scaleY="1.5"> + + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_fog.xml b/shared_resources/src/main/res/drawable/wic_moon_fog.xml index a017e834..9da39047 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_fog.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_fog.xml @@ -1,17 +1,29 @@ + + android:scaleY="1.5"> + + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_fullmoon.xml b/shared_resources/src/main/res/drawable/wic_moon_fullmoon.xml index 71576d70..d51ac69b 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_fullmoon.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_fullmoon.xml @@ -1,16 +1,18 @@ + + android:scaleY="1.5"> diff --git a/shared_resources/src/main/res/drawable/wic_moon_last_quarter.xml b/shared_resources/src/main/res/drawable/wic_moon_last_quarter.xml index d00265ae..4717c68b 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_last_quarter.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_last_quarter.xml @@ -1,17 +1,29 @@ + + android:scaleY="1.5"> + + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_newmoon.xml b/shared_resources/src/main/res/drawable/wic_moon_newmoon.xml index 98cd3501..01b51814 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_newmoon.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_newmoon.xml @@ -1,17 +1,18 @@ + + android:scaleY="1.5"> diff --git a/shared_resources/src/main/res/drawable/wic_moon_waning_crescent.xml b/shared_resources/src/main/res/drawable/wic_moon_waning_crescent.xml index 162179bd..3a1baa29 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_waning_crescent.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_waning_crescent.xml @@ -1,16 +1,29 @@ + + android:scaleY="1.5"> + + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_waning_gibbous.xml b/shared_resources/src/main/res/drawable/wic_moon_waning_gibbous.xml index 5dd274e7..ab8fc2ed 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_waning_gibbous.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_waning_gibbous.xml @@ -1,16 +1,29 @@ + + android:scaleY="1.5"> + + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_waxing_crescent.xml b/shared_resources/src/main/res/drawable/wic_moon_waxing_crescent.xml index 16bb9f32..e6970102 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_waxing_crescent.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_waxing_crescent.xml @@ -1,17 +1,29 @@ + + android:scaleY="1.5"> + + + diff --git a/shared_resources/src/main/res/drawable/wic_moon_waxing_gibbous.xml b/shared_resources/src/main/res/drawable/wic_moon_waxing_gibbous.xml index 077ca7cc..9fc4b836 100644 --- a/shared_resources/src/main/res/drawable/wic_moon_waxing_gibbous.xml +++ b/shared_resources/src/main/res/drawable/wic_moon_waxing_gibbous.xml @@ -1,17 +1,29 @@ + + android:scaleY="1.5"> + + + diff --git a/shared_resources/src/main/res/drawable/wic_moonrise.xml b/shared_resources/src/main/res/drawable/wic_moonrise.xml new file mode 100644 index 00000000..0df7a4d6 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_moonrise.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_moonset.xml b/shared_resources/src/main/res/drawable/wic_moonset.xml new file mode 100644 index 00000000..cd19a912 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_moonset.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_na.xml b/shared_resources/src/main/res/drawable/wic_na.xml new file mode 100644 index 00000000..f2326a93 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_na.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_pollen.xml b/shared_resources/src/main/res/drawable/wic_pollen.xml new file mode 100644 index 00000000..e49ac491 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_pollen.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_raindrop.xml b/shared_resources/src/main/res/drawable/wic_raindrop.xml index 57ffaa44..6871f931 100644 --- a/shared_resources/src/main/res/drawable/wic_raindrop.xml +++ b/shared_resources/src/main/res/drawable/wic_raindrop.xml @@ -1,19 +1,29 @@ + + android:scaleY="1.5"> + + diff --git a/shared_resources/src/main/res/drawable/wic_sandstorm.xml b/shared_resources/src/main/res/drawable/wic_sandstorm.xml new file mode 100644 index 00000000..9f8d023d --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_sandstorm.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_snowflake.xml b/shared_resources/src/main/res/drawable/wic_snowflake.xml index 24172f7e..24714bc9 100644 --- a/shared_resources/src/main/res/drawable/wic_snowflake.xml +++ b/shared_resources/src/main/res/drawable/wic_snowflake.xml @@ -1,17 +1,18 @@ + + android:scaleY="1.5"> diff --git a/shared_resources/src/main/res/drawable/wic_sun.xml b/shared_resources/src/main/res/drawable/wic_sun.xml index 22e2f6c4..023e3c82 100644 --- a/shared_resources/src/main/res/drawable/wic_sun.xml +++ b/shared_resources/src/main/res/drawable/wic_sun.xml @@ -1,40 +1,18 @@ + + android:scaleY="1.5"> - - - - - - - - diff --git a/shared_resources/src/main/res/drawable/wic_sun_cloud.xml b/shared_resources/src/main/res/drawable/wic_sun_cloud.xml index a9b0dc7e..e12e69e8 100644 --- a/shared_resources/src/main/res/drawable/wic_sun_cloud.xml +++ b/shared_resources/src/main/res/drawable/wic_sun_cloud.xml @@ -1,29 +1,29 @@ + + android:scaleY="1.4"> - - - + + diff --git a/shared_resources/src/main/res/drawable/wic_sun_cloud_fog.xml b/shared_resources/src/main/res/drawable/wic_sun_cloud_fog.xml new file mode 100644 index 00000000..28828868 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_sun_cloud_fog.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_sun_cloud_hail.xml b/shared_resources/src/main/res/drawable/wic_sun_cloud_hail.xml new file mode 100644 index 00000000..2f887584 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_sun_cloud_hail.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_sun_cloud_haze.xml b/shared_resources/src/main/res/drawable/wic_sun_cloud_haze.xml new file mode 100644 index 00000000..58dcb401 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_sun_cloud_haze.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_sun_cloud_lightning.xml b/shared_resources/src/main/res/drawable/wic_sun_cloud_lightning.xml index f88f1090..56cfbffb 100644 --- a/shared_resources/src/main/res/drawable/wic_sun_cloud_lightning.xml +++ b/shared_resources/src/main/res/drawable/wic_sun_cloud_lightning.xml @@ -1,32 +1,29 @@ + + android:scaleY="1.25"> - - - - + + diff --git a/shared_resources/src/main/res/drawable/wic_sun_cloud_rain.xml b/shared_resources/src/main/res/drawable/wic_sun_cloud_rain.xml index e282a897..39c9d3e7 100644 --- a/shared_resources/src/main/res/drawable/wic_sun_cloud_rain.xml +++ b/shared_resources/src/main/res/drawable/wic_sun_cloud_rain.xml @@ -1,38 +1,29 @@ + + android:scaleY="1.25"> - - - - - - + + diff --git a/shared_resources/src/main/res/drawable/wic_sun_cloud_rain_alt.xml b/shared_resources/src/main/res/drawable/wic_sun_cloud_rain_alt.xml new file mode 100644 index 00000000..30cd9586 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_sun_cloud_rain_alt.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_sun_cloud_sleet.xml b/shared_resources/src/main/res/drawable/wic_sun_cloud_sleet.xml new file mode 100644 index 00000000..a8715e89 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_sun_cloud_sleet.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_sun_cloud_snow.xml b/shared_resources/src/main/res/drawable/wic_sun_cloud_snow.xml index a608dd18..bce98b14 100644 --- a/shared_resources/src/main/res/drawable/wic_sun_cloud_snow.xml +++ b/shared_resources/src/main/res/drawable/wic_sun_cloud_snow.xml @@ -1,50 +1,29 @@ + + android:scaleY="1.25"> - - - - - - - - - - + + diff --git a/shared_resources/src/main/res/drawable/wic_sun_cloud_snow_alt.xml b/shared_resources/src/main/res/drawable/wic_sun_cloud_snow_alt.xml new file mode 100644 index 00000000..72991f64 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_sun_cloud_snow_alt.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_sun_cloud_wind.xml b/shared_resources/src/main/res/drawable/wic_sun_cloud_wind.xml index 10240803..a8608f69 100644 --- a/shared_resources/src/main/res/drawable/wic_sun_cloud_wind.xml +++ b/shared_resources/src/main/res/drawable/wic_sun_cloud_wind.xml @@ -1,35 +1,29 @@ + + android:scaleY="1.25"> - - - - - + + diff --git a/shared_resources/src/main/res/drawable/wic_sun_fog.xml b/shared_resources/src/main/res/drawable/wic_sun_fog.xml index 51610e1d..b215bec0 100644 --- a/shared_resources/src/main/res/drawable/wic_sun_fog.xml +++ b/shared_resources/src/main/res/drawable/wic_sun_fog.xml @@ -1,17 +1,29 @@ + - + android:scaleY="1.5"> + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_sunrise.xml b/shared_resources/src/main/res/drawable/wic_sunrise.xml index a707697e..7d8d7da2 100644 --- a/shared_resources/src/main/res/drawable/wic_sunrise.xml +++ b/shared_resources/src/main/res/drawable/wic_sunrise.xml @@ -1,29 +1,27 @@ + - - - - - + android:scaleX="1.5" + android:scaleY="1.5"> + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_sunset.xml b/shared_resources/src/main/res/drawable/wic_sunset.xml index 9df66909..5380fad1 100644 --- a/shared_resources/src/main/res/drawable/wic_sunset.xml +++ b/shared_resources/src/main/res/drawable/wic_sunset.xml @@ -1,29 +1,27 @@ + - - - - - + android:scaleX="1.5" + android:scaleY="1.5"> + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_thermometer_cold.xml b/shared_resources/src/main/res/drawable/wic_thermometer_cold.xml new file mode 100644 index 00000000..08b5daa4 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_thermometer_cold.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_thermometer_freeze.xml b/shared_resources/src/main/res/drawable/wic_thermometer_freeze.xml new file mode 100644 index 00000000..77cd6001 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_thermometer_freeze.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_thermometer_heat.xml b/shared_resources/src/main/res/drawable/wic_thermometer_heat.xml new file mode 100644 index 00000000..1f1a7789 --- /dev/null +++ b/shared_resources/src/main/res/drawable/wic_thermometer_heat.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_thermometer_hot.xml b/shared_resources/src/main/res/drawable/wic_thermometer_hot.xml index b8c97b3b..8f6a4add 100644 --- a/shared_resources/src/main/res/drawable/wic_thermometer_hot.xml +++ b/shared_resources/src/main/res/drawable/wic_thermometer_hot.xml @@ -1,20 +1,29 @@ + + android:scaleY="1.5"> + + diff --git a/shared_resources/src/main/res/drawable/wic_thermometer_medium.xml b/shared_resources/src/main/res/drawable/wic_thermometer_medium.xml index 939e495c..05329f61 100644 --- a/shared_resources/src/main/res/drawable/wic_thermometer_medium.xml +++ b/shared_resources/src/main/res/drawable/wic_thermometer_medium.xml @@ -1,20 +1,29 @@ + + android:scaleY="1.5"> + + diff --git a/shared_resources/src/main/res/drawable/wic_tornado.xml b/shared_resources/src/main/res/drawable/wic_tornado.xml index 74472f5f..a43a9bec 100644 --- a/shared_resources/src/main/res/drawable/wic_tornado.xml +++ b/shared_resources/src/main/res/drawable/wic_tornado.xml @@ -1,17 +1,27 @@ + - + android:scaleY="1.5"> + + + + + + diff --git a/shared_resources/src/main/res/drawable/wic_umbrella.xml b/shared_resources/src/main/res/drawable/wic_umbrella.xml index 996973ea..9f557abe 100644 --- a/shared_resources/src/main/res/drawable/wic_umbrella.xml +++ b/shared_resources/src/main/res/drawable/wic_umbrella.xml @@ -1,17 +1,29 @@ + + android:scaleY="1.5"> + + + diff --git a/shared_resources/src/main/res/drawable/wic_wind.xml b/shared_resources/src/main/res/drawable/wic_wind.xml index cb1db0a5..83d2f81f 100644 --- a/shared_resources/src/main/res/drawable/wic_wind.xml +++ b/shared_resources/src/main/res/drawable/wic_wind.xml @@ -1,23 +1,29 @@ + + android:scaleY="1.25"> - + + diff --git a/shared_resources/src/main/res/drawable/wic_wind_high.xml b/shared_resources/src/main/res/drawable/wic_wind_high.xml index 7e63464f..d1d29f1b 100644 --- a/shared_resources/src/main/res/drawable/wic_wind_high.xml +++ b/shared_resources/src/main/res/drawable/wic_wind_high.xml @@ -1,26 +1,29 @@ + + android:scaleY="1.25"> - - + + From 6ce53130813157567cfda2977bc854b9b55b1115 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Fri, 19 Jun 2026 20:12:56 -0400 Subject: [PATCH 38/67] app: update icon usage --- .../simpleweather/controls/DetailCard.java | 1 + .../WeatherNotificationBuilder.kt | 18 ++++++++++-------- .../layout-v31/weather_notification_layout.xml | 9 +++------ .../res/layout/weather_notification_layout.xml | 9 +++------ .../layout/weathernow_pollencountcontrol.xml | 14 ++++++++------ 5 files changed, 25 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/DetailCard.java b/app/src/main/java/com/thewizrd/simpleweather/controls/DetailCard.java index 971585e8..e8e5c4bb 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/DetailCard.java +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/DetailCard.java @@ -114,6 +114,7 @@ private void initialize(@NonNull Context context) { private void updateColors() { setBackgroundColor(ContextUtils.getAttrColor(getContext(), com.google.android.material.R.attr.colorSurfaceContainer)); ImageViewCompat.setImageTintList(binding.detailIcon, ColorStateList.valueOf(ContextUtils.getAttrColor(getContext(), androidx.appcompat.R.attr.colorPrimary))); + binding.detailIcon.setShowAsMonochrome(binding.detailIcon.getShowAsMonochrome()); bgDrawable.setStrokeColor(ContextCompat.getColorStateList(getContext(), com.google.android.material.R.color.m3_card_stroke_color)); } diff --git a/app/src/main/java/com/thewizrd/simpleweather/notifications/WeatherNotificationBuilder.kt b/app/src/main/java/com/thewizrd/simpleweather/notifications/WeatherNotificationBuilder.kt index c2512ff7..258a7105 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/notifications/WeatherNotificationBuilder.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/notifications/WeatherNotificationBuilder.kt @@ -13,12 +13,15 @@ import android.widget.RemoteViews import androidx.annotation.IdRes import androidx.annotation.LayoutRes import androidx.core.app.NotificationCompat -import com.thewizrd.common.controls.* +import com.thewizrd.common.controls.BaseForecastItemViewModel +import com.thewizrd.common.controls.ForecastItemViewModel +import com.thewizrd.common.controls.HourlyForecastItemViewModel +import com.thewizrd.common.controls.WeatherDetailsType +import com.thewizrd.common.controls.WeatherUiModel import com.thewizrd.common.utils.ImageUtils.bitmapFromDrawable import com.thewizrd.common.utils.ImageUtils.rotateBitmap import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons -import com.thewizrd.shared_resources.icons.WeatherIconsEFProvider import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.preferences.SettingsManager import com.thewizrd.shared_resources.sharedDeps @@ -47,7 +50,6 @@ object WeatherNotificationBuilder { viewModel: WeatherUiModel ): Notification { val wim = sharedDeps.weatherIconsManager - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) // Build update val updateViews = RemoteViews( @@ -118,7 +120,7 @@ object WeatherNotificationBuilder { if (chanceModel != null) { updateViews.setImageViewResource( R.id.weather_popicon, - wip.getWeatherIconResource(chanceModel.icon) + wim.getWeatherIconResource(chanceModel.icon) ) updateViews.setTextViewText(R.id.weather_pop, chanceModel.value) updateViews.setViewVisibility(R.id.weather_pop_layout, View.VISIBLE) @@ -134,7 +136,7 @@ object WeatherNotificationBuilder { } if (windModel != null) { - val windIconResId = wip.getWeatherIconResource(WeatherIcons.WIND_DIRECTION) + val windIconResId = wim.getWeatherIconResource(WeatherIcons.WIND_DIRECTION) if (windModel.iconRotation != 0) { bigUpdateViews.setImageViewBitmap( R.id.weather_windicon, @@ -157,7 +159,7 @@ object WeatherNotificationBuilder { if (humidityModel != null) { bigUpdateViews.setImageViewResource( R.id.humidity_icon, - wip.getWeatherIconResource(humidityModel.icon) + wim.getWeatherIconResource(humidityModel.icon) ) bigUpdateViews.setTextViewText(R.id.humidity, humidityModel.value) bigUpdateViews.setViewVisibility(R.id.humidity_layout, View.VISIBLE) @@ -166,7 +168,7 @@ object WeatherNotificationBuilder { if (windGustModel != null) { bigUpdateViews.setImageViewResource( R.id.windgust_icon, - wip.getWeatherIconResource(windGustModel.icon) + wim.getWeatherIconResource(windGustModel.icon) ) bigUpdateViews.setTextViewText(R.id.windgust, windGustModel.value) bigUpdateViews.setViewVisibility(R.id.windgust_layout, View.VISIBLE) @@ -191,7 +193,7 @@ object WeatherNotificationBuilder { weatherIconResId } else { // Use default icon pack here; animated icons are not supported here - wip.getWeatherIconResource(viewModel.weatherIcon) + wim.getWeatherIconResource(viewModel.weatherIcon) } } } diff --git a/app/src/main/res/layout-v31/weather_notification_layout.xml b/app/src/main/res/layout-v31/weather_notification_layout.xml index 3dd31998..e2f90095 100644 --- a/app/src/main/res/layout-v31/weather_notification_layout.xml +++ b/app/src/main/res/layout-v31/weather_notification_layout.xml @@ -143,8 +143,7 @@ android:layout_marginEnd="4dp" android:adjustViewBounds="true" android:scaleType="fitCenter" - android:src="@drawable/wi_wind_direction" - android:tint="@color/colorTextPrimary" /> + android:src="@drawable/wi_wind_direction" /> + android:src="@drawable/wi_humidity" /> + android:src="@drawable/wi_strong_wind" /> + android:src="@drawable/wi_wind_direction" /> + android:src="@drawable/wi_humidity" /> + android:src="@drawable/wi_strong_wind" /> + + @@ -59,11 +61,11 @@ app:layout_constraintEnd_toStartOf="@id/grasspollen_label" app:layout_constraintHorizontal_chainStyle="packed" /> - - - Date: Tue, 23 Jun 2026 23:57:02 -0400 Subject: [PATCH 39/67] weathernow: enable animations where possible --- .../com/thewizrd/simpleweather/adapters/MoonPhaseAdapter.kt | 1 + app/src/main/res/layout/weathernow_moonphasecontrol.xml | 2 ++ app/src/main/res/layout/weathernow_pollencountcontrol.xml | 3 +++ 3 files changed, 6 insertions(+) diff --git a/app/src/main/java/com/thewizrd/simpleweather/adapters/MoonPhaseAdapter.kt b/app/src/main/java/com/thewizrd/simpleweather/adapters/MoonPhaseAdapter.kt index 38ad286d..b80409db 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/adapters/MoonPhaseAdapter.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/adapters/MoonPhaseAdapter.kt @@ -50,6 +50,7 @@ class MoonPhaseAdapter : RecyclerView.Adapter 0.35f } } + view.shouldAnimate = isSelected } } diff --git a/app/src/main/res/layout/weathernow_moonphasecontrol.xml b/app/src/main/res/layout/weathernow_moonphasecontrol.xml index c411edda..0625697f 100644 --- a/app/src/main/res/layout/weathernow_moonphasecontrol.xml +++ b/app/src/main/res/layout/weathernow_moonphasecontrol.xml @@ -105,6 +105,7 @@ android:text="@{viewModel.weather.moonPhase.moonrise}" android:textAppearance="?textAppearanceBodyLarge" android:textSize="@dimen/moonriseset_text_size" + app:animate="true" app:drawableHeight="@dimen/moonriseset_image_size" app:drawableWidth="@dimen/moonriseset_image_size" android:drawablePadding="4dp" @@ -129,6 +130,7 @@ android:text="@{viewModel.weather.moonPhase.moonset}" android:textAppearance="?textAppearanceBodyLarge" android:textSize="@dimen/moonriseset_text_size" + app:animate="true" app:drawableHeight="@dimen/moonriseset_image_size" app:drawableWidth="@dimen/moonriseset_image_size" android:drawablePadding="4dp" diff --git a/app/src/main/res/layout/weathernow_pollencountcontrol.xml b/app/src/main/res/layout/weathernow_pollencountcontrol.xml index e9c5e357..e192eb67 100644 --- a/app/src/main/res/layout/weathernow_pollencountcontrol.xml +++ b/app/src/main/res/layout/weathernow_pollencountcontrol.xml @@ -65,6 +65,7 @@ android:id="@+id/treepollen_icon" android:layout_width="0dp" android:layout_height="36dp" + app:animate="true" app:weatherIcon="@{WeatherIcons.TREE_POLLEN}" app:layout_constraintTop_toBottomOf="@id/treepollen_label" app:layout_constraintBottom_toTopOf="@id/treepollen_description" @@ -110,6 +111,7 @@ android:id="@+id/grasspollen_icon" android:layout_width="0dp" android:layout_height="36dp" + app:animate="true" app:weatherIcon="@{WeatherIcons.GRASS_POLLEN}" app:layout_constraintTop_toBottomOf="@id/grasspollen_label" app:layout_constraintBottom_toTopOf="@id/grasspollen_description" @@ -155,6 +157,7 @@ android:id="@+id/ragweedpollen_icon" android:layout_width="0dp" android:layout_height="36dp" + app:animate="true" app:weatherIcon="@{WeatherIcons.RAGWEED_POLLEN}" app:layout_constraintTop_toBottomOf="@id/ragweedpollen_label" app:layout_constraintBottom_toTopOf="@id/ragweedpollen_description" From 18295a94bf4e716b0879bdf1860ba062c9e4bd48 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Tue, 23 Jun 2026 23:57:43 -0400 Subject: [PATCH 40/67] analytics: log selected icon provider --- .../simpleweather/preferences/SettingsFragment.kt | 9 ++++++--- .../com/thewizrd/common/migrations/VersionMigrations.kt | 5 +++++ .../thewizrd/shared_resources/utils/AnalyticsProps.kt | 1 + .../simpleweather/preferences/SettingsActivity.kt | 6 +++++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/thewizrd/simpleweather/preferences/SettingsFragment.kt b/app/src/main/java/com/thewizrd/simpleweather/preferences/SettingsFragment.kt index 42dc9169..cdba4254 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/preferences/SettingsFragment.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/preferences/SettingsFragment.kt @@ -39,10 +39,8 @@ import androidx.recyclerview.widget.ConcatAdapter import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import com.google.android.material.R as materialRes import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.shape.MaterialShapeDrawable -import com.thewizrd.common.R as commonRes import com.thewizrd.common.helpers.ListChangedArgs import com.thewizrd.common.helpers.OnListChangedListener import com.thewizrd.common.helpers.PermissionLauncher @@ -53,7 +51,6 @@ import com.thewizrd.common.helpers.notificationPermissionEnabled import com.thewizrd.common.helpers.openAppSettingsActivity import com.thewizrd.common.preferences.KeyEntryPreferenceDialogFragment import com.thewizrd.common.utils.ActivityUtils.recreateCompat -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.Constants import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.controls.ProviderEntry @@ -124,6 +121,8 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.isActive import kotlinx.coroutines.launch +import com.google.android.material.R as materialRes +import com.thewizrd.shared_resources.R as sharedRes class SettingsFragment : BaseSettingsFragment(), OnSharedPreferenceChangeListener, @@ -1172,6 +1171,10 @@ class SettingsFragment : BaseSettingsFragment(), return } super.onRadioButtonConfirmed(selectedKey) + AnalyticsLogger.logEvent("W_Icon_Selected", Bundle().apply { + putString("iconProvider", selectedKey) + }) + AnalyticsLogger.setUserProperty(AnalyticsProps.ICON_PROVIDER, selectedKey) } } diff --git a/common/src/main/java/com/thewizrd/common/migrations/VersionMigrations.kt b/common/src/main/java/com/thewizrd/common/migrations/VersionMigrations.kt index 341dd87b..8a5ef9e3 100644 --- a/common/src/main/java/com/thewizrd/common/migrations/VersionMigrations.kt +++ b/common/src/main/java/com/thewizrd/common/migrations/VersionMigrations.kt @@ -157,6 +157,7 @@ object VersionMigrations { "API_IsInternalKey", (!settingsMgr.usePersonalKey(settingsMgr.getAPI())).toString() ) + putString("IconProvider", settingsMgr.getIconsProvider()) putLong("VersionCode", settingsMgr.getVersionCode()) putLong("CurrentVersionCode", versionCode) } @@ -172,6 +173,10 @@ object VersionMigrations { AnalyticsProps.USER_LOCALE, LocaleUtils.getLocale().toLanguageTag() ) + AnalyticsLogger.setUserProperty( + AnalyticsProps.ICON_PROVIDER, + settingsMgr.getIconsProvider() + ) } if (versionCode > 0) { diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/AnalyticsProps.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/AnalyticsProps.kt index 5e4475ae..20b8e72e 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/AnalyticsProps.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/AnalyticsProps.kt @@ -2,6 +2,7 @@ package com.thewizrd.shared_resources.utils object AnalyticsProps { const val WEATHER_PROVIDER = "weather_provider" + const val ICON_PROVIDER = "icon_provider" const val USING_PERSONAL_KEY = "using_personal_key" const val USER_LOCALE = "user_locale" const val DEVICE_TYPE = "device_type" diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/preferences/SettingsActivity.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/preferences/SettingsActivity.kt index 58e6d8b8..e125a9d4 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/preferences/SettingsActivity.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/preferences/SettingsActivity.kt @@ -43,7 +43,6 @@ import com.thewizrd.common.helpers.getBackgroundLocationRationale import com.thewizrd.common.helpers.locationPermissionEnabled import com.thewizrd.common.utils.ErrorMessage import com.thewizrd.common.wearable.WearConnectionStatus -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.appLib import com.thewizrd.shared_resources.controls.ProviderEntry import com.thewizrd.shared_resources.di.localBroadcastManager @@ -90,6 +89,7 @@ import com.thewizrd.simpleweather.wearable.tiles.WeatherTileHelper import com.thewizrd.weather_api.weatherModule import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import com.thewizrd.shared_resources.R as sharedRes class SettingsActivity : UserLocaleActivity() { companion object { @@ -1006,6 +1006,10 @@ class SettingsActivity : UserLocaleActivity() { return } super.onRadioButtonConfirmed(selectedKey) + AnalyticsLogger.logEvent("W_Icon_Selected", Bundle().apply { + putString("iconProvider", selectedKey) + }) + AnalyticsLogger.setUserProperty(AnalyticsProps.ICON_PROVIDER, selectedKey) } } From 9d7ea23ff7459504ed1209121948008474fa0933 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 27 Jun 2026 15:52:13 -0400 Subject: [PATCH 41/67] icons: add visibility and aq --- .../thewizrd/common/controls/DetailItemViewModel.java | 10 +++++----- .../icons/GoogleWeatherIconsProvider.kt | 3 +++ .../shared_resources/icons/JDWIIconsProvider.kt | 3 +++ .../icons/WUndergroundIconsProvider.kt | 3 +++ .../shared_resources/icons/WeatherIconicProvider.kt | 3 +++ .../thewizrd/shared_resources/icons/WeatherIcons.java | 3 +++ .../shared_resources/icons/WeatherIconsEFProvider.kt | 3 +++ shared_resources/src/main/res/drawable/material_aq.xml | 9 +++++++++ .../src/main/res/drawable/material_visibility.xml | 9 +++++++++ .../ui/preferences/DetailsWeatherTileConfigScreen.kt | 6 +++--- .../tiles/DetailsWeatherTileProviderService.kt | 6 +++--- 11 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 shared_resources/src/main/res/drawable/material_aq.xml create mode 100644 shared_resources/src/main/res/drawable/material_visibility.xml diff --git a/common/src/main/java/com/thewizrd/common/controls/DetailItemViewModel.java b/common/src/main/java/com/thewizrd/common/controls/DetailItemViewModel.java index 20f23db8..b356a970 100644 --- a/common/src/main/java/com/thewizrd/common/controls/DetailItemViewModel.java +++ b/common/src/main/java/com/thewizrd/common/controls/DetailItemViewModel.java @@ -72,7 +72,7 @@ public DetailItemViewModel(@NonNull WeatherDetailsType detailsType, CharSequence break; case VISIBILITY: this.label = context.getString(R.string.label_visibility); - this.icon = WeatherIcons.FOG; + this.icon = WeatherIcons.VISIBILITY; break; case POPCHANCE: this.label = context.getString(R.string.label_chance); @@ -112,11 +112,11 @@ public DetailItemViewModel(@NonNull WeatherDetailsType detailsType, CharSequence break; case UV: this.label = context.getString(R.string.label_uv); - this.icon = WeatherIcons.DAY_SUNNY; + this.icon = WeatherIcons.UV_INDEX; break; case AIRQUALITY: this.label = context.getString(R.string.label_airquality); - this.icon = WeatherIcons.CLOUDY_GUSTS; + this.icon = WeatherIcons.AIR_QUALITY; break; case TREEPOLLEN: this.label = context.getString(R.string.label_tree_pollen); @@ -257,7 +257,7 @@ public DetailItemViewModel(@NonNull AirQuality aqi) { final Context context = SharedModuleKt.getSharedDeps().getContext(); this.detailsType = WeatherDetailsType.AIRQUALITY; this.label = context.getString(R.string.label_airquality_short); - this.icon = WeatherIcons.CLOUDY_GUSTS; + this.icon = WeatherIcons.AIR_QUALITY; this.iconRotation = 0; if (aqi.getIndex() < 51) { @@ -281,7 +281,7 @@ public DetailItemViewModel(@NonNull UV uv) { final Context context = SharedModuleKt.getSharedDeps().getContext(); this.detailsType = WeatherDetailsType.UV; this.label = context.getString(R.string.label_uv); - this.icon = WeatherIcons.DAY_SUNNY; + this.icon = WeatherIcons.UV_INDEX; this.iconRotation = 0; if (uv.getIndex() < 3) { diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/GoogleWeatherIconsProvider.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/GoogleWeatherIconsProvider.kt index 3969073a..f4fa6165 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/GoogleWeatherIconsProvider.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/GoogleWeatherIconsProvider.kt @@ -181,6 +181,9 @@ class GoogleWeatherIconsProvider : WeatherIconProvider() { WeatherIcons.DIRECTION_UP -> R.drawable.material_arrow_upward WeatherIcons.DIRECTION_DOWN -> R.drawable.material_arrow_downward + WeatherIcons.VISIBILITY -> R.drawable.material_visibility + WeatherIcons.AIR_QUALITY -> R.drawable.material_aq + WeatherIcons.WIND_BEAUFORT_0 -> R.drawable.wi_wind_beaufort_0 WeatherIcons.WIND_BEAUFORT_1 -> R.drawable.wi_wind_beaufort_1 WeatherIcons.WIND_BEAUFORT_2 -> R.drawable.wi_wind_beaufort_2 diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/JDWIIconsProvider.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/JDWIIconsProvider.kt index cd04990c..9586601c 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/JDWIIconsProvider.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/JDWIIconsProvider.kt @@ -159,6 +159,9 @@ class JDWIIconsProvider : WeatherIconProvider() { WeatherIcons.DIRECTION_UP -> R.drawable.material_arrow_upward WeatherIcons.DIRECTION_DOWN -> R.drawable.material_arrow_downward + WeatherIcons.VISIBILITY -> R.drawable.jdwi_visibility + WeatherIcons.AIR_QUALITY -> R.drawable.material_aq + WeatherIcons.WIND_BEAUFORT_0 -> R.drawable.wi_wind_beaufort_0 WeatherIcons.WIND_BEAUFORT_1 -> R.drawable.wi_wind_beaufort_1 WeatherIcons.WIND_BEAUFORT_2 -> R.drawable.wi_wind_beaufort_2 diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WUndergroundIconsProvider.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WUndergroundIconsProvider.kt index 95bd73a4..7d05a80c 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WUndergroundIconsProvider.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WUndergroundIconsProvider.kt @@ -149,6 +149,9 @@ class WUndergroundIconsProvider : WeatherIconProvider() { WeatherIcons.DIRECTION_UP -> R.drawable.wi_direction_up WeatherIcons.DIRECTION_DOWN -> R.drawable.wi_direction_down + WeatherIcons.VISIBILITY -> R.drawable.material_visibility + WeatherIcons.AIR_QUALITY -> R.drawable.wi_windy + // Beaufort WeatherIcons.WIND_BEAUFORT_0 -> R.drawable.wi_wind_beaufort_0 WeatherIcons.WIND_BEAUFORT_1 -> R.drawable.wi_wind_beaufort_1 diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconicProvider.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconicProvider.kt index 3b419936..874cc688 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconicProvider.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconicProvider.kt @@ -130,6 +130,9 @@ class WeatherIconicProvider(private val isColored: Boolean = false) : WeatherIco WeatherIcons.DIRECTION_UP -> R.drawable.wi_direction_up WeatherIcons.DIRECTION_DOWN -> R.drawable.wi_direction_down + WeatherIcons.VISIBILITY -> R.drawable.material_visibility + WeatherIcons.AIR_QUALITY -> if (isColored) R.drawable.wic_color_fog else R.drawable.wic_fog + WeatherIcons.WIND_BEAUFORT_0 -> R.drawable.wi_wind_beaufort_0 WeatherIcons.WIND_BEAUFORT_1 -> R.drawable.wi_wind_beaufort_1 WeatherIcons.WIND_BEAUFORT_2 -> R.drawable.wi_wind_beaufort_2 diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIcons.java b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIcons.java index 99bf2cc4..bfb88d91 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIcons.java +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIcons.java @@ -113,6 +113,9 @@ private WeatherIcons() { public static final String DIRECTION_UP = "\uf058"; public static final String DIRECTION_DOWN = "\uf044"; + public static final String VISIBILITY = "\uf014-vis"; + public static final String AIR_QUALITY = "\uf011-aqi"; + // Beaufort public static final String WIND_BEAUFORT_0 = "\uf0b7"; public static final String WIND_BEAUFORT_1 = "\uf0b8"; diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsEFProvider.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsEFProvider.kt index 1a34d584..69507a17 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsEFProvider.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsEFProvider.kt @@ -134,6 +134,9 @@ class WeatherIconsEFProvider : WeatherIconProvider() { WeatherIcons.DIRECTION_UP -> R.drawable.wi_direction_up WeatherIcons.DIRECTION_DOWN -> R.drawable.wi_direction_down + WeatherIcons.VISIBILITY -> R.drawable.material_visibility + WeatherIcons.AIR_QUALITY -> R.drawable.wi_windy + WeatherIcons.WIND_BEAUFORT_0 -> R.drawable.wi_wind_beaufort_0 WeatherIcons.WIND_BEAUFORT_1 -> R.drawable.wi_wind_beaufort_1 WeatherIcons.WIND_BEAUFORT_2 -> R.drawable.wi_wind_beaufort_2 diff --git a/shared_resources/src/main/res/drawable/material_aq.xml b/shared_resources/src/main/res/drawable/material_aq.xml new file mode 100644 index 00000000..dd687d36 --- /dev/null +++ b/shared_resources/src/main/res/drawable/material_aq.xml @@ -0,0 +1,9 @@ + + + diff --git a/shared_resources/src/main/res/drawable/material_visibility.xml b/shared_resources/src/main/res/drawable/material_visibility.xml new file mode 100644 index 00000000..f96b8ea2 --- /dev/null +++ b/shared_resources/src/main/res/drawable/material_visibility.xml @@ -0,0 +1,9 @@ + + + diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/preferences/DetailsWeatherTileConfigScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/preferences/DetailsWeatherTileConfigScreen.kt index 4e983b5e..d9afb96c 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/preferences/DetailsWeatherTileConfigScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/preferences/DetailsWeatherTileConfigScreen.kt @@ -71,7 +71,6 @@ import androidx.wear.compose.material3.LocalContentColor import androidx.wear.compose.material3.ScreenScaffold import androidx.wear.compose.material3.Text import com.thewizrd.common.controls.WeatherDetailsType -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.designer.initializeDependencies import com.thewizrd.shared_resources.icons.WeatherIcons @@ -98,6 +97,7 @@ import sh.calvin.reorderable.ReorderableItem import sh.calvin.reorderable.rememberReorderableLazyGridState import java.util.Collections import kotlin.math.roundToInt +import com.thewizrd.shared_resources.R as sharedRes @Composable fun DetailsWeatherTileConfigScreen( @@ -541,7 +541,7 @@ private fun WeatherDetailsType.toWeatherIcon(): String = when (this) { WeatherDetailsType.WINDGUST -> WeatherIcons.CLOUDY_GUSTS WeatherDetailsType.HUMIDITY -> WeatherIcons.HUMIDITY WeatherDetailsType.PRESSURE -> WeatherIcons.BAROMETER - WeatherDetailsType.VISIBILITY -> WeatherIcons.FOG + WeatherDetailsType.VISIBILITY -> WeatherIcons.VISIBILITY WeatherDetailsType.POPCLOUDINESS -> WeatherIcons.CLOUDY WeatherDetailsType.POPCHANCE -> WeatherIcons.UMBRELLA WeatherDetailsType.POPRAIN -> WeatherIcons.RAINDROPS @@ -552,7 +552,7 @@ private fun WeatherDetailsType.toWeatherIcon(): String = when (this) { WeatherDetailsType.MOONPHASE -> WeatherIcons.MOON_NEW WeatherDetailsType.BEAUFORT -> WeatherIcons.WIND_BEAUFORT_0 WeatherDetailsType.UV -> WeatherIcons.UV_INDEX - WeatherDetailsType.AIRQUALITY -> WeatherIcons.CLOUDY_GUSTS + WeatherDetailsType.AIRQUALITY -> WeatherIcons.AIR_QUALITY WeatherDetailsType.TREEPOLLEN -> WeatherIcons.TREE_POLLEN WeatherDetailsType.GRASSPOLLEN -> WeatherIcons.GRASS_POLLEN WeatherDetailsType.RAGWEEDPOLLEN -> WeatherIcons.RAGWEED_POLLEN diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/DetailsWeatherTileProviderService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/DetailsWeatherTileProviderService.kt index 46de9b10..c51b0dc3 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/DetailsWeatherTileProviderService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/tiles/DetailsWeatherTileProviderService.kt @@ -111,7 +111,7 @@ class DetailsWeatherTileProviderService : WeatherCoroutinesTileService() { WeatherDetailsType.VISIBILITY.name -> { this.addIdToImageMapping( id, - createImageResourceFromWeatherIcon(WeatherIcons.FOG, rotation) + createImageResourceFromWeatherIcon(WeatherIcons.VISIBILITY, rotation) ) } @@ -181,14 +181,14 @@ class DetailsWeatherTileProviderService : WeatherCoroutinesTileService() { WeatherDetailsType.UV.name -> { this.addIdToImageMapping( id, - createImageResourceFromWeatherIcon(WeatherIcons.DAY_SUNNY, rotation) + createImageResourceFromWeatherIcon(WeatherIcons.UV_INDEX, rotation) ) } WeatherDetailsType.AIRQUALITY.name -> { this.addIdToImageMapping( id, - createImageResourceFromWeatherIcon(WeatherIcons.CLOUDY_GUSTS, rotation) + createImageResourceFromWeatherIcon(WeatherIcons.AIR_QUALITY, rotation) ) } From 939f46934e84cd28c2621f5f4a1ee537597d0914 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 27 Jun 2026 16:44:39 -0400 Subject: [PATCH 42/67] icons: reorder --- .../com/thewizrd/shared_resources/icons/WeatherIconsManager.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt index 3e1f8d5d..f705c649 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt @@ -11,11 +11,11 @@ class WeatherIconsManager internal constructor() : WeatherIconsProvider { init { val defaultIconMap = mutableMapOf() defaultIconMap.addIconProvider(WeatherIconsEFProvider()) - defaultIconMap.addIconProvider(WUndergroundIconsProvider()) defaultIconMap.addIconProvider(WeatherIconicProvider()) defaultIconMap.addIconProvider(WeatherIconicProvider(isColored = true)) defaultIconMap.addIconProvider(JDWIIconsProvider()) defaultIconMap.addIconProvider(GoogleWeatherIconsProvider()) + defaultIconMap.addIconProvider(WUndergroundIconsProvider()) defaultIconProviders = Collections.unmodifiableMap(defaultIconMap) // Register default icon providers From cd0cf18294fcf270cb50e01d33852a1b480eed59 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 27 Jun 2026 16:55:49 -0400 Subject: [PATCH 43/67] icons: cleanup --- .../icons/WUndergroundIconsProvider.kt | 220 ------------------ .../icons/WeatherIconsManager.kt | 1 - .../main/res/drawable/wui_chanceflurries.xml | 26 --- .../src/main/res/drawable/wui_chancerain.xml | 20 -- .../src/main/res/drawable/wui_chancesleet.xml | 20 -- .../src/main/res/drawable/wui_chancesnow.xml | 20 -- .../main/res/drawable/wui_chancetstorms.xml | 20 -- .../src/main/res/drawable/wui_cloudy.xml | 17 -- .../res/drawable/wui_day_mostlycloudy.xml | 23 -- .../res/drawable/wui_day_partlycloudy.xml | 23 -- .../src/main/res/drawable/wui_day_sunny.xml | 17 -- .../src/main/res/drawable/wui_flurries.xml | 35 --- .../src/main/res/drawable/wui_fog.xml | 20 -- .../src/main/res/drawable/wui_nt_clear.xml | 15 -- .../main/res/drawable/wui_nt_mostlycloudy.xml | 20 -- .../main/res/drawable/wui_nt_partlycloudy.xml | 20 -- .../src/main/res/drawable/wui_rain.xml | 20 -- .../src/main/res/drawable/wui_sleet.xml | 20 -- .../src/main/res/drawable/wui_tstorms.xml | 23 -- .../tile_layout_currentweather_icontemp.xml | 2 +- .../tile_layout_currentweather_icontemp.xml | 2 +- .../tile_layout_currentweather_icontemp.xml | 2 +- 22 files changed, 3 insertions(+), 583 deletions(-) delete mode 100644 shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WUndergroundIconsProvider.kt delete mode 100644 shared_resources/src/main/res/drawable/wui_chanceflurries.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_chancerain.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_chancesleet.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_chancesnow.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_chancetstorms.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_cloudy.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_day_mostlycloudy.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_day_partlycloudy.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_day_sunny.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_flurries.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_fog.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_nt_clear.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_nt_mostlycloudy.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_nt_partlycloudy.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_rain.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_sleet.xml delete mode 100644 shared_resources/src/main/res/drawable/wui_tstorms.xml diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WUndergroundIconsProvider.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WUndergroundIconsProvider.kt deleted file mode 100644 index 7d05a80c..00000000 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WUndergroundIconsProvider.kt +++ /dev/null @@ -1,220 +0,0 @@ -package com.thewizrd.shared_resources.icons - -import androidx.annotation.DrawableRes -import com.thewizrd.shared_resources.R - -class WUndergroundIconsProvider : WeatherIconProvider() { - override fun getKey(): String { - return "wui-ashley-jager" - } - - override fun getDisplayName(): String { - return "WeatherUnderground Icons" - } - - override fun getAuthorName(): String { - return "Ashley Jager" - } - - override fun getAttributionLink(): String { - return "https://github.com/manifestinteractive/weather-underground-icons" - } - - override fun isFontIcon(): Boolean { - return false - } - - @DrawableRes - override fun getWeatherIconResource(icon: String): Int { - var weatherIcon = when (icon) { - WeatherIcons.DAY_SUNNY, - WeatherIcons.DAY_HOT, - WeatherIcons.DAY_LIGHT_WIND -> R.drawable.wui_day_sunny - - WeatherIcons.DAY_CLOUDY, - WeatherIcons.DAY_CLOUDY_GUSTS, - WeatherIcons.DAY_CLOUDY_WINDY, - WeatherIcons.DAY_CLOUDY_HIGH -> R.drawable.wui_day_mostlycloudy - - WeatherIcons.DAY_PARTLY_CLOUDY, - WeatherIcons.DAY_SUNNY_OVERCAST -> R.drawable.wui_day_partlycloudy - - // Night - WeatherIcons.NIGHT_CLEAR, - WeatherIcons.NIGHT_HOT, - WeatherIcons.NIGHT_LIGHT_WIND -> R.drawable.wui_nt_clear - - WeatherIcons.NIGHT_ALT_CLOUDY, - WeatherIcons.NIGHT_ALT_CLOUDY_GUSTS, - WeatherIcons.NIGHT_ALT_CLOUDY_WINDY -> R.drawable.wui_nt_mostlycloudy - - WeatherIcons.NIGHT_ALT_PARTLY_CLOUDY, - WeatherIcons.NIGHT_OVERCAST -> R.drawable.wui_nt_partlycloudy - - WeatherIcons.NIGHT_ALT_CLOUDY_HIGH -> R.drawable.wui_nt_mostlycloudy - - // Neutral - WeatherIcons.DAY_FOG, - WeatherIcons.DAY_HAZE, - WeatherIcons.NIGHT_FOG, - WeatherIcons.NIGHT_HAZE, - WeatherIcons.FOG, - WeatherIcons.HAZE -> R.drawable.wui_fog - - WeatherIcons.DAY_LIGHTNING, - WeatherIcons.NIGHT_ALT_LIGHTNING, - WeatherIcons.LIGHTNING -> R.drawable.wui_chancetstorms - - WeatherIcons.DAY_HAIL, - WeatherIcons.DAY_SLEET, - WeatherIcons.DAY_SLEET_STORM, - WeatherIcons.NIGHT_ALT_HAIL, - WeatherIcons.NIGHT_ALT_SLEET, - WeatherIcons.NIGHT_ALT_SLEET_STORM, - WeatherIcons.SLEET, - WeatherIcons.SLEET_STORM -> R.drawable.wui_sleet - - WeatherIcons.DAY_RAIN_MIX, - WeatherIcons.NIGHT_ALT_RAIN_MIX, - WeatherIcons.RAIN_MIX, - WeatherIcons.HAIL -> R.drawable.wui_chancesleet - - WeatherIcons.DAY_RAIN, - WeatherIcons.DAY_RAIN_WIND, - WeatherIcons.DAY_SHOWERS, - WeatherIcons.NIGHT_ALT_RAIN, - WeatherIcons.NIGHT_ALT_RAIN_WIND, - WeatherIcons.NIGHT_ALT_SHOWERS, - WeatherIcons.RAIN, - WeatherIcons.RAIN_WIND, - WeatherIcons.SHOWERS -> R.drawable.wui_rain - - WeatherIcons.DAY_SNOW, - WeatherIcons.DAY_SNOW_THUNDERSTORM, - WeatherIcons.DAY_SNOW_WIND, - WeatherIcons.NIGHT_ALT_SNOW, - WeatherIcons.NIGHT_ALT_SNOW_THUNDERSTORM, - WeatherIcons.NIGHT_ALT_SNOW_WIND, - WeatherIcons.SNOW, - WeatherIcons.SNOW_THUNDERSTORM, - WeatherIcons.SNOW_WIND, - WeatherIcons.SNOWFLAKE_COLD -> R.drawable.wui_snow - - WeatherIcons.DAY_SPRINKLE, - WeatherIcons.NIGHT_ALT_SPRINKLE, - WeatherIcons.SPRINKLE -> R.drawable.wui_chancerain - - WeatherIcons.DAY_STORM_SHOWERS, - WeatherIcons.DAY_THUNDERSTORM, - WeatherIcons.NIGHT_ALT_STORM_SHOWERS, - WeatherIcons.NIGHT_ALT_THUNDERSTORM, - WeatherIcons.STORM_SHOWERS, - WeatherIcons.THUNDERSTORM -> R.drawable.wui_tstorms - - WeatherIcons.DAY_WINDY, - WeatherIcons.NIGHT_WINDY -> R.drawable.wi_windy - - WeatherIcons.CLOUD, - WeatherIcons.CLOUDY, - WeatherIcons.CLOUDY_GUSTS, - WeatherIcons.CLOUDY_WINDY, - WeatherIcons.OVERCAST -> R.drawable.wui_cloudy - - WeatherIcons.HOT -> R.drawable.wi_thermometer_up - WeatherIcons.SMOG -> R.drawable.wi_smog - WeatherIcons.SMOKE -> R.drawable.wi_smoke - WeatherIcons.DUST -> R.drawable.wi_dust - WeatherIcons.WINDY, - WeatherIcons.LIGHT_WIND -> R.drawable.wi_windy - WeatherIcons.STRONG_WIND -> R.drawable.wi_strong_wind - WeatherIcons.SANDSTORM -> R.drawable.wi_sandstorm - WeatherIcons.HURRICANE -> R.drawable.wi_hurricane - WeatherIcons.TORNADO -> R.drawable.wi_tornado - - // Misc icons - WeatherIcons.FIRE -> R.drawable.wi_fire - WeatherIcons.FLOOD -> R.drawable.wi_flood - WeatherIcons.VOLCANO -> R.drawable.wi_volcano - WeatherIcons.BAROMETER -> R.drawable.wi_barometer - WeatherIcons.HUMIDITY -> R.drawable.wi_humidity - WeatherIcons.MOONRISE -> R.drawable.wi_moonrise - WeatherIcons.MOONSET -> R.drawable.wi_moonset - WeatherIcons.RAINDROP -> R.drawable.wi_raindrop - WeatherIcons.RAINDROPS -> R.drawable.wi_raindrops - WeatherIcons.SUNRISE -> R.drawable.wi_sunrise - WeatherIcons.SUNSET -> R.drawable.wi_sunset - WeatherIcons.THERMOMETER -> R.drawable.wi_thermometer - WeatherIcons.UMBRELLA -> R.drawable.wi_umbrella - WeatherIcons.WIND_DIRECTION -> R.drawable.wi_wind_direction - WeatherIcons.DIRECTION_UP -> R.drawable.wi_direction_up - WeatherIcons.DIRECTION_DOWN -> R.drawable.wi_direction_down - - WeatherIcons.VISIBILITY -> R.drawable.material_visibility - WeatherIcons.AIR_QUALITY -> R.drawable.wi_windy - - // Beaufort - WeatherIcons.WIND_BEAUFORT_0 -> R.drawable.wi_wind_beaufort_0 - WeatherIcons.WIND_BEAUFORT_1 -> R.drawable.wi_wind_beaufort_1 - WeatherIcons.WIND_BEAUFORT_2 -> R.drawable.wi_wind_beaufort_2 - WeatherIcons.WIND_BEAUFORT_3 -> R.drawable.wi_wind_beaufort_3 - WeatherIcons.WIND_BEAUFORT_4 -> R.drawable.wi_wind_beaufort_4 - WeatherIcons.WIND_BEAUFORT_5 -> R.drawable.wi_wind_beaufort_5 - WeatherIcons.WIND_BEAUFORT_6 -> R.drawable.wi_wind_beaufort_6 - WeatherIcons.WIND_BEAUFORT_7 -> R.drawable.wi_wind_beaufort_7 - WeatherIcons.WIND_BEAUFORT_8 -> R.drawable.wi_wind_beaufort_8 - WeatherIcons.WIND_BEAUFORT_9 -> R.drawable.wi_wind_beaufort_9 - WeatherIcons.WIND_BEAUFORT_10 -> R.drawable.wi_wind_beaufort_10 - WeatherIcons.WIND_BEAUFORT_11 -> R.drawable.wi_wind_beaufort_11 - WeatherIcons.WIND_BEAUFORT_12 -> R.drawable.wi_wind_beaufort_12 - - // Moon phase - WeatherIcons.MOON_NEW -> R.drawable.wi_moon_new - WeatherIcons.MOON_WAXING_CRESCENT_3 -> R.drawable.wi_moon_waxing_crescent_3 - WeatherIcons.MOON_FIRST_QUARTER -> R.drawable.wi_moon_first_quarter - WeatherIcons.MOON_WAXING_GIBBOUS_3 -> R.drawable.wi_moon_waxing_gibbous_3 - WeatherIcons.MOON_FULL -> R.drawable.wi_moon_full - WeatherIcons.MOON_WANING_GIBBOUS_3 -> R.drawable.wi_moon_waning_gibbous_3 - WeatherIcons.MOON_THIRD_QUARTER -> R.drawable.wi_moon_third_quarter - WeatherIcons.MOON_WANING_CRESCENT_3 -> R.drawable.wi_moon_waning_crescent_3 - WeatherIcons.MOON_ALT_NEW -> R.drawable.wi_moon_alt_new - WeatherIcons.MOON_ALT_WAXING_CRESCENT_3 -> R.drawable.wi_moon_alt_waxing_crescent_3 - WeatherIcons.MOON_ALT_FIRST_QUARTER -> R.drawable.wi_moon_alt_first_quarter - WeatherIcons.MOON_ALT_WAXING_GIBBOUS_3 -> R.drawable.wi_moon_alt_waxing_gibbous_3 - WeatherIcons.MOON_ALT_FULL -> R.drawable.wi_moon_alt_full - WeatherIcons.MOON_ALT_WANING_GIBBOUS_3 -> R.drawable.wi_moon_alt_waning_gibbous_3 - WeatherIcons.MOON_ALT_THIRD_QUARTER -> R.drawable.wi_moon_alt_third_quarter - WeatherIcons.MOON_ALT_WANING_CRESCENT_3 -> R.drawable.wi_moon_alt_waning_crescent_3 - - WeatherIcons.UV_INDEX, - WeatherIcons.UV_INDEX_1, - WeatherIcons.UV_INDEX_2, - WeatherIcons.UV_INDEX_3, - WeatherIcons.UV_INDEX_4, - WeatherIcons.UV_INDEX_5, - WeatherIcons.UV_INDEX_6, - WeatherIcons.UV_INDEX_7, - WeatherIcons.UV_INDEX_8, - WeatherIcons.UV_INDEX_9, - WeatherIcons.UV_INDEX_10, - WeatherIcons.UV_INDEX_11 -> R.drawable.wui_day_sunny - - WeatherIcons.TREE_POLLEN -> R.drawable.ic_outline_tree - WeatherIcons.GRASS_POLLEN -> R.drawable.ic_baseline_grass - WeatherIcons.RAGWEED_POLLEN -> R.drawable.ic_ragweed_pollen - - WeatherIcons.FAHRENHEIT -> R.drawable.wi_fahrenheit - WeatherIcons.CELSIUS -> R.drawable.wi_celsius - - WeatherIcons.NA -> R.drawable.wui_unknown - - else -> -1 - } - - if (weatherIcon == -1) { - // Not Available - weatherIcon = R.drawable.wui_unknown - } - - return weatherIcon - } -} \ No newline at end of file diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt index f705c649..70d5657c 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt @@ -15,7 +15,6 @@ class WeatherIconsManager internal constructor() : WeatherIconsProvider { defaultIconMap.addIconProvider(WeatherIconicProvider(isColored = true)) defaultIconMap.addIconProvider(JDWIIconsProvider()) defaultIconMap.addIconProvider(GoogleWeatherIconsProvider()) - defaultIconMap.addIconProvider(WUndergroundIconsProvider()) defaultIconProviders = Collections.unmodifiableMap(defaultIconMap) // Register default icon providers diff --git a/shared_resources/src/main/res/drawable/wui_chanceflurries.xml b/shared_resources/src/main/res/drawable/wui_chanceflurries.xml deleted file mode 100644 index c62acc9b..00000000 --- a/shared_resources/src/main/res/drawable/wui_chanceflurries.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_chancerain.xml b/shared_resources/src/main/res/drawable/wui_chancerain.xml deleted file mode 100644 index c35c4aa7..00000000 --- a/shared_resources/src/main/res/drawable/wui_chancerain.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_chancesleet.xml b/shared_resources/src/main/res/drawable/wui_chancesleet.xml deleted file mode 100644 index 3b2162ab..00000000 --- a/shared_resources/src/main/res/drawable/wui_chancesleet.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_chancesnow.xml b/shared_resources/src/main/res/drawable/wui_chancesnow.xml deleted file mode 100644 index 3fd1ced8..00000000 --- a/shared_resources/src/main/res/drawable/wui_chancesnow.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_chancetstorms.xml b/shared_resources/src/main/res/drawable/wui_chancetstorms.xml deleted file mode 100644 index 68befc80..00000000 --- a/shared_resources/src/main/res/drawable/wui_chancetstorms.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_cloudy.xml b/shared_resources/src/main/res/drawable/wui_cloudy.xml deleted file mode 100644 index 25e0fdd0..00000000 --- a/shared_resources/src/main/res/drawable/wui_cloudy.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_day_mostlycloudy.xml b/shared_resources/src/main/res/drawable/wui_day_mostlycloudy.xml deleted file mode 100644 index 584576d0..00000000 --- a/shared_resources/src/main/res/drawable/wui_day_mostlycloudy.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_day_partlycloudy.xml b/shared_resources/src/main/res/drawable/wui_day_partlycloudy.xml deleted file mode 100644 index 8760ddb0..00000000 --- a/shared_resources/src/main/res/drawable/wui_day_partlycloudy.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_day_sunny.xml b/shared_resources/src/main/res/drawable/wui_day_sunny.xml deleted file mode 100644 index cde45509..00000000 --- a/shared_resources/src/main/res/drawable/wui_day_sunny.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_flurries.xml b/shared_resources/src/main/res/drawable/wui_flurries.xml deleted file mode 100644 index b1a5e319..00000000 --- a/shared_resources/src/main/res/drawable/wui_flurries.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_fog.xml b/shared_resources/src/main/res/drawable/wui_fog.xml deleted file mode 100644 index 927fbc99..00000000 --- a/shared_resources/src/main/res/drawable/wui_fog.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_nt_clear.xml b/shared_resources/src/main/res/drawable/wui_nt_clear.xml deleted file mode 100644 index 656dd241..00000000 --- a/shared_resources/src/main/res/drawable/wui_nt_clear.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_nt_mostlycloudy.xml b/shared_resources/src/main/res/drawable/wui_nt_mostlycloudy.xml deleted file mode 100644 index ba86bd2e..00000000 --- a/shared_resources/src/main/res/drawable/wui_nt_mostlycloudy.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_nt_partlycloudy.xml b/shared_resources/src/main/res/drawable/wui_nt_partlycloudy.xml deleted file mode 100644 index 9c457ce7..00000000 --- a/shared_resources/src/main/res/drawable/wui_nt_partlycloudy.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_rain.xml b/shared_resources/src/main/res/drawable/wui_rain.xml deleted file mode 100644 index e9c72bf4..00000000 --- a/shared_resources/src/main/res/drawable/wui_rain.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_sleet.xml b/shared_resources/src/main/res/drawable/wui_sleet.xml deleted file mode 100644 index da3f3382..00000000 --- a/shared_resources/src/main/res/drawable/wui_sleet.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/shared_resources/src/main/res/drawable/wui_tstorms.xml b/shared_resources/src/main/res/drawable/wui_tstorms.xml deleted file mode 100644 index 9385d6cb..00000000 --- a/shared_resources/src/main/res/drawable/wui_tstorms.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - diff --git a/wearapp/src/main/res/layout-sw180dp-notround/tile_layout_currentweather_icontemp.xml b/wearapp/src/main/res/layout-sw180dp-notround/tile_layout_currentweather_icontemp.xml index eee1f27f..ba1b16a0 100644 --- a/wearapp/src/main/res/layout-sw180dp-notround/tile_layout_currentweather_icontemp.xml +++ b/wearapp/src/main/res/layout-sw180dp-notround/tile_layout_currentweather_icontemp.xml @@ -16,7 +16,7 @@ android:layout_height="48dp" android:scaleType="fitCenter" android:layout_gravity="center" - tools:srcCompat="@drawable/wui_day_mostlycloudy" /> + tools:srcCompat="@drawable/goog_mostly_cloudy_day" /> + tools:srcCompat="@drawable/goog_mostly_cloudy_day" /> + tools:srcCompat="@drawable/goog_mostly_cloudy_day" /> Date: Sat, 27 Jun 2026 20:55:01 -0400 Subject: [PATCH 44/67] MeteoconsIconsProvider: add line variant --- .../com/thewizrd/shared_resources/icons/WeatherIconsManager.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt index 70d5657c..d3bb9175 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/icons/WeatherIconsManager.kt @@ -96,6 +96,7 @@ class WeatherIconsManager internal constructor() : WeatherIconsProvider { "pixeden-icons_set-weather" -> true "meteocons-basmilius", + "meteocons-basmilius-line", "wci_sliu_iconfinder", "w-iconic-jackd248-multicolor" -> false From a42c0b0aecbbeb32ddc6bf0dad3c7235b7c001b2 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 27 Jun 2026 22:51:45 -0400 Subject: [PATCH 45/67] WeatherApiProvider: correct smoky haze icon --- .../weather_api/weatherapi/weather/WeatherApiProvider.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt index 6dd2aac2..f505ecf5 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt @@ -510,8 +510,10 @@ class WeatherApiProvider : WeatherProviderImpl(), WeatherAlertProvider, PollenPr weatherIcon = WeatherIcons.OVERCAST } - /* Haze */ - 1012 -> { + /* 1012: Haze + * 1036: Smoky haze + */ + 1012, 1036 -> { weatherIcon = WeatherIcons.HAZE } @@ -545,9 +547,8 @@ class WeatherApiProvider : WeatherProviderImpl(), WeatherAlertProvider, PollenPr /* * 1033: Smoke - * 1036: Smoky haze */ - 1033, 1036 -> { + 1033 -> { weatherIcon = WeatherIcons.SMOKE } From 182f24d92c4c581e5725f665007276088f68bf08 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 27 Jun 2026 23:42:33 -0400 Subject: [PATCH 46/67] WeatherProviderImpl: update uv calculation from aqicn * Use sinusoidal interpolation from uv max --- .../weatherdata/WeatherProviderImpl.kt | 46 +++++++------------ 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt index e4318123..dd190c01 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherdata/WeatherProviderImpl.kt @@ -38,10 +38,11 @@ import com.thewizrd.weather_api.utils.RateLimitedRequest import com.thewizrd.weather_api.utils.logMissingIcon import com.thewizrd.weather_api.weatherModule import com.thewizrd.weather_api.weatherapi.weather.WeatherApiProvider -import java.time.Duration import java.time.LocalDate import java.time.format.DateTimeFormatter import java.util.Locale +import kotlin.math.PI +import kotlin.math.sin abstract class WeatherProviderImpl : WeatherProvider, RateLimitedRequest { protected lateinit var mLocationProvider: WeatherLocationProvider @@ -271,36 +272,21 @@ abstract class WeatherProviderImpl : WeatherProvider, RateLimitedRequest { if (weather.condition?.uv == null && date.isEqual(weather.condition!!.observationTime.toLocalDate())) { if (weather.astronomy!!.sunrise != null && weather.astronomy!!.sunset != null) { - val obsLocalTime = weather.condition!!.observationTime.toLocalTime() - // if before sunrise, after sunset, or +/- 2hrs before/after sunrise/sunset, uv min - if (obsLocalTime.isBefore(weather.astronomy!!.sunrise.toLocalTime()) || - obsLocalTime.isAfter(weather.astronomy!!.sunset.toLocalTime()) || - Duration.between( - weather.astronomy!!.sunrise.toLocalTime(), - obsLocalTime - ).abs().toHours() <= 2 || - Duration.between( - weather.astronomy!!.sunset.toLocalTime(), - obsLocalTime - ).abs().toHours() <= 2 - ) { - weather.condition!!.uv = UV(uviData.min?.toFloat() ?: 0f) + val sunrise = + weather.astronomy!!.sunrise.toEpochSecond(location.tzOffset) + val sunset = + weather.astronomy!!.sunset.toEpochSecond(location.tzOffset) + val obsTime = weather.condition!!.observationTime.toEpochSecond() + + if (obsTime in (sunrise + 1) until sunset) { + val dayFraction = + (obsTime - sunrise).toDouble() / (sunset - sunrise) + val maxUV = uviData.max?.toFloat() ?: 0f + // Sinusoidal interpolation: peak at solar noon (dayFraction = 0.5) + weather.condition!!.uv = + UV(maxUV * sin(dayFraction * PI).toFloat()) } else { - val totalSunlightTime = - weather.astronomy!!.sunset.toEpochSecond(location.tzOffset) - weather.astronomy!!.sunrise.toEpochSecond( - location.tzOffset - ) - val solarNoon = - weather.astronomy!!.sunrise.plusSeconds(totalSunlightTime / 2) - - // If +/- 2hrs within solar noon, UV max - if (Duration.between(solarNoon.toLocalTime(), obsLocalTime) - .abs().toHours() <= 2 - ) { - weather.condition!!.uv = UV(uviData.max?.toFloat() ?: 0f) - } else { // else uv avg - weather.condition!!.uv = UV(uviData.avg?.toFloat() ?: 0f) - } + weather.condition!!.uv = UV(uviData.min?.toFloat() ?: 0f) } } } From afa6363a83d815e175fd980cd0d503f7479a4d7e Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 27 Jun 2026 23:44:27 -0400 Subject: [PATCH 47/67] wearapp: update icon usage --- .../common/controls/DetailItemViewModel.java | 16 +++++- .../ui/components/IconControl.kt | 6 +- .../ui/components/WeatherDetailItem.kt | 55 ++++++++++++++----- .../ui/components/WeatherForecastPanel.kt | 22 +++++--- .../components/WeatherHourlyForecastPanel.kt | 24 ++++---- .../WeatherMinutelyForecastPanel.kt | 28 ++++++---- .../ui/weather/WeatherDetailsScreen.kt | 5 +- .../ui/weather/WeatherForecastScreen.kt | 5 +- .../ui/weather/WeatherHourlyForecastScreen.kt | 5 +- .../weather/WeatherMinutelyForecastScreen.kt | 5 +- .../simpleweather/ui/weather/WeatherNow.kt | 25 +++++++-- .../ui/weather/WeatherNowScreen.kt | 29 +++++++--- 12 files changed, 161 insertions(+), 64 deletions(-) diff --git a/common/src/main/java/com/thewizrd/common/controls/DetailItemViewModel.java b/common/src/main/java/com/thewizrd/common/controls/DetailItemViewModel.java index b356a970..c47adebe 100644 --- a/common/src/main/java/com/thewizrd/common/controls/DetailItemViewModel.java +++ b/common/src/main/java/com/thewizrd/common/controls/DetailItemViewModel.java @@ -281,7 +281,6 @@ public DetailItemViewModel(@NonNull UV uv) { final Context context = SharedModuleKt.getSharedDeps().getContext(); this.detailsType = WeatherDetailsType.UV; this.label = context.getString(R.string.label_uv); - this.icon = WeatherIcons.UV_INDEX; this.iconRotation = 0; if (uv.getIndex() < 3) { @@ -296,6 +295,21 @@ public DetailItemViewModel(@NonNull UV uv) { this.value = context.getString(R.string.uv_11); } + switch (uv.getIndex().intValue()) { + case 1 -> icon = WeatherIcons.UV_INDEX_1; + case 2 -> icon = WeatherIcons.UV_INDEX_2; + case 3 -> icon = WeatherIcons.UV_INDEX_3; + case 4 -> icon = WeatherIcons.UV_INDEX_4; + case 5 -> icon = WeatherIcons.UV_INDEX_5; + case 6 -> icon = WeatherIcons.UV_INDEX_6; + case 7 -> icon = WeatherIcons.UV_INDEX_7; + case 8 -> icon = WeatherIcons.UV_INDEX_8; + case 9 -> icon = WeatherIcons.UV_INDEX_9; + case 10 -> icon = WeatherIcons.UV_INDEX_10; + case 11 -> icon = WeatherIcons.UV_INDEX_11; + default -> icon = WeatherIcons.UV_INDEX; + } + this.shortValue = String.format(LocaleUtils.getLocale(), "%d", Math.round(uv.getIndex())); } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/IconControl.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/IconControl.kt index d34af60c..1d95fcb8 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/IconControl.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/IconControl.kt @@ -30,7 +30,6 @@ fun WeatherIcon( factory = { IconControl(it).apply { this.scaleType = alignment.scaleType - this.showAsMonochrome = showAsMonochrome this.shouldAnimate = shouldAnimate this.forceDarkMode = forceDarkMode this.iconProvider = iconProvider @@ -40,8 +39,8 @@ fun WeatherIcon( if (useDefaultIconProvider) { useDefaultIconProvider() } - this.contentDescription = contentDescription + this.showAsMonochrome = showAsMonochrome } }, update = { @@ -51,6 +50,9 @@ fun WeatherIcon( if (it.weatherIcon != weatherIcon) { it.weatherIcon = weatherIcon } + if (it.showAsMonochrome != showAsMonochrome) { + it.showAsMonochrome = showAsMonochrome + } } ) } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherDetailItem.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherDetailItem.kt index 2e7ba5dc..27ec61ee 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherDetailItem.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherDetailItem.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate @@ -19,16 +20,42 @@ import androidx.wear.compose.material3.LocalContentColor import androidx.wear.compose.material3.Text import androidx.wear.compose.ui.tooling.preview.WearPreviewFontScales import com.thewizrd.common.controls.DetailItemViewModel -import com.thewizrd.common.controls.WeatherDetailsType -import com.thewizrd.shared_resources.R as sharedRes -import com.thewizrd.simpleweather.R +import com.thewizrd.shared_resources.icons.WeatherIcons +import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.simpleweather.ui.compose.tools.WearPreviewDevices import com.thewizrd.simpleweather.ui.text.spannableStringToAnnotatedString import org.jetbrains.annotations.TestOnly +import com.thewizrd.shared_resources.R as sharedRes @Composable fun WeatherDetailItem( - model: DetailItemViewModel + model: DetailItemViewModel, + iconProvider: String? = null +) { + val wim = remember { + sharedDeps.weatherIconsManager + } + + WeatherDetailItem( + label = model.label, + value = model.value, + icon = model.icon, + iconRotation = model.iconRotation, + iconProvider = iconProvider, + showAsMonochrome = wim.shouldUseMonochrome(), + shouldAnimate = true + ) +} + +@Composable +private fun WeatherDetailItem( + label: CharSequence, + value: CharSequence, + icon: String, + iconProvider: String? = null, + iconRotation: Int = 0, + showAsMonochrome: Boolean = false, + shouldAnimate: Boolean = true, ) { val isPreview = LocalInspectionMode.current @@ -38,12 +65,12 @@ fun WeatherDetailItem( .height(60.dp), label = { Text( - text = spannableStringToAnnotatedString(model.label) + text = spannableStringToAnnotatedString(label) ) }, secondaryLabel = { Text( - text = spannableStringToAnnotatedString(model.value) + text = spannableStringToAnnotatedString(value) ) }, onClick = {}, @@ -63,9 +90,12 @@ fun WeatherDetailItem( modifier = Modifier .size(ButtonDefaults.IconSize) .wrapContentSize(align = Alignment.Center) - .rotate(model.iconRotation.toFloat()), - weatherIcon = model.icon, - tint = LocalContentColor.current + .rotate(iconRotation.toFloat()), + weatherIcon = icon, + iconProvider = iconProvider, + tint = LocalContentColor.current, + shouldAnimate = shouldAnimate, + showAsMonochrome = showAsMonochrome ) } } @@ -78,9 +108,8 @@ fun WeatherDetailItem( @TestOnly fun PreviewWeatherDetailItem() { WeatherDetailItem( - model = DetailItemViewModel(WeatherDetailsType.FEELSLIKE).apply { - value = "70°" - label = "Feels like" - } + label = "Feels like", + value = "70°", + icon = WeatherIcons.THERMOMETER ) } \ No newline at end of file diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherForecastPanel.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherForecastPanel.kt index 1468c9dc..ebfe032b 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherForecastPanel.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherForecastPanel.kt @@ -33,15 +33,16 @@ import androidx.wear.tooling.preview.devices.WearDevices import com.thewizrd.common.controls.DetailItemViewModel import com.thewizrd.common.controls.ForecastItemViewModel import com.thewizrd.common.controls.WeatherDetailsType -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.designer.initializeDependencies import com.thewizrd.shared_resources.icons.WeatherIcons import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.ui.text.spannableStringToAnnotatedString +import com.thewizrd.shared_resources.R as sharedRes @Composable fun WeatherForecastPanel( - model: ForecastItemViewModel + model: ForecastItemViewModel, + iconProvider: String? = null ) { val context = LocalContext.current val isLargeHeight = LocalConfiguration.current.screenHeightDp >= 225 @@ -82,6 +83,7 @@ fun WeatherForecastPanel( width = 32.dp, height = 36.dp ), weatherIcon = model.weatherIcon, + iconProvider = iconProvider, shouldAnimate = true ) Column( @@ -133,13 +135,15 @@ fun WeatherForecastPanel( ) { if (popData != null) { Row(verticalAlignment = Alignment.CenterVertically) { - Icon( + WeatherIcon( modifier = Modifier .size(20.dp) .padding(end = 2.dp), - painter = painterResource(sharedRes.drawable.wi_umbrella), + weatherIcon = WeatherIcons.UMBRELLA, + iconProvider = iconProvider, tint = colorResource(sharedRes.color.colorPrimaryLight), - contentDescription = null + showAsMonochrome = true, + contentDescription = popData.label?.toString() ) Text( text = spannableStringToAnnotatedString(popData.value), @@ -163,15 +167,17 @@ fun WeatherForecastPanel( } Row(verticalAlignment = Alignment.CenterVertically) { - Icon( + WeatherIcon( modifier = Modifier .size(20.dp) .padding(end = 2.dp) .rotate(windData.iconRotation.toFloat()) .align(Alignment.CenterVertically), - painter = painterResource(sharedRes.drawable.wi_wind_direction), + weatherIcon = WeatherIcons.WIND_DIRECTION, + useDefaultIconProvider = true, tint = Color(0xFF20B2AA), - contentDescription = null + showAsMonochrome = true, + contentDescription = windData.label?.toString() ) Text( modifier = Modifier.align(Alignment.CenterVertically), diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherHourlyForecastPanel.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherHourlyForecastPanel.kt index f5348ba3..066099e9 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherHourlyForecastPanel.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherHourlyForecastPanel.kt @@ -26,7 +26,6 @@ import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.dimensionResource -import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign @@ -34,14 +33,12 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.em import androidx.compose.ui.unit.sp -import androidx.wear.compose.material3.Icon import androidx.wear.compose.material3.MaterialTheme import androidx.wear.compose.material3.Text import androidx.wear.tooling.preview.devices.WearDevices import com.thewizrd.common.controls.DetailItemViewModel import com.thewizrd.common.controls.HourlyForecastItemViewModel import com.thewizrd.common.controls.WeatherDetailsType -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.designer.initializeDependencies import com.thewizrd.shared_resources.icons.WeatherIcons @@ -50,10 +47,12 @@ import com.thewizrd.shared_resources.utils.StringUtils import com.thewizrd.simpleweather.R import com.thewizrd.simpleweather.ui.text.spannableStringToAnnotatedString import java.time.ZonedDateTime +import com.thewizrd.shared_resources.R as sharedRes @Composable fun WeatherHourlyForecastPanel( - model: HourlyForecastItemViewModel + model: HourlyForecastItemViewModel, + iconProvider: String? = null ) { val ctx = LocalContext.current val isLargeHeight = LocalConfiguration.current.screenHeightDp >= 225 @@ -130,6 +129,7 @@ fun WeatherHourlyForecastPanel( width = 32.dp, height = 36.dp ), weatherIcon = model.weatherIcon, + iconProvider = iconProvider, shouldAnimate = true ) Text( @@ -147,14 +147,16 @@ fun WeatherHourlyForecastPanel( ) { if (popData != null) { Row(verticalAlignment = Alignment.CenterVertically) { - Icon( + WeatherIcon( modifier = Modifier .size(20.dp) .padding(end = 2.dp) .align(Alignment.CenterVertically), - painter = painterResource(sharedRes.drawable.wi_umbrella), + weatherIcon = WeatherIcons.UMBRELLA, + iconProvider = iconProvider, tint = colorResource(sharedRes.color.colorPrimaryLight), - contentDescription = null + showAsMonochrome = true, + contentDescription = popData.label?.toString() ) Text( modifier = Modifier.align(Alignment.CenterVertically), @@ -179,15 +181,17 @@ fun WeatherHourlyForecastPanel( } Row(verticalAlignment = Alignment.CenterVertically) { - Icon( + WeatherIcon( modifier = Modifier .size(20.dp) .padding(end = 2.dp) .rotate(windData.iconRotation.toFloat()) .align(Alignment.CenterVertically), - painter = painterResource(sharedRes.drawable.wi_wind_direction), + weatherIcon = WeatherIcons.WIND_DIRECTION, + useDefaultIconProvider = true, tint = Color(0xFF20B2AA), - contentDescription = null + showAsMonochrome = true, + contentDescription = windData.label?.toString() ) Text( modifier = Modifier.align(Alignment.CenterVertically), diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherMinutelyForecastPanel.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherMinutelyForecastPanel.kt index d4a5bd99..bec5d59e 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherMinutelyForecastPanel.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/components/WeatherMinutelyForecastPanel.kt @@ -16,11 +16,10 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.dimensionResource -import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.wear.compose.material3.Icon import androidx.wear.compose.material3.MaterialTheme import androidx.wear.compose.material3.Text import androidx.wear.tooling.preview.devices.WearDevices @@ -33,12 +32,14 @@ import com.thewizrd.shared_resources.R as sharedRes @Composable fun WeatherMinutelyForecastPanel( - model: MinutelyForecastViewModel + model: MinutelyForecastViewModel, + iconProvider: String? = null ) { WeatherMinutelyForecastPanel( date = model.date, precipAmount = model.precipAmount, - isSnow = model.isSnow + isSnow = model.isSnow, + iconProvider = iconProvider ) } @@ -46,7 +47,8 @@ fun WeatherMinutelyForecastPanel( private fun WeatherMinutelyForecastPanel( date: String? = null, precipAmount: String? = null, - isSnow: Boolean = false + isSnow: Boolean = false, + iconProvider: String? = null ) { Row( modifier = Modifier @@ -85,18 +87,24 @@ private fun WeatherMinutelyForecastPanel( text = precipAmount ?: WeatherIcons.PLACEHOLDER, style = MaterialTheme.typography.bodyLarge ) - Icon( + WeatherIcon( modifier = Modifier.size(20.dp), - painter = if (isSnow) { - painterResource(sharedRes.drawable.wi_snowflake_cold) + weatherIcon = if (isSnow) { + WeatherIcons.SNOWFLAKE_COLD } else { - painterResource(sharedRes.drawable.wi_raindrop) + WeatherIcons.RAINDROP }, - contentDescription = null, + iconProvider = iconProvider, tint = if (isSnow) { colorResource(id = sharedRes.color.colorSecondaryLight) } else { colorResource(id = sharedRes.color.colorSecondaryDark) + }, + showAsMonochrome = true, + contentDescription = if (isSnow) { + stringResource(id = sharedRes.string.label_qpf_snow) + } else { + stringResource(id = sharedRes.string.label_qpf_rain) } ) } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherDetailsScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherDetailsScreen.kt index 9462a8b3..1a48c5d6 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherDetailsScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherDetailsScreen.kt @@ -38,7 +38,8 @@ import com.thewizrd.simpleweather.ui.utils.rememberFocusRequester fun WeatherDetailsScreen( backStackEntry: NavBackStackEntry, focusRequester: FocusRequester, - weatherDetails: Collection + weatherDetails: Collection, + iconProvider: String? = null ) { val lifecycleOwner = LocalLifecycleOwner.current val scrollStateViewModel: ScalingLazyListStateViewModel = viewModel(backStackEntry) @@ -57,7 +58,7 @@ fun WeatherDetailsScreen( ) { weatherDetails.forEach { item(key = it.detailsType) { - WeatherDetailItem(model = it) + WeatherDetailItem(model = it, iconProvider = iconProvider) } } } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherForecastScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherForecastScreen.kt index 086fe1b5..01cb87fb 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherForecastScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherForecastScreen.kt @@ -29,7 +29,8 @@ import com.thewizrd.simpleweather.ui.theme.activityViewModel @Composable fun WeatherForecastScreen( backStackEntry: NavBackStackEntry, - focusRequester: FocusRequester + focusRequester: FocusRequester, + iconProvider: String? = null ) { val lifecycleOwner = LocalLifecycleOwner.current @@ -55,7 +56,7 @@ fun WeatherForecastScreen( ) { items(forecasts) { it?.let { - WeatherForecastPanel(model = it) + WeatherForecastPanel(model = it, iconProvider = iconProvider) } } } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherHourlyForecastScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherHourlyForecastScreen.kt index d74a2731..644bd6c3 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherHourlyForecastScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherHourlyForecastScreen.kt @@ -29,7 +29,8 @@ import com.thewizrd.simpleweather.ui.theme.activityViewModel @Composable fun WeatherHourlyForecastScreen( backStackEntry: NavBackStackEntry, - focusRequester: FocusRequester + focusRequester: FocusRequester, + iconProvider: String? = null ) { val lifecycleOwner = LocalLifecycleOwner.current @@ -55,7 +56,7 @@ fun WeatherHourlyForecastScreen( ) { items(hourlyForecasts) { it?.let { - WeatherHourlyForecastPanel(model = it) + WeatherHourlyForecastPanel(model = it, iconProvider = iconProvider) } } } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherMinutelyForecastScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherMinutelyForecastScreen.kt index d6677b32..a3ab89cf 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherMinutelyForecastScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherMinutelyForecastScreen.kt @@ -29,7 +29,8 @@ import com.thewizrd.simpleweather.viewmodels.ForecastPanelsViewModel @Composable fun WeatherMinutelyForecastScreen( backStackEntry: NavBackStackEntry, - focusRequester: FocusRequester + focusRequester: FocusRequester, + iconProvider: String? = null ) { val lifecycleOwner = LocalLifecycleOwner.current @@ -51,7 +52,7 @@ fun WeatherMinutelyForecastScreen( contentPadding = PaddingValues(top = 48.dp) ) { items(minutelyForecasts) { - WeatherMinutelyForecastPanel(model = it) + WeatherMinutelyForecastPanel(model = it, iconProvider = iconProvider) } } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNow.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNow.kt index eb1b563e..687b05e2 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNow.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNow.kt @@ -128,7 +128,12 @@ fun WeatherNow( weather.weatherDetailsMap.values } - WeatherDetailsScreen(backStackEntry, swipeFocusRequester, detailItems) + WeatherDetailsScreen( + backStackEntry, + swipeFocusRequester, + detailItems, + iconProvider = weather.iconProvider + ) } composable( @@ -140,7 +145,11 @@ fun WeatherNow( }, ) ) { backStackEntry -> - WeatherForecastScreen(backStackEntry, swipeFocusRequester) + WeatherForecastScreen( + backStackEntry, + swipeFocusRequester, + iconProvider = weather.iconProvider + ) } composable( @@ -152,13 +161,21 @@ fun WeatherNow( }, ) ) { backStackEntry -> - WeatherHourlyForecastScreen(backStackEntry, swipeFocusRequester) + WeatherHourlyForecastScreen( + backStackEntry, + swipeFocusRequester, + iconProvider = weather.iconProvider + ) } composable( route = Screen.Precipitation.route, ) { backStackEntry -> - WeatherMinutelyForecastScreen(backStackEntry, swipeFocusRequester) + WeatherMinutelyForecastScreen( + backStackEntry, + swipeFocusRequester, + iconProvider = weather.iconProvider + ) } composable( diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt index 24f3d818..b35f93f0 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/ui/weather/WeatherNowScreen.kt @@ -97,6 +97,7 @@ import com.thewizrd.shared_resources.utils.Units import com.thewizrd.shared_resources.utils.getColorFromTempF import com.thewizrd.shared_resources.weatherdata.model.Condition import com.thewizrd.shared_resources.weatherdata.model.Location +import com.thewizrd.shared_resources.weatherdata.model.Precipitation import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.simpleweather.BuildConfig import com.thewizrd.simpleweather.R @@ -666,14 +667,16 @@ private fun ConditionDetails( Row( modifier = Modifier.padding(4.dp) ) { - Icon( + WeatherIcon( modifier = Modifier .size(20.dp) .padding(end = 4.dp) .align(Alignment.CenterVertically), - painter = painterResource(id = sharedRes.drawable.wi_umbrella), + weatherIcon = WeatherIcons.UMBRELLA, + iconProvider = weather.iconProvider, tint = colorResource(sharedRes.color.colorPrimaryLight), - contentDescription = null + showAsMonochrome = true, + contentDescription = popData.label?.toString() ) Text( modifier = Modifier.align(Alignment.CenterVertically), @@ -692,15 +695,17 @@ private fun ConditionDetails( Row( modifier = Modifier.padding(4.dp) ) { - Icon( + WeatherIcon( modifier = Modifier .size(20.dp) .padding(end = 4.dp) .rotate(windData.iconRotation.toFloat()) .align(Alignment.CenterVertically), - painter = painterResource(id = sharedRes.drawable.wi_wind_direction), + weatherIcon = WeatherIcons.WIND_DIRECTION, + useDefaultIconProvider = true, tint = Color(0xFF20B2AA), - contentDescription = null + showAsMonochrome = true, + contentDescription = windData.label?.toString() ) Text( modifier = Modifier.align(Alignment.CenterVertically), @@ -1017,15 +1022,23 @@ private fun PreviewWeatherNowScreen() { } val weather = remember { Weather().apply { + location = Location().apply { + name = "New York" + } condition = Condition().apply { icon = WeatherIcons.DAY_SUNNY tempF = 70f weather = "Sunny" highF = 75f lowF = 60f + windMph = 4f + windKph = 6.43f + windGustKph = 9f + windGustKph = 14.5f + windDegrees = 0 } - location = Location().apply { - name = "New York" + precipitation = Precipitation().apply { + pop = 5 } }.toUiModel() } From 1421cc36f58ccec8110112a6a8d129b661f03f43 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sun, 28 Jun 2026 02:45:26 -0400 Subject: [PATCH 48/67] wearapp: update icon usage in complications --- .../complications/AQIComplicationService.kt | 121 +++++++++--- .../BeaufortComplicationService.kt | 165 +++++++++------- ...tionFeelsLikeWeatherComplicationService.kt | 118 +++++------- ...rrentLocationWeatherComplicationService.kt | 117 +++++------- .../DewPointComplicationService.kt | 94 ++++++--- .../FeelsLikeComplicationService.kt | 94 ++++++--- .../HumidityComplicationService.kt | 124 ++++++++---- .../PrecipitationComplicationService.kt | 124 ++++++++---- .../PressureComplicationService.kt | 124 ++++++++---- .../SunriseSunsetComplicationService.kt | 102 +++++++--- .../complications/UVComplicationService.kt | 126 ++++++++---- .../WeatherComplicationService.kt | 117 +++++------- .../WeatherHiLoComplicationService.kt | 104 +++++----- .../complications/WindComplicationService.kt | 179 +++++++++--------- 14 files changed, 1052 insertions(+), 657 deletions(-) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/AQIComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/AQIComplicationService.kt index 8859fa31..ff4c5892 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/AQIComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/AQIComplicationService.kt @@ -9,14 +9,19 @@ import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.RangedValueComplicationData import androidx.wear.watchface.complications.data.ShortTextComplicationData +import androidx.wear.watchface.complications.data.SmallImage +import androidx.wear.watchface.complications.data.SmallImageType import androidx.wear.watchface.complications.datasource.ComplicationRequest import com.thewizrd.common.controls.AirQualityViewModel +import com.thewizrd.common.utils.ImageUtils import com.thewizrd.common.weatherdata.WeatherDataLoader import com.thewizrd.common.weatherdata.WeatherRequest import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons +import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.AirQualityUtils.getIndexFromData import com.thewizrd.shared_resources.utils.Colors +import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride import com.thewizrd.shared_resources.weatherdata.model.AirQuality import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async @@ -37,7 +42,8 @@ class AQIComplicationService : BaseWeatherComplicationService() { ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT ) - private val complicationIconResId = sharedRes.drawable.wi_cloud + + private val complicationIcon = WeatherIcons.AIR_QUALITY override suspend fun onComplicationRequest(request: ComplicationRequest): ComplicationData { if (!supportedComplicationTypes.contains(request.complicationType)) { @@ -95,17 +101,33 @@ class AQIComplicationService : BaseWeatherComplicationService() { return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (type) { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( 57f, 0f, 301f, PlainComplicationText.Builder("Air Quality: 57, Moderate").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setText( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setText( PlainComplicationText.Builder("57").build() ).setValueType( RangedValueComplicationData.TYPE_RATING @@ -116,11 +138,16 @@ class AQIComplicationService : BaseWeatherComplicationService() { PlainComplicationText.Builder("57").build(), PlainComplicationText.Builder("Air Quality: 57, Moderate").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( @@ -129,11 +156,16 @@ class AQIComplicationService : BaseWeatherComplicationService() { ).setTitle( PlainComplicationText.Builder("57, Moderate").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } else -> { null @@ -146,6 +178,8 @@ class AQIComplicationService : BaseWeatherComplicationService() { return null } + val wim = sharedDeps.weatherIconsManager + val aqiModel = aqi?.apply { if (index == null) index = getIndexFromData() } ?.takeIf { it.index != null }?.let { AirQualityViewModel(it) } val aqiStr = aqiModel?.let { "${it.index}, ${it.level}" } ?: WeatherIcons.EM_DASH @@ -153,6 +187,16 @@ class AQIComplicationService : BaseWeatherComplicationService() { val aqiProgress = aqiModel?.progress?.toFloat() ?: 0f val aqiProgressMax = aqiModel?.let { max(it.progressMax, it.progress).toFloat() } ?: 301f + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (dataType) { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( @@ -161,11 +205,16 @@ class AQIComplicationService : BaseWeatherComplicationService() { "${getString(sharedRes.string.label_airquality_short)}: $aqiStr" ).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setText( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setText( PlainComplicationText.Builder(aqiShortStr).build() ).setTapAction( getTapIntent(this) @@ -180,11 +229,16 @@ class AQIComplicationService : BaseWeatherComplicationService() { "${getString(sharedRes.string.label_airquality_short)}: $aqiStr" ).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } @@ -198,11 +252,16 @@ class AQIComplicationService : BaseWeatherComplicationService() { ).setTitle( PlainComplicationText.Builder(aqiStr).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/BeaufortComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/BeaufortComplicationService.kt index 83806f89..61f60a9b 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/BeaufortComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/BeaufortComplicationService.kt @@ -15,9 +15,7 @@ import androidx.wear.watchface.complications.data.SmallImageComplicationData import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.controls.BeaufortViewModel import com.thewizrd.common.utils.ImageUtils -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.icons.WeatherIcons -import com.thewizrd.shared_resources.icons.WeatherIconsEFProvider import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride @@ -25,7 +23,7 @@ import com.thewizrd.shared_resources.utils.getBeaufortScale import com.thewizrd.shared_resources.weatherdata.model.Beaufort import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R +import com.thewizrd.shared_resources.R as sharedRes class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { companion object { @@ -40,24 +38,41 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.MONOCHROMATIC_IMAGE, ComplicationType.SMALL_IMAGE ) - private val complicationIconResId = sharedRes.drawable.wi_strong_wind override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val complicationIcon = WeatherIcons.WIND_BEAUFORT_3 + + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (type) { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( 3f, 0f, 12f, PlainComplicationText.Builder("Beaufort: 3, Gentle Breeze").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setText( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setText( PlainComplicationText.Builder("3").build() ).setValueType( RangedValueComplicationData.TYPE_RATING @@ -68,11 +83,16 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { PlainComplicationText.Builder("3").build(), PlainComplicationText.Builder("Beaufort: 3, Gentle Breeze").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( @@ -81,35 +101,28 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { ).setTitle( PlainComplicationText.Builder("3, Gentle Breeze").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } ComplicationType.MONOCHROMATIC_IMAGE -> { MonochromaticImageComplicationData.Builder( - MonochromaticImage.Builder( - Icon.createWithResource(this, sharedRes.drawable.wi_wind_beaufort_3) - .setTint(Colors.WHITESMOKE) - ).build(), + MonochromaticImage.Builder(monochromaticIcon).build(), PlainComplicationText.Builder("Beaufort: 3, Gentle Breeze").build() ).build() } ComplicationType.SMALL_IMAGE -> { SmallImageComplicationData.Builder( - SmallImage.Builder( - Icon.createWithBitmap( - ImageUtils.bitmapFromDrawable( - getThemeContextOverride(false), - sharedRes.drawable.wi_wind_beaufort_3 - ) - ), - SmallImageType.ICON - ).setAmbientImage( - Icon.createWithResource(this, sharedRes.drawable.wi_wind_beaufort_3) - .setTint(Colors.WHITESMOKE) - ).build(), + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), PlainComplicationText.Builder("Beaufort: 3, Gentle Breeze").build() ).build() } @@ -134,7 +147,6 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { val beaufortModel = beaufort?.let { BeaufortViewModel(it) } val wim = sharedDeps.weatherIconsManager - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) val contentDescription = PlainComplicationText.Builder( beaufortModel?.let { "${beaufortModel.beaufort.label}: ${beaufortModel.progress}, ${beaufortModel.beaufort.value}" } @@ -146,6 +158,16 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { ?: WeatherIcons.EM_DASH val beaufortIcon = beaufortModel?.beaufort?.icon ?: WeatherIcons.WIND_BEAUFORT_0 + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(beaufortIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(beaufortIcon) + ) + ) + return when (dataType) { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( @@ -154,11 +176,16 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { beaufortModel?.progressMax?.toFloat() ?: 1f, contentDescription ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setText( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), + ) + } + }.setText( PlainComplicationText.Builder(progressShortStr).build() ).setTapAction( getTapIntent(this) @@ -171,11 +198,16 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { PlainComplicationText.Builder(progressShortStr).build(), contentDescription ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), + ) + } + }.setTapAction( getTapIntent(this) ).build() } @@ -189,23 +221,22 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { progressStr ).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), + ) + } + }.setTapAction( getTapIntent(this) ).build() } ComplicationType.MONOCHROMATIC_IMAGE -> { MonochromaticImageComplicationData.Builder( - MonochromaticImage.Builder( - Icon.createWithResource( - this, - wip.getWeatherIconResource(beaufortIcon) - ) - .setTint(Colors.WHITESMOKE) - ).build(), + MonochromaticImage.Builder(monochromaticIcon).build(), contentDescription ).setTapAction( getTapIntent(this) @@ -213,21 +244,9 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { } ComplicationType.SMALL_IMAGE -> { SmallImageComplicationData.Builder( - SmallImage.Builder( - Icon.createWithBitmap( - ImageUtils.bitmapFromDrawable( - getThemeContextOverride(false), - wim.getWeatherIconResource(beaufortIcon) - ) - ), - SmallImageType.ICON - ).setAmbientImage( - Icon.createWithResource( - this, - wip.getWeatherIconResource(beaufortIcon) - ) - .setTint(Colors.WHITESMOKE) - ).build(), + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), contentDescription ).setTapAction( getTapIntent(this) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationFeelsLikeWeatherComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationFeelsLikeWeatherComplicationService.kt index d779ca1f..2b36bcf1 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationFeelsLikeWeatherComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationFeelsLikeWeatherComplicationService.kt @@ -13,10 +13,8 @@ import androidx.wear.watchface.complications.data.SmallImage import androidx.wear.watchface.complications.data.SmallImageComplicationData import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.utils.ImageUtils -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons -import com.thewizrd.shared_resources.icons.WeatherIconsEFProvider import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride @@ -24,9 +22,9 @@ import com.thewizrd.shared_resources.utils.LocaleUtils import com.thewizrd.shared_resources.utils.Units import com.thewizrd.shared_resources.weatherdata.model.Forecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R import com.thewizrd.weather_api.weatherModule import kotlin.math.roundToInt +import com.thewizrd.shared_resources.R as sharedRes class CurrentLocationFeelsLikeWeatherComplicationService : WeatherForecastComplicationService() { companion object { @@ -40,24 +38,39 @@ class CurrentLocationFeelsLikeWeatherComplicationService : WeatherForecastCompli ComplicationType.MONOCHROMATIC_IMAGE, ComplicationType.SMALL_IMAGE ) - private val complicationIconResId = sharedRes.drawable.wi_day_sunny override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val complicationIcon = WeatherIcons.DAY_SUNNY + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (type) { ComplicationType.SHORT_TEXT -> { ShortTextComplicationData.Builder( PlainComplicationText.Builder("70°").build(), PlainComplicationText.Builder("70° - Sunny").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon).build(), + ) + } + }.build() } ComplicationType.LONG_TEXT -> { @@ -67,30 +80,30 @@ class CurrentLocationFeelsLikeWeatherComplicationService : WeatherForecastCompli ).setTitle( PlainComplicationText.Builder("70°").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), + ) + } + }.build() } ComplicationType.MONOCHROMATIC_IMAGE -> { MonochromaticImageComplicationData.Builder( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build(), + MonochromaticImage.Builder(monochromaticIcon).build(), PlainComplicationText.Builder("70° - Sunny").build() ).build() } ComplicationType.SMALL_IMAGE -> { SmallImageComplicationData.Builder( - SmallImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE), - SmallImageType.ICON - ).build(), + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), PlainComplicationText.Builder("70° - Sunny").build() ).build() } @@ -145,6 +158,8 @@ class CurrentLocationFeelsLikeWeatherComplicationService : WeatherForecastCompli val wim = sharedDeps.weatherIconsManager val weatherIcon = wim.getWeatherIconResource(weather.condition!!.icon) + val monochromaticIcon = Icon.createWithResource(this, weatherIcon) + .setTint(Colors.WHITESMOKE) val icon = Icon.createWithBitmap( ImageUtils.bitmapFromDrawable( getThemeContextOverride(false), @@ -167,21 +182,20 @@ class CurrentLocationFeelsLikeWeatherComplicationService : WeatherForecastCompli MonochromaticImage.Builder(icon).apply { // Weather Icon if (!wim.isFontIcon) { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) - setAmbientImage( - Icon.createWithBitmap( - ImageUtils.tintedBitmapFromDrawable( - this@CurrentLocationFeelsLikeWeatherComplicationService, - wip.getWeatherIconResource(weather.condition!!.icon), - Colors.WHITE - ) - ) - ) + setAmbientImage(monochromaticIcon) } } .build() ) + if (!wim.isFontIcon) { + builder.setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + builder.setTapAction(getTapIntent(this)) return builder.build() } @@ -200,18 +214,9 @@ class CurrentLocationFeelsLikeWeatherComplicationService : WeatherForecastCompli MonochromaticImage.Builder(icon).build() ) } else { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) builder.setSmallImage( SmallImage.Builder(icon, SmallImageType.ICON) - .setAmbientImage( - Icon.createWithBitmap( - ImageUtils.tintedBitmapFromDrawable( - this, - wip.getWeatherIconResource(weather.condition!!.icon), - Colors.WHITE - ) - ) - ) + .setAmbientImage(monochromaticIcon) .build() ) } @@ -221,16 +226,8 @@ class CurrentLocationFeelsLikeWeatherComplicationService : WeatherForecastCompli } ComplicationType.MONOCHROMATIC_IMAGE -> { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) - return MonochromaticImageComplicationData.Builder( - MonochromaticImage.Builder( - Icon.createWithResource( - this, - wip.getWeatherIconResource(weather.condition!!.icon) - ) - .setTint(Colors.WHITESMOKE) - ).build(), + MonochromaticImage.Builder(monochromaticIcon).build(), contentDescription ).setTapAction( getTapIntent(this) @@ -238,21 +235,10 @@ class CurrentLocationFeelsLikeWeatherComplicationService : WeatherForecastCompli } ComplicationType.SMALL_IMAGE -> { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) - return SmallImageComplicationData.Builder( - SmallImage.Builder( - icon, - SmallImageType.ICON - ).setAmbientImage( - Icon.createWithBitmap( - ImageUtils.tintedBitmapFromDrawable( - this, - wip.getWeatherIconResource(weather.condition!!.icon), - Colors.WHITE - ) - ) - ).build(), + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), contentDescription ).setTapAction( getTapIntent(this) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationWeatherComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationWeatherComplicationService.kt index 1ba4c1e0..f300262c 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationWeatherComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/CurrentLocationWeatherComplicationService.kt @@ -13,10 +13,8 @@ import androidx.wear.watchface.complications.data.SmallImage import androidx.wear.watchface.complications.data.SmallImageComplicationData import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.utils.ImageUtils -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons -import com.thewizrd.shared_resources.icons.WeatherIconsEFProvider import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride @@ -24,7 +22,6 @@ import com.thewizrd.shared_resources.utils.LocaleUtils import com.thewizrd.shared_resources.utils.Units import com.thewizrd.shared_resources.weatherdata.model.Forecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R import com.thewizrd.weather_api.weatherModule class CurrentLocationWeatherComplicationService : WeatherForecastComplicationService() { @@ -39,24 +36,39 @@ class CurrentLocationWeatherComplicationService : WeatherForecastComplicationSer ComplicationType.MONOCHROMATIC_IMAGE, ComplicationType.SMALL_IMAGE ) - private val complicationIconResId = sharedRes.drawable.wi_day_sunny override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val complicationIcon = WeatherIcons.DAY_SUNNY + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (type) { ComplicationType.SHORT_TEXT -> { ShortTextComplicationData.Builder( PlainComplicationText.Builder("70°").build(), PlainComplicationText.Builder("70° - Sunny").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon).build(), + ) + } + }.build() } ComplicationType.LONG_TEXT -> { @@ -66,30 +78,30 @@ class CurrentLocationWeatherComplicationService : WeatherForecastComplicationSer ).setTitle( PlainComplicationText.Builder("70°").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), + ) + } + }.build() } ComplicationType.MONOCHROMATIC_IMAGE -> { MonochromaticImageComplicationData.Builder( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build(), + MonochromaticImage.Builder(monochromaticIcon).build(), PlainComplicationText.Builder("70° - Sunny").build() ).build() } ComplicationType.SMALL_IMAGE -> { SmallImageComplicationData.Builder( - SmallImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE), - SmallImageType.ICON - ).build(), + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), PlainComplicationText.Builder("70° - Sunny").build() ).build() } @@ -135,6 +147,8 @@ class CurrentLocationWeatherComplicationService : WeatherForecastComplicationSer val wim = sharedDeps.weatherIconsManager val weatherIcon = wim.getWeatherIconResource(weather.condition!!.icon) + val monochromaticIcon = Icon.createWithResource(this, weatherIcon) + .setTint(Colors.WHITESMOKE) val icon = Icon.createWithBitmap( ImageUtils.bitmapFromDrawable( getThemeContextOverride(false), @@ -155,21 +169,20 @@ class CurrentLocationWeatherComplicationService : WeatherForecastComplicationSer MonochromaticImage.Builder(icon).apply { // Weather Icon if (!wim.isFontIcon) { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) - setAmbientImage( - Icon.createWithBitmap( - ImageUtils.tintedBitmapFromDrawable( - this@CurrentLocationWeatherComplicationService, - wip.getWeatherIconResource(weather.condition!!.icon), - Colors.WHITE - ) - ) - ) + setAmbientImage(monochromaticIcon) } } .build() ) + if (!wim.isFontIcon) { + builder.setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + builder.setTapAction(getTapIntent(this)) return builder.build() } @@ -190,18 +203,9 @@ class CurrentLocationWeatherComplicationService : WeatherForecastComplicationSer MonochromaticImage.Builder(icon).build() ) } else { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) builder.setSmallImage( SmallImage.Builder(icon, SmallImageType.ICON) - .setAmbientImage( - Icon.createWithBitmap( - ImageUtils.tintedBitmapFromDrawable( - this, - wip.getWeatherIconResource(weather.condition!!.icon), - Colors.WHITE - ) - ) - ) + .setAmbientImage(monochromaticIcon) .build() ) } @@ -211,16 +215,8 @@ class CurrentLocationWeatherComplicationService : WeatherForecastComplicationSer } ComplicationType.MONOCHROMATIC_IMAGE -> { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) - return MonochromaticImageComplicationData.Builder( - MonochromaticImage.Builder( - Icon.createWithResource( - this, - wip.getWeatherIconResource(weather.condition!!.icon) - ) - .setTint(Colors.WHITESMOKE) - ).build(), + MonochromaticImage.Builder(monochromaticIcon).build(), contentDescription ).setTapAction( getTapIntent(this) @@ -228,21 +224,10 @@ class CurrentLocationWeatherComplicationService : WeatherForecastComplicationSer } ComplicationType.SMALL_IMAGE -> { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) - return SmallImageComplicationData.Builder( - SmallImage.Builder( - icon, - SmallImageType.ICON - ).setAmbientImage( - Icon.createWithBitmap( - ImageUtils.tintedBitmapFromDrawable( - this, - wip.getWeatherIconResource(weather.condition!!.icon), - Colors.WHITE - ) - ) - ).build(), + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), contentDescription ).setTapAction( getTapIntent(this) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/DewPointComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/DewPointComplicationService.kt index ef3eba04..6365496e 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/DewPointComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/DewPointComplicationService.kt @@ -8,15 +8,19 @@ import androidx.wear.watchface.complications.data.MonochromaticImage import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.ShortTextComplicationData -import com.thewizrd.shared_resources.R as sharedRes +import androidx.wear.watchface.complications.data.SmallImage +import androidx.wear.watchface.complications.data.SmallImageType +import com.thewizrd.common.utils.ImageUtils import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons +import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors +import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride import com.thewizrd.shared_resources.utils.Units import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R import kotlin.math.roundToInt +import com.thewizrd.shared_resources.R as sharedRes class DewPointComplicationService : WeatherHourlyForecastComplicationService() { companion object { @@ -25,24 +29,41 @@ class DewPointComplicationService : WeatherHourlyForecastComplicationService() { override val supportedComplicationTypes = setOf(ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT) - private val complicationIconResId = sharedRes.drawable.wi_thermometer + + private val complicationIcon = WeatherIcons.THERMOMETER override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (type) { ComplicationType.SHORT_TEXT -> { ShortTextComplicationData.Builder( PlainComplicationText.Builder("38°").build(), PlainComplicationText.Builder("Dew Point: 38°").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( @@ -52,11 +73,16 @@ class DewPointComplicationService : WeatherHourlyForecastComplicationService() { ).setTitle( PlainComplicationText.Builder("38°").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } else -> { null @@ -73,6 +99,8 @@ class DewPointComplicationService : WeatherHourlyForecastComplicationService() { return null } + val wim = sharedDeps.weatherIconsManager + val dewPointF = weather.atmosphere?.dewpointF ?: hourlyForecast?.extras?.dewpointF val dewPointC = weather.atmosphere?.dewpointC ?: hourlyForecast?.extras?.dewpointC @@ -85,6 +113,16 @@ class DewPointComplicationService : WeatherHourlyForecastComplicationService() { String.format("$tempVal°$tempUnit") } + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (dataType) { ComplicationType.SHORT_TEXT -> { ShortTextComplicationData.Builder( @@ -93,11 +131,16 @@ class DewPointComplicationService : WeatherHourlyForecastComplicationService() { String.format("%s: %s", getString(sharedRes.string.label_dewpoint), tempStr) ).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } @@ -111,11 +154,16 @@ class DewPointComplicationService : WeatherHourlyForecastComplicationService() { ).setTitle( PlainComplicationText.Builder(tempStr).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/FeelsLikeComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/FeelsLikeComplicationService.kt index c6ebae07..5039bebf 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/FeelsLikeComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/FeelsLikeComplicationService.kt @@ -8,15 +8,19 @@ import androidx.wear.watchface.complications.data.MonochromaticImage import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.ShortTextComplicationData -import com.thewizrd.shared_resources.R as sharedRes +import androidx.wear.watchface.complications.data.SmallImage +import androidx.wear.watchface.complications.data.SmallImageType +import com.thewizrd.common.utils.ImageUtils import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons +import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors +import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride import com.thewizrd.shared_resources.utils.Units import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R import kotlin.math.roundToInt +import com.thewizrd.shared_resources.R as sharedRes class FeelsLikeComplicationService : WeatherHourlyForecastComplicationService() { companion object { @@ -25,24 +29,41 @@ class FeelsLikeComplicationService : WeatherHourlyForecastComplicationService() override val supportedComplicationTypes = setOf(ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT) - private val complicationIconResId = sharedRes.drawable.wi_thermometer + + private val complicationIcon = WeatherIcons.THERMOMETER override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (type) { ComplicationType.SHORT_TEXT -> { ShortTextComplicationData.Builder( PlainComplicationText.Builder("75°").build(), PlainComplicationText.Builder("Feels like: 75°").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( @@ -52,11 +73,16 @@ class FeelsLikeComplicationService : WeatherHourlyForecastComplicationService() ).setTitle( PlainComplicationText.Builder("75°").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } else -> { null @@ -73,6 +99,8 @@ class FeelsLikeComplicationService : WeatherHourlyForecastComplicationService() return null } + val wim = sharedDeps.weatherIconsManager + val feelsLikeF = weather.condition?.feelslikeF ?: hourlyForecast?.extras?.feelslikeF val feelsLikeC = weather.condition?.feelslikeC ?: hourlyForecast?.extras?.feelslikeC @@ -85,6 +113,16 @@ class FeelsLikeComplicationService : WeatherHourlyForecastComplicationService() String.format("$tempVal°$tempUnit") } + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (dataType) { ComplicationType.SHORT_TEXT -> { ShortTextComplicationData.Builder( @@ -97,11 +135,16 @@ class FeelsLikeComplicationService : WeatherHourlyForecastComplicationService() ) ).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } @@ -119,11 +162,16 @@ class FeelsLikeComplicationService : WeatherHourlyForecastComplicationService() ).setTitle( PlainComplicationText.Builder(tempStr).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/HumidityComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/HumidityComplicationService.kt index 9c8f1198..4ecbc0fa 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/HumidityComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/HumidityComplicationService.kt @@ -9,12 +9,16 @@ import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.RangedValueComplicationData import androidx.wear.watchface.complications.data.ShortTextComplicationData -import com.thewizrd.shared_resources.R as sharedRes +import androidx.wear.watchface.complications.data.SmallImage +import androidx.wear.watchface.complications.data.SmallImageType +import com.thewizrd.common.utils.ImageUtils import com.thewizrd.shared_resources.icons.WeatherIcons +import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors +import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R +import com.thewizrd.shared_resources.R as sharedRes class HumidityComplicationService : WeatherHourlyForecastComplicationService() { companion object { @@ -27,13 +31,25 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT ) - private val complicationIconResId = sharedRes.drawable.wi_humidity + + private val complicationIcon = WeatherIcons.HUMIDITY override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (type) { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( @@ -41,11 +57,16 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { PlainComplicationText.Builder("${getString(sharedRes.string.label_humidity)}: 75%") .build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setText( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setText( PlainComplicationText.Builder("75%").build() ).setValueType( RangedValueComplicationData.TYPE_PERCENTAGE @@ -57,11 +78,16 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { PlainComplicationText.Builder("${getString(sharedRes.string.label_humidity)}: 75%") .build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( @@ -72,11 +98,16 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { ).setTitle( PlainComplicationText.Builder("75%").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } else -> { null @@ -93,9 +124,21 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { return null } + val wim = sharedDeps.weatherIconsManager + val humidityPct = weather.atmosphere?.humidity ?: hourlyForecast?.extras?.humidity val humidityStr = humidityPct?.let { "${it}%" } ?: WeatherIcons.EM_DASH + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (dataType) { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( @@ -104,11 +147,16 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { "${getString(sharedRes.string.label_humidity)}: $humidityStr" ).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setText( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setText( PlainComplicationText.Builder(humidityStr).build() ).setValueType( RangedValueComplicationData.TYPE_PERCENTAGE @@ -123,11 +171,16 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { "${getString(sharedRes.string.label_humidity)}: $humidityStr" ).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } @@ -141,11 +194,16 @@ class HumidityComplicationService : WeatherHourlyForecastComplicationService() { ).setTitle( PlainComplicationText.Builder(humidityStr).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PrecipitationComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PrecipitationComplicationService.kt index 6a0259c3..50ea1b5d 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PrecipitationComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PrecipitationComplicationService.kt @@ -9,12 +9,16 @@ import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.RangedValueComplicationData import androidx.wear.watchface.complications.data.ShortTextComplicationData -import com.thewizrd.shared_resources.R as sharedRes +import androidx.wear.watchface.complications.data.SmallImage +import androidx.wear.watchface.complications.data.SmallImageType +import com.thewizrd.common.utils.ImageUtils import com.thewizrd.shared_resources.icons.WeatherIcons +import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors +import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R +import com.thewizrd.shared_resources.R as sharedRes class PrecipitationComplicationService : WeatherHourlyForecastComplicationService() { companion object { @@ -27,24 +31,41 @@ class PrecipitationComplicationService : WeatherHourlyForecastComplicationServic ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT ) - private val complicationIconResId = sharedRes.drawable.wi_umbrella + + private val complicationIcon = WeatherIcons.UMBRELLA override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (type) { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( 50f, 0f, 100f, PlainComplicationText.Builder("Chance: 50%").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setText( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setText( PlainComplicationText.Builder("50%").build() ).setValueType( RangedValueComplicationData.TYPE_PERCENTAGE @@ -55,11 +76,16 @@ class PrecipitationComplicationService : WeatherHourlyForecastComplicationServic PlainComplicationText.Builder("50%").build(), PlainComplicationText.Builder("Chance: 50%").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( @@ -68,11 +94,16 @@ class PrecipitationComplicationService : WeatherHourlyForecastComplicationServic ).setTitle( PlainComplicationText.Builder("50%").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } else -> { null @@ -89,20 +120,37 @@ class PrecipitationComplicationService : WeatherHourlyForecastComplicationServic return null } + val wim = sharedDeps.weatherIconsManager + val popChance = weather.precipitation?.pop ?: hourlyForecast?.extras?.pop val popChanceStr = popChance?.let { "${it}%" } ?: WeatherIcons.EM_DASH + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (dataType) { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( popChance?.toFloat() ?: 0f, 0f, 100f, PlainComplicationText.Builder(getString(sharedRes.string.label_chance)).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setText( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setText( PlainComplicationText.Builder(popChanceStr).build() ).setValueType( RangedValueComplicationData.TYPE_PERCENTAGE @@ -117,11 +165,16 @@ class PrecipitationComplicationService : WeatherHourlyForecastComplicationServic "${getString(sharedRes.string.label_chance)}: $popChanceStr" ).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } @@ -134,11 +187,16 @@ class PrecipitationComplicationService : WeatherHourlyForecastComplicationServic ).setTitle( PlainComplicationText.Builder(popChanceStr).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PressureComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PressureComplicationService.kt index 8191b65a..92675ed2 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PressureComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PressureComplicationService.kt @@ -9,17 +9,21 @@ import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.RangedValueComplicationData import androidx.wear.watchface.complications.data.ShortTextComplicationData -import com.thewizrd.shared_resources.R as sharedRes +import androidx.wear.watchface.complications.data.SmallImage +import androidx.wear.watchface.complications.data.SmallImageType +import com.thewizrd.common.utils.ImageUtils import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons +import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors +import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride import com.thewizrd.shared_resources.utils.ConversionMethods import com.thewizrd.shared_resources.utils.LocaleUtils import com.thewizrd.shared_resources.utils.Units import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R import java.text.DecimalFormat +import com.thewizrd.shared_resources.R as sharedRes class PressureComplicationService : WeatherHourlyForecastComplicationService() { companion object { @@ -32,24 +36,41 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT ) - private val complicationIconResId = sharedRes.drawable.wi_barometer + + private val complicationIcon = WeatherIcons.BAROMETER override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (type) { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( 30.3f, 26f, 32f, PlainComplicationText.Builder("Pressure: 30.3 inHg").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setText( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setText( PlainComplicationText.Builder("30.3 in").build() ).build() } @@ -59,11 +80,16 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { PlainComplicationText.Builder("30.3 in").build(), PlainComplicationText.Builder("Pressure: 30.3 inHg").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } ComplicationType.LONG_TEXT -> { @@ -74,11 +100,16 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { ).setTitle( PlainComplicationText.Builder("30.3 inHg").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } else -> { @@ -149,6 +180,18 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { dataType: ComplicationType, pressureStr: String? = null, pressureStrShort: String? = null, pressureVal: Float? = null ): ComplicationData? { + val wim = sharedDeps.weatherIconsManager + + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (dataType) { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( @@ -161,11 +204,16 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { ) ).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setText( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setText( PlainComplicationText.Builder(pressureStrShort ?: WeatherIcons.EM_DASH) .build() ).setTapAction( @@ -185,11 +233,16 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { ) ).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } @@ -208,11 +261,16 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { ).setTitle( PlainComplicationText.Builder(pressureStr ?: WeatherIcons.EM_DASH).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/SunriseSunsetComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/SunriseSunsetComplicationService.kt index 660e9903..d1a7c6ce 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/SunriseSunsetComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/SunriseSunsetComplicationService.kt @@ -9,16 +9,20 @@ import androidx.wear.watchface.complications.data.MonochromaticImage import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.ShortTextComplicationData -import com.thewizrd.shared_resources.R as sharedRes +import androidx.wear.watchface.complications.data.SmallImage +import androidx.wear.watchface.complications.data.SmallImageType +import com.thewizrd.common.utils.ImageUtils import com.thewizrd.shared_resources.DateTimeConstants import com.thewizrd.shared_resources.icons.WeatherIcons +import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors +import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride import com.thewizrd.shared_resources.utils.DateTimeUtils import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R import java.time.LocalDateTime import java.time.ZonedDateTime +import com.thewizrd.shared_resources.R as sharedRes class SunriseSunsetComplicationService : WeatherHourlyForecastComplicationService() { companion object { @@ -33,17 +37,34 @@ class SunriseSunsetComplicationService : WeatherHourlyForecastComplicationServic return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val complicationIcon = WeatherIcons.SUNSET + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (type) { ComplicationType.SHORT_TEXT -> { ShortTextComplicationData.Builder( PlainComplicationText.Builder("6:05 PM").build(), PlainComplicationText.Builder("Sunset: 6:05 PM").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, sharedRes.drawable.wi_sunset) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } ComplicationType.LONG_TEXT -> { @@ -53,11 +74,16 @@ class SunriseSunsetComplicationService : WeatherHourlyForecastComplicationServic ).setTitle( PlainComplicationText.Builder("6:05 PM").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, sharedRes.drawable.wi_sunset) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } else -> { @@ -75,6 +101,8 @@ class SunriseSunsetComplicationService : WeatherHourlyForecastComplicationServic return null } + val wim = sharedDeps.weatherIconsManager + val sunrise = weather.astronomy?.sunrise val sunset = weather.astronomy?.sunset @@ -92,40 +120,55 @@ class SunriseSunsetComplicationService : WeatherHourlyForecastComplicationServic } val text: String - val complicationIconResId: Int + val complicationIcon: String val desc: String if (sunset != null && sunrise != null) { if (now.toLocalTime() > sunrise.toLocalTime()) { text = sunset.format(fmt) - complicationIconResId = sharedRes.drawable.wi_sunset + complicationIcon = WeatherIcons.SUNSET desc = getString(sharedRes.string.label_sunset) } else { text = sunrise.format(fmt) - complicationIconResId = sharedRes.drawable.wi_sunrise + complicationIcon = WeatherIcons.SUNRISE desc = getString(sharedRes.string.label_sunrise) } } else if (sunset != null) { text = sunset.format(fmt) - complicationIconResId = sharedRes.drawable.wi_sunset + complicationIcon = WeatherIcons.SUNSET desc = getString(sharedRes.string.label_sunset) } else { text = sunrise?.format(fmt) ?: WeatherIcons.EM_DASH - complicationIconResId = sharedRes.drawable.wi_sunrise + complicationIcon = WeatherIcons.SUNRISE desc = getString(sharedRes.string.label_sunrise) } + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (dataType) { ComplicationType.SHORT_TEXT -> { ShortTextComplicationData.Builder( PlainComplicationText.Builder(text).build(), PlainComplicationText.Builder("$desc: $text").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } @@ -137,11 +180,16 @@ class SunriseSunsetComplicationService : WeatherHourlyForecastComplicationServic ).setTitle( PlainComplicationText.Builder(text).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setTapAction( getTapIntent(this) ).build() } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/UVComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/UVComplicationService.kt index 0f829a5c..0cec8c3b 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/UVComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/UVComplicationService.kt @@ -9,15 +9,20 @@ import androidx.wear.watchface.complications.data.NoDataComplicationData import androidx.wear.watchface.complications.data.PlainComplicationText import androidx.wear.watchface.complications.data.RangedValueComplicationData import androidx.wear.watchface.complications.data.ShortTextComplicationData +import androidx.wear.watchface.complications.data.SmallImage +import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.controls.UVIndexViewModel -import com.thewizrd.shared_resources.R as sharedRes +import com.thewizrd.common.utils.ImageUtils import com.thewizrd.shared_resources.icons.WeatherIcons +import com.thewizrd.shared_resources.icons.WeatherIconsEFProvider +import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors +import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.UV import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R import kotlin.math.max +import com.thewizrd.shared_resources.R as sharedRes class UVComplicationService : WeatherHourlyForecastComplicationService() { companion object { @@ -30,24 +35,42 @@ class UVComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.SHORT_TEXT, ComplicationType.LONG_TEXT ) - private val complicationIconResId = sharedRes.drawable.wi_day_sunny override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) + val complicationIcon = WeatherIcons.UV_INDEX_3 + + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (type) { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( 3f, 0f, 11f, PlainComplicationText.Builder("UV Index: 3, Moderate").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setText( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.setText( PlainComplicationText.Builder("3").build() ).setTitle( PlainComplicationText.Builder("UV").build() @@ -60,11 +83,16 @@ class UVComplicationService : WeatherHourlyForecastComplicationService() { PlainComplicationText.Builder("3").build(), PlainComplicationText.Builder("UV Index: 3, Moderate").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( @@ -73,11 +101,16 @@ class UVComplicationService : WeatherHourlyForecastComplicationService() { ).setTitle( PlainComplicationText.Builder("3, Moderate").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } else -> { null @@ -94,6 +127,8 @@ class UVComplicationService : WeatherHourlyForecastComplicationService() { return null } + val wim = sharedDeps.weatherIconsManager + val uvIndex = weather.condition?.uv?.index ?: hourlyForecast?.extras?.uvIndex val uvModel = uvIndex?.let { UVIndexViewModel(UV(it)) } val uvStr = @@ -102,6 +137,16 @@ class UVComplicationService : WeatherHourlyForecastComplicationService() { val uvProgress = uvModel?.progress?.toFloat() ?: 0f val uvProgressMax = uvModel?.let { max(it.progressMax, it.progress).toFloat() } ?: 11f val contentDescription = "${getString(sharedRes.string.label_uv)}: $uvStr" + val uvIcon = uvModel?.icon ?: WeatherIcons.UV_INDEX + + val monochromaticIcon = Icon.createWithResource(this, wim.getWeatherIconResource(uvIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(uvIcon) + ) + ) return when (dataType) { ComplicationType.RANGED_VALUE -> { @@ -111,11 +156,16 @@ class UVComplicationService : WeatherHourlyForecastComplicationService() { contentDescription ).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setText( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), + ) + } + }.setText( PlainComplicationText.Builder(uvIdxStr).build() ).setTitle( PlainComplicationText.Builder("UV").build() @@ -132,11 +182,16 @@ class UVComplicationService : WeatherHourlyForecastComplicationService() { contentDescription ).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), + ) + } + }.setTapAction( getTapIntent(this) ).build() } @@ -149,11 +204,16 @@ class UVComplicationService : WeatherHourlyForecastComplicationService() { ).setTitle( PlainComplicationText.Builder(uvStr).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), + ) + } + }.setTapAction( getTapIntent(this) ).build() } diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherComplicationService.kt index 0d5cd26c..3e3f7aa0 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherComplicationService.kt @@ -13,10 +13,8 @@ import androidx.wear.watchface.complications.data.SmallImage import androidx.wear.watchface.complications.data.SmallImageComplicationData import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.utils.ImageUtils -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons -import com.thewizrd.shared_resources.icons.WeatherIconsEFProvider import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride @@ -24,8 +22,8 @@ import com.thewizrd.shared_resources.utils.LocaleUtils import com.thewizrd.shared_resources.utils.Units import com.thewizrd.shared_resources.weatherdata.model.Forecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R import com.thewizrd.weather_api.weatherModule +import com.thewizrd.shared_resources.R as sharedRes class WeatherComplicationService : WeatherForecastComplicationService() { companion object { @@ -39,24 +37,39 @@ class WeatherComplicationService : WeatherForecastComplicationService() { ComplicationType.MONOCHROMATIC_IMAGE, ComplicationType.SMALL_IMAGE ) - private val complicationIconResId = sharedRes.drawable.wi_day_sunny override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val complicationIcon = WeatherIcons.DAY_SUNNY + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (type) { ComplicationType.SHORT_TEXT -> { ShortTextComplicationData.Builder( PlainComplicationText.Builder("70°").build(), PlainComplicationText.Builder("70° - Sunny").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon).build(), + ) + } + }.build() } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( @@ -65,28 +78,27 @@ class WeatherComplicationService : WeatherForecastComplicationService() { ).setTitle( PlainComplicationText.Builder("70°").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon).build(), + ) + } + }.build() } ComplicationType.MONOCHROMATIC_IMAGE -> { MonochromaticImageComplicationData.Builder( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build(), + MonochromaticImage.Builder(monochromaticIcon).build(), PlainComplicationText.Builder("70° - Sunny").build() ).build() } ComplicationType.SMALL_IMAGE -> { SmallImageComplicationData.Builder( - SmallImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE), - SmallImageType.ICON - ).build(), + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), PlainComplicationText.Builder("70° - Sunny").build() ).build() } @@ -131,6 +143,8 @@ class WeatherComplicationService : WeatherForecastComplicationService() { val wim = sharedDeps.weatherIconsManager val weatherIcon = wim.getWeatherIconResource(weather.condition!!.icon) + val monochromaticIcon = Icon.createWithResource(this, weatherIcon) + .setTint(Colors.WHITESMOKE) val icon = Icon.createWithBitmap( ImageUtils.bitmapFromDrawable( getThemeContextOverride(false), @@ -151,21 +165,20 @@ class WeatherComplicationService : WeatherForecastComplicationService() { MonochromaticImage.Builder(icon).apply { // Weather Icon if (!wim.isFontIcon) { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) - setAmbientImage( - Icon.createWithBitmap( - ImageUtils.tintedBitmapFromDrawable( - this@WeatherComplicationService, - wip.getWeatherIconResource(weather.condition!!.icon), - Colors.WHITE - ) - ) - ) + setAmbientImage(monochromaticIcon) } } .build() ) + if (!wim.isFontIcon) { + builder.setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + builder.setTapAction(getTapIntent(this)) return builder.build() } @@ -183,18 +196,9 @@ class WeatherComplicationService : WeatherForecastComplicationService() { MonochromaticImage.Builder(icon).build() ) } else { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) builder.setSmallImage( SmallImage.Builder(icon, SmallImageType.ICON) - .setAmbientImage( - Icon.createWithBitmap( - ImageUtils.tintedBitmapFromDrawable( - this, - wip.getWeatherIconResource(weather.condition!!.icon), - Colors.WHITE - ) - ) - ) + .setAmbientImage(monochromaticIcon) .build() ) } @@ -203,37 +207,18 @@ class WeatherComplicationService : WeatherForecastComplicationService() { return builder.build() } ComplicationType.MONOCHROMATIC_IMAGE -> { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) - return MonochromaticImageComplicationData.Builder( - MonochromaticImage.Builder( - Icon.createWithResource( - this, - wip.getWeatherIconResource(weather.condition!!.icon) - ) - .setTint(Colors.WHITESMOKE) - ).build(), + MonochromaticImage.Builder(monochromaticIcon).build(), contentDescription ).setTapAction( getTapIntent(this) ).build() } ComplicationType.SMALL_IMAGE -> { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) - return SmallImageComplicationData.Builder( - SmallImage.Builder( - icon, - SmallImageType.ICON - ).setAmbientImage( - Icon.createWithBitmap( - ImageUtils.tintedBitmapFromDrawable( - this, - wip.getWeatherIconResource(weather.condition!!.icon), - Colors.WHITE - ) - ) - ).build(), + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), contentDescription ).setTapAction( getTapIntent(this) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherHiLoComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherHiLoComplicationService.kt index faf9d86d..9eb607e1 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherHiLoComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WeatherHiLoComplicationService.kt @@ -13,10 +13,8 @@ import androidx.wear.watchface.complications.data.SmallImage import androidx.wear.watchface.complications.data.SmallImageComplicationData import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.utils.ImageUtils -import com.thewizrd.shared_resources.R as sharedRes import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons -import com.thewizrd.shared_resources.icons.WeatherIconsEFProvider import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride @@ -24,8 +22,8 @@ import com.thewizrd.shared_resources.utils.LocaleUtils import com.thewizrd.shared_resources.utils.Units import com.thewizrd.shared_resources.weatherdata.model.Forecast import com.thewizrd.shared_resources.weatherdata.model.Weather -import com.thewizrd.simpleweather.R import com.thewizrd.weather_api.weatherModule +import com.thewizrd.shared_resources.R as sharedRes class WeatherHiLoComplicationService : WeatherForecastComplicationService() { companion object { @@ -39,24 +37,39 @@ class WeatherHiLoComplicationService : WeatherForecastComplicationService() { ComplicationType.MONOCHROMATIC_IMAGE, ComplicationType.SMALL_IMAGE ) - private val complicationIconResId = sharedRes.drawable.wi_day_sunny override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val complicationIcon = WeatherIcons.DAY_SUNNY + val monochromaticIcon = + Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) + .setTint(Colors.WHITESMOKE) + val icon = Icon.createWithBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ) + ) + return when (type) { ComplicationType.SHORT_TEXT -> { ShortTextComplicationData.Builder( PlainComplicationText.Builder("75°/65°").build(), PlainComplicationText.Builder("70° - Sunny").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon).build(), + ) + } + }.build() } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( @@ -65,11 +78,15 @@ class WeatherHiLoComplicationService : WeatherForecastComplicationService() { ).setTitle( PlainComplicationText.Builder("75° | 65°").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon).build(), + ) + } + }.build() } else -> { null @@ -145,6 +162,8 @@ class WeatherHiLoComplicationService : WeatherForecastComplicationService() { val wim = sharedDeps.weatherIconsManager val weatherIcon = wim.getWeatherIconResource(weather.condition!!.icon) + val monochromaticIcon = Icon.createWithResource(this, weatherIcon) + .setTint(Colors.WHITESMOKE) val icon = Icon.createWithBitmap( ImageUtils.bitmapFromDrawable( getThemeContextOverride(false), @@ -177,21 +196,20 @@ class WeatherHiLoComplicationService : WeatherForecastComplicationService() { MonochromaticImage.Builder(icon).apply { // Weather Icon if (!wim.isFontIcon) { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) - setAmbientImage( - Icon.createWithBitmap( - ImageUtils.tintedBitmapFromDrawable( - this@WeatherHiLoComplicationService, - wip.getWeatherIconResource(weather.condition!!.icon), - Colors.WHITE - ) - ) - ) + setAmbientImage(monochromaticIcon) } } .build() ) + if (!wim.isFontIcon) { + builder.setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + builder.setTapAction(getTapIntent(this)) return builder.build() } @@ -209,18 +227,9 @@ class WeatherHiLoComplicationService : WeatherForecastComplicationService() { MonochromaticImage.Builder(icon).build() ) } else { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) builder.setSmallImage( SmallImage.Builder(icon, SmallImageType.ICON) - .setAmbientImage( - Icon.createWithBitmap( - ImageUtils.tintedBitmapFromDrawable( - this, - wip.getWeatherIconResource(weather.condition!!.icon), - Colors.WHITE - ) - ) - ) + .setAmbientImage(monochromaticIcon) .build() ) } @@ -229,37 +238,18 @@ class WeatherHiLoComplicationService : WeatherForecastComplicationService() { return builder.build() } ComplicationType.MONOCHROMATIC_IMAGE -> { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) - return MonochromaticImageComplicationData.Builder( - MonochromaticImage.Builder( - Icon.createWithResource( - this, - wip.getWeatherIconResource(weather.condition!!.icon) - ) - .setTint(Colors.WHITESMOKE) - ).build(), + MonochromaticImage.Builder(monochromaticIcon).build(), contentDescription ).setTapAction( getTapIntent(this) ).build() } ComplicationType.SMALL_IMAGE -> { - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) - return SmallImageComplicationData.Builder( - SmallImage.Builder( - icon, - SmallImageType.ICON - ).setAmbientImage( - Icon.createWithBitmap( - ImageUtils.tintedBitmapFromDrawable( - this, - wip.getWeatherIconResource(weather.condition!!.icon), - Colors.WHITE - ) - ) - ).build(), + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), contentDescription ).setTapAction( getTapIntent(this) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WindComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WindComplicationService.kt index 09eed361..ac2d7615 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WindComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/WindComplicationService.kt @@ -15,6 +15,7 @@ import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.utils.ImageUtils import com.thewizrd.shared_resources.di.settingsManager import com.thewizrd.shared_resources.icons.WeatherIcons +import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride import com.thewizrd.shared_resources.utils.ConversionMethods @@ -38,30 +39,49 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.MONOCHROMATIC_IMAGE, ComplicationType.SMALL_IMAGE ) - private val complicationIconResId = sharedRes.drawable.wi_strong_wind + + private val complicationIcon = WeatherIcons.WIND_DIRECTION override fun getPreviewData(type: ComplicationType): ComplicationData? { if (!supportedComplicationTypes.contains(type)) { return NoDataComplicationData() } + val wim = sharedDeps.weatherIconsManager + val icon = Icon.createWithBitmap( + ImageUtils.rotateBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ), 330.0f // 150° + 180 + ) + ) + val monochromaticIcon = Icon.createWithBitmap( + ImageUtils.rotateBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ), 330.0f // 150° + 180 + ) + ) + .setTint(Colors.WHITESMOKE) + return when (type) { ComplicationType.SHORT_TEXT -> { ShortTextComplicationData.Builder( PlainComplicationText.Builder("5 mph").build(), PlainComplicationText.Builder("Wind: 5 mph, SSE").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithBitmap( - ImageUtils.rotateBitmap( - ImageUtils.bitmapFromDrawable( - getThemeContextOverride(false), - sharedRes.drawable.wi_wind_direction_white - ), 330.0f // 150° + 180 - ) + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() ) - ).build() - ).build() + } + }.build() } ComplicationType.LONG_TEXT -> { LongTextComplicationData.Builder( @@ -70,51 +90,30 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ).setTitle( PlainComplicationText.Builder("5 mph, SSE").build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).build() + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build() + ) + } + }.build() } ComplicationType.MONOCHROMATIC_IMAGE -> { MonochromaticImageComplicationData.Builder( - MonochromaticImage.Builder( - Icon.createWithBitmap( - ImageUtils.rotateBitmap( - ImageUtils.bitmapFromDrawable( - getThemeContextOverride(false), - sharedRes.drawable.wi_wind_direction_white - ), 330.0f // 150° + 180 - ) - ) - ).build(), + MonochromaticImage.Builder(monochromaticIcon).build(), PlainComplicationText.Builder("Wind: 5 mph, SSE").build() ).build() } ComplicationType.SMALL_IMAGE -> { SmallImageComplicationData.Builder( - SmallImage.Builder( - Icon.createWithBitmap( - ImageUtils.rotateBitmap( - ImageUtils.bitmapFromDrawable( - getThemeContextOverride(false), - sharedRes.drawable.wi_wind_direction_white - ), 330.0f // 150° + 180 - ) - ), - SmallImageType.ICON - ).setAmbientImage( - Icon.createWithBitmap( - ImageUtils.rotateBitmap( - ImageUtils.bitmapFromDrawable( - getThemeContextOverride(false), - sharedRes.drawable.wi_wind_direction_white - ), 330.0f // 150° + 180 - ) - ) - ).build(), + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), PlainComplicationText.Builder("Wind: 5 mph, SSE").build() ).build() } @@ -190,6 +189,24 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { dataType: ComplicationType, windSpeedShort: String? = null, windSpeedLong: String? = null, windDirection: Int = 0 ): ComplicationData? { + val wim = sharedDeps.weatherIconsManager + val icon = Icon.createWithBitmap( + ImageUtils.rotateBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ), windDirection.toFloat() + 180 + ) + ) + val monochromaticIcon = Icon.createWithBitmap( + ImageUtils.rotateBitmap( + ImageUtils.bitmapFromDrawable( + getThemeContextOverride(false), + wim.getWeatherIconResource(complicationIcon) + ), windDirection.toFloat() + 180 + ) + ).setTint(Colors.WHITESMOKE) + return when (dataType) { ComplicationType.SHORT_TEXT -> { ShortTextComplicationData.Builder( @@ -200,17 +217,16 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ?: "${getString(sharedRes.string.label_wind)}: ${getString(sharedRes.string.weather_notavailable)}" ).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithBitmap( - ImageUtils.rotateBitmap( - ImageUtils.bitmapFromDrawable( - getThemeContextOverride(false), - sharedRes.drawable.wi_wind_direction_white - ), windDirection.toFloat() + 180 - ) + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), ) - ).build() - ).setTapAction( + } + }.setTapAction( getTapIntent(this) ).build() } @@ -224,28 +240,23 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ).setTitle( PlainComplicationText.Builder(windSpeedLong ?: WeatherIcons.EM_DASH).build() ).setMonochromaticImage( - MonochromaticImage.Builder( - Icon.createWithResource(this, complicationIconResId) - .setTint(Colors.WHITESMOKE) - ).build() - ).setTapAction( + MonochromaticImage.Builder(monochromaticIcon).build() + ).apply { + if (!wim.isFontIcon) { + setSmallImage( + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), + ) + } + }.setTapAction( getTapIntent(this) ).build() } ComplicationType.MONOCHROMATIC_IMAGE -> { MonochromaticImageComplicationData.Builder( - MonochromaticImage.Builder( - Icon.createWithBitmap( - ImageUtils.rotateBitmap( - ImageUtils.bitmapFromDrawable( - getThemeContextOverride(false), - sharedRes.drawable.wi_wind_direction_white - ), windDirection.toFloat() + 180 - ) - ) - .setTint(Colors.WHITESMOKE) - ).build(), + MonochromaticImage.Builder(monochromaticIcon).build(), PlainComplicationText.Builder("${getString(sharedRes.string.label_wind)}: $windSpeedLong") .build() ).build() @@ -253,27 +264,9 @@ class WindComplicationService : WeatherHourlyForecastComplicationService() { ComplicationType.SMALL_IMAGE -> { SmallImageComplicationData.Builder( - SmallImage.Builder( - Icon.createWithBitmap( - ImageUtils.rotateBitmap( - ImageUtils.bitmapFromDrawable( - getThemeContextOverride(false), - sharedRes.drawable.wi_wind_direction_white - ), windDirection.toFloat() + 180 - ) - ), - SmallImageType.ICON - ).setAmbientImage( - Icon.createWithBitmap( - ImageUtils.rotateBitmap( - ImageUtils.bitmapFromDrawable( - getThemeContextOverride(false), - sharedRes.drawable.wi_wind_direction_white - ), windDirection.toFloat() + 180 - ) - ) - .setTint(Colors.WHITESMOKE) - ).build(), + SmallImage.Builder(icon, SmallImageType.ICON) + .setAmbientImage(monochromaticIcon) + .build(), PlainComplicationText.Builder( "${getString(sharedRes.string.label_wind)}: ${ windSpeedLong ?: getString( From e7cd1926f0578378a228631d8688d3bacec266fb Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sun, 28 Jun 2026 16:31:31 -0400 Subject: [PATCH 49/67] RemoteConfig: default to OpenMeteo if location is within supported models --- .../remoteconfig/RemoteConfigServiceImpl.kt | 8 ++ .../shared_resources/utils/LocationUtils.kt | 130 +++++++++++++++++- .../remoteconfig/RemoteConfigServiceImpl.kt | 24 ++++ 3 files changed, 160 insertions(+), 2 deletions(-) diff --git a/shared_resources/src/fullgms/java/com/thewizrd/shared_resources/remoteconfig/RemoteConfigServiceImpl.kt b/shared_resources/src/fullgms/java/com/thewizrd/shared_resources/remoteconfig/RemoteConfigServiceImpl.kt index 055780be..0cae9a4c 100644 --- a/shared_resources/src/fullgms/java/com/thewizrd/shared_resources/remoteconfig/RemoteConfigServiceImpl.kt +++ b/shared_resources/src/fullgms/java/com/thewizrd/shared_resources/remoteconfig/RemoteConfigServiceImpl.kt @@ -89,6 +89,10 @@ class RemoteConfigServiceImpl : RemoteConfigService { WeatherAPI.ECCC } + LocationUtils.isOpenMeteoSupported(location) && isProviderEnabled(WeatherAPI.OPENMETEO) -> { + WeatherAPI.OPENMETEO + } + else -> { getDefaultWeatherProvider() } @@ -114,6 +118,10 @@ class RemoteConfigServiceImpl : RemoteConfigService { WeatherAPI.ECCC } + LocationUtils.isOpenMeteoSupported(location) && isProviderEnabled(WeatherAPI.OPENMETEO) -> { + WeatherAPI.OPENMETEO + } + else -> { getDefaultWeatherProvider() } diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/LocationUtils.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/LocationUtils.kt index 7dde5d0a..c82c1795 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/LocationUtils.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/utils/LocationUtils.kt @@ -6,7 +6,8 @@ import com.thewizrd.shared_resources.locationdata.LocationData import com.thewizrd.shared_resources.locationdata.LocationQuery object LocationUtils { - // Source: https://gist.github.com/graydon/11198540 + // xMin -> lon_min, xMax -> lon_max; yMin -> lat_min, yMax -> lat_max + // xMax -> East, xMin -> West, yMax -> North, yMin -> South private val US_BOUNDING_BOX = BoundingBox(24.9493, 49.5904, -125.0011, -66.9326) // Canada @@ -36,7 +37,51 @@ object LocationUtils { BoundingBox(47.2701114, 55.099161, 5.8663153, 15.0419319) private val CAMS_OPENMETEO_EUROPE_BBOX = - BoundingBox(-25.0, 45.0, 30.0, 72.0) + BoundingBox(30.0, 72.0, -25.0, 45.0) + + // United Kingdom and Ireland + private val UK_IE_BOUNDING_BOX = + BoundingBox(49.674, 61.061, -14.015517, 2.0919117) + + // Korea + private val KOREA_BOUNDING_BOX = + BoundingBox(32.9104556, 43.0078553939, 124.3017732603, 131.0789644224) + + // Japan + private val JP_BOUNDING_BOX = + BoundingBox(20.2145811, 45.7563343, 122.7141754, 154.205541) + + // Switzerland + private val CH_BOUNDING_BOX = + BoundingBox(45.8179579, 47.8084544, 5.9558318, 10.4922941) + + // Met Norway Area + private val METNO_BOUNDING_BOX = + BoundingBox(54.4504920972, 81.0280176, -9.6846279, 34.6889114) + + // Australia + private val AU_BOUNDING_BOX = + BoundingBox(-55.3228175, -9.0880125, 72.2461932, 168.2261259) + + // China + private val CN_BOUNDING_BOX = + BoundingBox(17.917694912, 53.5608154, 73.4997347, 134.7751959) + + // Netherlands + private val NL_BOUNDING_BOX = + BoundingBox(50.7218810189, 53.7801536938, 3.3388847969, 7.590283575) + + // Denmark + private val DK_BOUNDING_BOX = + BoundingBox(54.4516667, 57.9524297, 7.7153255, 15.5530641) + + // Italy + private val IT_BOUNDING_BOX = + BoundingBox(35.2889616, 47.0921485, 6.6272658, 18.7844746) + + // Austria + private val AT_BOUNDING_BOX = + BoundingBox(46.3722987, 49.0205239, 9.5307487, 17.1607728) private val NWS_SUPPORTED_COUNTRIES = setOf("US", "AS", "UM", "GU", "MP", "PR", "VI") private val NWS_SUPPORTED_LOCATIONS = listOf( @@ -47,6 +92,57 @@ object LocationUtils { AS_BOUNDING_BOX ) + private val OPENMETEO_SUPPORTED_COUNTRIES = setOf( + "US", "AS", "UM", "GU", "MP", "PR", "VI", // NWS + "UK", "IE", // UK and Ireland - UK Met Office + "FR", // France - MeteoFrance + "KR", "KP", // Korea - KMA Korea + "JP", // JMA Japan + "CH", // Switzerland - MeteoSwiss + "NO", "DK", "SE", "FI", // Norway, Denmark, Sweden, Finland - Met Norway + "CA", // Canada - GEM Canada + "AU", // Australia - BOM Australia + "CN", // China - CMA China + "NL", // Netherlands - KNMI Netherlands + "DK", // Denmark - DMI Denmark + "IT", // Italy - ItaliaMeteo + "AT", // Austria - GeoSphere Austria + ) + private val OPENMETEO_SUPPORTED_LOCATIONS = listOf( + // NWS + US_BOUNDING_BOX, + PR_BOUNDING_BOX, + VI_BOUNDING_BOX, + GU_MP_BOUNDING_BOX, + AS_BOUNDING_BOX, + // UK and Ireland + UK_IE_BOUNDING_BOX, + // France + FR_BOUNDING_BOX, + // Korea + KOREA_BOUNDING_BOX, + // Japan + JP_BOUNDING_BOX, + // Switzerland + CH_BOUNDING_BOX, + // MetNo + METNO_BOUNDING_BOX, + // Canada + CA_BOUNDING_BOX, + // Australia + AU_BOUNDING_BOX, + // China + CN_BOUNDING_BOX, + // Netherlands + NL_BOUNDING_BOX, + // Denmark + DK_BOUNDING_BOX, + // Italy + IT_BOUNDING_BOX, + // Austria, + AT_BOUNDING_BOX, + ) + fun isUS(countryCode: String?): Boolean { return if (countryCode.isNullOrBlank()) { false @@ -240,6 +336,36 @@ object LocationUtils { return CAMS_OPENMETEO_EUROPE_BBOX.intersects(location.latitude, location.longitude) } + fun isOpenMeteoSupported(countryCode: String?): Boolean { + return OPENMETEO_SUPPORTED_COUNTRIES.contains(countryCode?.uppercase()) + } + + fun isOpenMeteoSupported(location: LocationData): Boolean { + return if (!location.countryCode.isNullOrBlank()) { + isOpenMeteoSupported(location.countryCode) + } else { + OPENMETEO_SUPPORTED_LOCATIONS.any { + it.intersects( + location.latitude, + location.longitude + ) + } + } + } + + fun isOpenMeteoSupported(location: LocationQuery): Boolean { + return if (!location.locationCountry.isNullOrBlank()) { + isOpenMeteoSupported(location.locationCountry) + } else { + OPENMETEO_SUPPORTED_LOCATIONS.any { + it.intersects( + location.locationLat, + location.locationLong + ) + } + } + } + private data class BoundingBox( val lat_min: Double, val lat_max: Double, diff --git a/shared_resources/src/nongms/java/com/thewizrd/shared_resources/remoteconfig/RemoteConfigServiceImpl.kt b/shared_resources/src/nongms/java/com/thewizrd/shared_resources/remoteconfig/RemoteConfigServiceImpl.kt index f56a47d3..dd248bc8 100644 --- a/shared_resources/src/nongms/java/com/thewizrd/shared_resources/remoteconfig/RemoteConfigServiceImpl.kt +++ b/shared_resources/src/nongms/java/com/thewizrd/shared_resources/remoteconfig/RemoteConfigServiceImpl.kt @@ -40,6 +40,18 @@ class RemoteConfigServiceImpl : RemoteConfigService { WeatherAPI.METEOFRANCE } + LocationUtils.isGermany(location) && isProviderEnabled(WeatherAPI.DWD) -> { + WeatherAPI.DWD + } + + LocationUtils.isCanada(location) && isProviderEnabled(WeatherAPI.ECCC) -> { + WeatherAPI.ECCC + } + + LocationUtils.isOpenMeteoSupported(location) && isProviderEnabled(WeatherAPI.OPENMETEO) -> { + WeatherAPI.OPENMETEO + } + else -> { getDefaultWeatherProvider() } @@ -57,6 +69,18 @@ class RemoteConfigServiceImpl : RemoteConfigService { WeatherAPI.METEOFRANCE } + LocationUtils.isGermany(location) && isProviderEnabled(WeatherAPI.DWD) -> { + WeatherAPI.DWD + } + + LocationUtils.isCanada(location) && isProviderEnabled(WeatherAPI.ECCC) -> { + WeatherAPI.ECCC + } + + LocationUtils.isOpenMeteoSupported(location) && isProviderEnabled(WeatherAPI.OPENMETEO) -> { + WeatherAPI.OPENMETEO + } + else -> { getDefaultWeatherProvider() } From e924cf915c6208e80f649f8098cfd7edd12b6ff6 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sun, 28 Jun 2026 17:03:26 -0400 Subject: [PATCH 50/67] gradle: update dependencies --- gradle/libs.versions.toml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4ac9dd0e..2c009368 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,10 +11,10 @@ ksp_version = "2.3.6" desugar_version = '2.1.5' -firebase_version = "34.14.0" +firebase_version = "34.15.0" firebaseCrashlyticsGradleVersion = "3.0.7" firebasePerfPluginVersion = "2.0.2" -gms_location_version = '21.3.0' +gms_location_version = "21.4.0" gms_base_version = "18.10.0" gms_basement_version = "18.10.0" gms_tasks_version = "18.4.1" @@ -28,7 +28,7 @@ constraintlayout_version = '2.2.1' core_version = "1.19.0" arch_core_runtime_version = '2.2.0' fragment_version = '1.8.9' -lifecycle_version = "2.10.0" +lifecycle_version = "2.11.0" nav_version = "2.9.8" paging_version = "3.5.0" preference_version = '1.2.1' @@ -48,10 +48,10 @@ google_truth_version = '1.4.5' espresso_core_version = "3.7.0" material_version = "1.14.0" -material_compose_version = "1.5.0-alpha21" +material_compose_version = "1.5.0-alpha22" compose_compiler_version = '1.5.15' -compose_bom_version = "2026.05.01" +compose_bom_version = "2026.06.00" wear_version = "1.4.0" wear_compose_version = "1.6.2" wear_input_version = '1.2.0' @@ -64,10 +64,10 @@ glide_version = "5.0.7" icu4j_version = "78.3" jjwt_version = '0.13.0' moshi_version = '1.15.2' -okhttp_version = "5.3.2" +okhttp_version = "5.4.0" timber_version = '5.0.1' -revcat_version = "10.8.0" +revcat_version = "10.11.0" [libraries] com-google-devtools-ksp-gradle-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp_version" } From e48756859eb235289ee13c48935e948487191f73 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sun, 28 Jun 2026 17:07:43 -0400 Subject: [PATCH 51/67] SimpleWeather: v5.14.0-build6 --- app/build.gradle | 2 +- wearapp/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 2484c15c..7cab633f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get().toInteger() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code (Android: 0, WearOS: 1) // ex) 345100131 = (34, 5.10, 013, 0) - versionCode 375140050 + versionCode 375140060 versionName "5.14.0" vectorDrawables { diff --git a/wearapp/build.gradle b/wearapp/build.gradle index ad5ed1fd..5554ef61 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -16,7 +16,7 @@ android { targetSdkVersion libs.versions.wearTargetSdkVersion.get() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code [Android: 0, WearOS: 1]) // ex) 345100131 = (34, 5.10, 013, 1) - versionCode 365140051 + versionCode 365140061 versionName "5.14.0" vectorDrawables { From 475b11de178b75762717855508f850a51c823d6d Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sun, 28 Jun 2026 22:09:38 -0400 Subject: [PATCH 52/67] wearapp: update ranged complication bounds --- .../complications/BeaufortComplicationService.kt | 13 ++++++++----- .../complications/PressureComplicationService.kt | 10 ++++++++-- .../wearable/complications/UVComplicationService.kt | 2 -- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/BeaufortComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/BeaufortComplicationService.kt index 61f60a9b..a718e4c6 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/BeaufortComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/BeaufortComplicationService.kt @@ -23,6 +23,8 @@ import com.thewizrd.shared_resources.utils.getBeaufortScale import com.thewizrd.shared_resources.weatherdata.model.Beaufort import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.Weather +import kotlin.math.max +import kotlin.math.roundToInt import com.thewizrd.shared_resources.R as sharedRes class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { @@ -141,8 +143,8 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { return null } - val beaufort = weather.condition!!.beaufort ?: hourlyForecast?.extras?.windMph?.let { - Beaufort(getBeaufortScale(it)) + val beaufort = weather.condition?.beaufort ?: hourlyForecast?.extras?.windMph?.let { + Beaufort(getBeaufortScale(it.roundToInt())) } val beaufortModel = beaufort?.let { BeaufortViewModel(it) } @@ -156,6 +158,9 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { val progressShortStr = beaufortModel?.progress?.toString() ?: WeatherIcons.EM_DASH val progressStr = beaufortModel?.let { "${it.progress}, ${it.beaufort.value}" } ?: WeatherIcons.EM_DASH + val beaufortProgress = beaufortModel?.progress?.toFloat() ?: 0f + val beaufortProgressMax = + beaufortModel?.let { max(it.progressMax, it.progress).toFloat() } ?: 12f val beaufortIcon = beaufortModel?.beaufort?.icon ?: WeatherIcons.WIND_BEAUFORT_0 val monochromaticIcon = @@ -171,9 +176,7 @@ class BeaufortComplicationService : WeatherHourlyForecastComplicationService() { return when (dataType) { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( - beaufortModel?.progress?.toFloat() ?: 0f, - 0f, - beaufortModel?.progressMax?.toFloat() ?: 1f, + beaufortProgress, 0f, beaufortProgressMax, contentDescription ).setMonochromaticImage( MonochromaticImage.Builder(monochromaticIcon).build() diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PressureComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PressureComplicationService.kt index 92675ed2..cf9e46e3 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PressureComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/PressureComplicationService.kt @@ -23,6 +23,8 @@ import com.thewizrd.shared_resources.utils.Units import com.thewizrd.shared_resources.weatherdata.model.HourlyForecast import com.thewizrd.shared_resources.weatherdata.model.Weather import java.text.DecimalFormat +import kotlin.math.max +import kotlin.math.min import com.thewizrd.shared_resources.R as sharedRes class PressureComplicationService : WeatherHourlyForecastComplicationService() { @@ -178,10 +180,14 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { private fun buildUpdate( dataType: ComplicationType, - pressureStr: String? = null, pressureStrShort: String? = null, pressureVal: Float? = null + pressureStr: String? = null, pressureStrShort: String? = null, pressureInVal: Float? = null ): ComplicationData? { val wim = sharedDeps.weatherIconsManager + val pressureProgress = pressureInVal ?: 26f + val pressureMin = min(pressureProgress, 26f) + val pressureMax = max(pressureProgress, 32f) + val monochromaticIcon = Icon.createWithResource(this, wim.getWeatherIconResource(complicationIcon)) .setTint(Colors.WHITESMOKE) @@ -195,7 +201,7 @@ class PressureComplicationService : WeatherHourlyForecastComplicationService() { return when (dataType) { ComplicationType.RANGED_VALUE -> { RangedValueComplicationData.Builder( - pressureVal ?: 26f, 26f, 32f, + pressureProgress, pressureMin, pressureMax, PlainComplicationText.Builder( String.format( "%s: %s", diff --git a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/UVComplicationService.kt b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/UVComplicationService.kt index 0cec8c3b..335f7db1 100644 --- a/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/UVComplicationService.kt +++ b/wearapp/src/main/java/com/thewizrd/simpleweather/wearable/complications/UVComplicationService.kt @@ -14,7 +14,6 @@ import androidx.wear.watchface.complications.data.SmallImageType import com.thewizrd.common.controls.UVIndexViewModel import com.thewizrd.common.utils.ImageUtils import com.thewizrd.shared_resources.icons.WeatherIcons -import com.thewizrd.shared_resources.icons.WeatherIconsEFProvider import com.thewizrd.shared_resources.sharedDeps import com.thewizrd.shared_resources.utils.Colors import com.thewizrd.shared_resources.utils.ContextUtils.getThemeContextOverride @@ -42,7 +41,6 @@ class UVComplicationService : WeatherHourlyForecastComplicationService() { } val wim = sharedDeps.weatherIconsManager - val wip = wim.getIconProvider(WeatherIconsEFProvider.KEY) val complicationIcon = WeatherIcons.UV_INDEX_3 val monochromaticIcon = From b1a64b4fdf891c44f7b2369438a750d2a316ffe3 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sun, 28 Jun 2026 22:14:37 -0400 Subject: [PATCH 53/67] SimpleWeather: v5.14.0-build7 --- wearapp/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wearapp/build.gradle b/wearapp/build.gradle index 5554ef61..9d30ef39 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -16,7 +16,7 @@ android { targetSdkVersion libs.versions.wearTargetSdkVersion.get() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code [Android: 0, WearOS: 1]) // ex) 345100131 = (34, 5.10, 013, 1) - versionCode 365140061 + versionCode 365140071 versionName "5.14.0" vectorDrawables { From b484a6f32e6c9c7bde41e5da0e9e16dca83afc4b Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Mon, 29 Jun 2026 20:45:18 -0400 Subject: [PATCH 54/67] JSONParser: fix parsing issue with floats --- .../com/thewizrd/shared_resources/json/NaNToNullAdapter.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shared_resources/src/main/java/com/thewizrd/shared_resources/json/NaNToNullAdapter.kt b/shared_resources/src/main/java/com/thewizrd/shared_resources/json/NaNToNullAdapter.kt index 4d37005f..98576bfb 100644 --- a/shared_resources/src/main/java/com/thewizrd/shared_resources/json/NaNToNullAdapter.kt +++ b/shared_resources/src/main/java/com/thewizrd/shared_resources/json/NaNToNullAdapter.kt @@ -6,7 +6,8 @@ import com.squareup.moshi.JsonWriter val doubleNaNToNullAdapter = object : JsonAdapter() { override fun fromJson(reader: JsonReader): Double? { - return reader.readJsonValue() as? Double + val value = reader.readJsonValue() + return (value as? Number)?.toDouble() } override fun toJson(writer: JsonWriter, value: Double?) { @@ -20,7 +21,8 @@ val doubleNaNToNullAdapter = object : JsonAdapter() { val floatNaNToNullAdapter = object : JsonAdapter() { override fun fromJson(reader: JsonReader): Float? { - return reader.readJsonValue() as? Float + val value = reader.readJsonValue() + return (value as? Number)?.toFloat() } override fun toJson(writer: JsonWriter, value: Float?) { From 4c05c8c79472f30f00e405ea59c4880d45dfba20 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Mon, 29 Jun 2026 20:46:31 -0400 Subject: [PATCH 55/67] SimpleWeather: v5.14.0-build8 --- app/build.gradle | 2 +- wearapp/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7cab633f..e75e15f4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get().toInteger() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code (Android: 0, WearOS: 1) // ex) 345100131 = (34, 5.10, 013, 0) - versionCode 375140060 + versionCode 375140080 versionName "5.14.0" vectorDrawables { diff --git a/wearapp/build.gradle b/wearapp/build.gradle index 9d30ef39..a72a6cd8 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -16,7 +16,7 @@ android { targetSdkVersion libs.versions.wearTargetSdkVersion.get() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code [Android: 0, WearOS: 1]) // ex) 345100131 = (34, 5.10, 013, 1) - versionCode 365140071 + versionCode 365140081 versionName "5.14.0" vectorDrawables { From 9b542c4f98a0aa70ff2ed3770143733af7084678 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Fri, 3 Jul 2026 23:39:08 -0400 Subject: [PATCH 56/67] MeteoFranceProvider: update api --- .../weather_api/meteofrance/weather/Common.kt | 14 + .../meteofrance/weather/CurrentsResponse.kt | 72 ++--- .../meteofrance/weather/ForecastResponse.kt | 290 ++++++++---------- .../weather/MeteoFranceProvider.kt | 38 ++- .../meteofrance/weather/WeatherData.kt | 242 ++++++++------- 5 files changed, 325 insertions(+), 331 deletions(-) create mode 100644 weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/Common.kt diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/Common.kt b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/Common.kt new file mode 100644 index 00000000..bc6ea116 --- /dev/null +++ b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/Common.kt @@ -0,0 +1,14 @@ +package com.thewizrd.weather_api.meteofrance.weather + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class Geometry( + + @Json(name = "coordinates") + val coordinates: List? = null, + + @Json(name = "type") + val type: String? = null +) \ No newline at end of file diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/CurrentsResponse.kt b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/CurrentsResponse.kt index 1bbedda8..bfee7c5f 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/CurrentsResponse.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/CurrentsResponse.kt @@ -6,61 +6,53 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) data class CurrentsResponse( - @field:Json(name = "updated_on") - var updatedOn: Long? = null, + @Json(name = "update_time") + val updateTime: String? = null, - @field:Json(name = "observation") - var observation: Observation? = null, + @Json(name = "geometry") + val geometry: Geometry? = null, - @field:Json(name = "position") - var position: CurrentsPosition? = null + @Json(name = "type") + val type: String? = null, + + @Json(name = "properties") + val properties: CurrentProperties? = null ) @JsonClass(generateAdapter = true) -data class CurrentsPosition( - - @field:Json(name = "timezone") - var timezone: String? = null, +data class CurrentProperties( - @field:Json(name = "lon") - var lon: Float? = null, + @Json(name = "timezone") + val timezone: String? = null, - @field:Json(name = "lat") - var lat: Float? = null + @Json(name = "gridded") + val gridded: Gridded? = null ) @JsonClass(generateAdapter = true) -data class Observation( +data class Gridded( - @field:Json(name = "T") - var T: Float? = null, + @Json(name = "T") + val t: Float? = null, - @field:Json(name = "weather") - var weather: Weather? = null, + @Json(name = "weather_description") + val weatherDescription: String? = null, - @field:Json(name = "wind") - var wind: Wind? = null -) -/* -@JsonClass(generateAdapter = true) -data class Weather( + @Json(name = "wind_icon") + val windIcon: String? = null, - @field:Json(name = "icon") - var icon: String? = null, + @Json(name = "wind_speed") + val windSpeed: Float? = null, - @field:Json(name = "desc") - var desc: String? = null -) -@JsonClass(generateAdapter = true) -data class Wind( + @Json(name = "wind_direction") + val windDirection: Int? = null, - @field:Json(name = "icon") - var icon: String? = null, + @Json(name = "time") + val time: String? = null, - @field:Json(name = "speed") - var speed: Int? = null, + @Json(name = "weather_icon") + val weatherIcon: String? = null, - @field:Json(name = "direction") - var direction: Int? = null -) -*/ \ No newline at end of file + @Json(name = "wind_speed_gust") + val windSpeedGust: Float? = null +) \ No newline at end of file diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/ForecastResponse.kt b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/ForecastResponse.kt index 9eca47df..581371a5 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/ForecastResponse.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/ForecastResponse.kt @@ -6,242 +6,196 @@ import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) data class ForecastResponse( - @field:Json(name = "updated_on") - var updatedOn: Long? = null, + @Json(name = "update_time") + val updateTime: String? = null, - @field:Json(name = "probability_forecast") - var probabilityForecast: List? = null, + @Json(name = "geometry") + val geometry: Geometry? = null, - @field:Json(name = "forecast") - var forecast: List? = null, + @Json(name = "type") + val type: String? = null, - @field:Json(name = "position") - var position: ForecastPosition? = null, - - @field:Json(name = "daily_forecast") - var dailyForecast: List? = null -) - -@JsonClass(generateAdapter = true) -data class Rain( - - @field:Json(name = "6h") - var jsonMember6h: Float? = null, - - @field:Json(name = "3h") - var jsonMember3h: Float? = null, - - @field:Json(name = "1h") - var jsonMember1h: Float? = null + @Json(name = "properties") + val properties: ForecastProperties? = null ) @JsonClass(generateAdapter = true) -data class Weather12H( - - @field:Json(name = "icon") - var icon: String? = null, - - @field:Json(name = "desc") - var desc: String? = null -) +data class DailyForecastItem( -@JsonClass(generateAdapter = true) -data class ForecastItem( + @Json(name = "daily_weather_icon") + val dailyWeatherIcon: String? = null, - @field:Json(name = "dt") - var dt: Long? = null, + @Json(name = "sunset_time") + val sunsetTime: String? = null, - @field:Json(name = "rain") - var rain: Rain? = null, + @Json(name = "daily_weather_description") + val dailyWeatherDescription: String? = null, - @field:Json(name = "T") - var T: ForecastTemp? = null, + @Json(name = "uv_index") + val uvIndex: Float? = null, - @field:Json(name = "snow") - var snow: Snow? = null, + @Json(name = "T_max") + val tMax: Float? = null, - @field:Json(name = "weather") - var weather: Weather? = null, + @Json(name = "total_precipitation_24h") + val totalPrecipitation24h: Float? = null, - @field:Json(name = "humidity") - var humidity: Int? = null, + @Json(name = "relative_humidity_min") + val relativeHumidityMin: Int? = null, - @field:Json(name = "rain snow limit") - var rainSnowLimit: String? = null, + @Json(name = "relative_humidity_max") + val relativeHumidityMax: Int? = null, - @field:Json(name = "iso0") - var iso0: Int? = null, + @Json(name = "sunrise_time") + val sunriseTime: String? = null, - @field:Json(name = "sea_level") - var seaLevel: Float? = null, + @Json(name = "time") + val time: String? = null, - @field:Json(name = "clouds") - var clouds: Int? = null, + @Json(name = "T_min") + val tMin: Float? = null, - @field:Json(name = "wind") - var wind: Wind? = null + @Json(name = "T_sea") + val tSea: Float? = null ) @JsonClass(generateAdapter = true) -data class ForecastPosition( - - @field:Json(name = "bulletin_cote") - var bulletinCote: Int? = null, - - @field:Json(name = "country") - var country: String? = null, - - @field:Json(name = "insee") - var insee: String? = null, +data class ProbabilityForecastItem( - @field:Json(name = "timezone") - var timezone: String? = null, + @Json(name = "freezing_hazard") + val freezingHazard: Int? = null, - @field:Json(name = "name") - var name: String? = null, + @Json(name = "snow_hazard_3h") + val snowHazard3h: Float? = null, - @field:Json(name = "lon") - var lon: Float? = null, + @Json(name = "snow_hazard_6h") + val snowHazard6h: Float? = null, - @field:Json(name = "dept") - var dept: String? = null, + @Json(name = "rain_hazard_3h") + val rainHazard3h: Float? = null, - @field:Json(name = "alti") - var alti: Int? = null, + @Json(name = "rain_hazard_6h") + val rainHazard6h: Float? = null, - @field:Json(name = "lat") - var lat: Float? = null, + @Json(name = "time") + val time: String? = null, - @field:Json(name = "rain_product_available") - var rainProductAvailable: Int? = null + @Json(name = "storm_hazard") + val stormHazard: Int? = null ) @JsonClass(generateAdapter = true) -data class Weather( - - @field:Json(name = "icon") - var icon: String? = null, +data class ForecastItem( - @field:Json(name = "desc") - var desc: String? = null -) + @Json(name = "weather_icon") + val weatherIcon: String? = null, -@JsonClass(generateAdapter = true) -data class Precipitation( + @Json(name = "rain_24h") + val rain24h: Float? = null, - @field:Json(name = "24h") - var jsonMember24h: Float? = null -) + @Json(name = "T") + val t: Float? = null, -@JsonClass(generateAdapter = true) -data class DailyForecastTemp( + @Json(name = "rain_12h") + val rain12h: Float? = null, - @field:Json(name = "min") - var min: Float? = null, + @Json(name = "weather_confidence_index") + val weatherConfidenceIndex: Int? = null, - @field:Json(name = "max") - var max: Float? = null, + @Json(name = "wind_speed") + val windSpeed: Float? = null, - @field:Json(name = "sea") - var sea: Float? = null -) + @Json(name = "snow_6h") + val snow6h: Float? = null, -@JsonClass(generateAdapter = true) -data class ForecastTemp( + @Json(name = "snow_12h") + val snow12h: Float? = null, - @field:Json(name = "value") - var value: Float? = null, + @Json(name = "T_windchill") + val tWindchill: Float? = null, - @field:Json(name = "windchill") - var windchill: Float? = null -) + @Json(name = "snow_24h") + val snow24h: Float? = null, -@JsonClass(generateAdapter = true) -data class Sun( + @Json(name = "snow_3h") + val snow3h: Float? = null, - @field:Json(name = "set") - var set: Long? = null, + @Json(name = "weather_description") + val weatherDescription: String? = null, - @field:Json(name = "rise") - var rise: Long? = null -) + @Json(name = "rain_1h") + val rain1h: Float? = null, -@JsonClass(generateAdapter = true) -data class DailyForecastItem( + @Json(name = "snow_1h") + val snow1h: Float? = null, - @field:Json(name = "dt") - var dt: Long? = null, + @Json(name = "rain_3h") + val rain3h: Float? = null, - @field:Json(name = "precipitation") - var precipitation: Precipitation? = null, + @Json(name = "total_cloud_cover") + val totalCloudCover: Int? = null, - @field:Json(name = "uv") - var uv: Float? = null, + @Json(name = "wind_direction") + val windDirection: Int? = null, - @field:Json(name = "T") - var T: DailyForecastTemp? = null, + @Json(name = "wind_speed_gust") + val windSpeedGust: Float? = null, - @field:Json(name = "weather12H") - var weather12H: Weather12H? = null, + @Json(name = "P_sea") + val pSea: Float? = null, - @field:Json(name = "humidity") - var humidity: Humidity? = null, + @Json(name = "rain_snow_limit") + val rainSnowLimit: String? = null, - @field:Json(name = "sun") - var sun: Sun? = null -) + @Json(name = "wind_icon") + val windIcon: String? = null, -@JsonClass(generateAdapter = true) -data class Snow( + @Json(name = "rain_6h") + val rain6h: Float? = null, - @field:Json(name = "6h") - var jsonMember6h: Float? = null, + @Json(name = "iso0") + val iso0: Int? = null, - @field:Json(name = "3h") - var jsonMember3h: Float? = null, + @Json(name = "time") + val time: String? = null, - @field:Json(name = "1h") - var jsonMember1h: Float? = null + @Json(name = "relative_humidity") + val relativeHumidity: Int? = null ) @JsonClass(generateAdapter = true) -data class Humidity( +data class ForecastProperties( - @field:Json(name = "min") - var min: Int? = null, + @Json(name = "bulletin_cote") + val bulletinCote: Int? = null, - @field:Json(name = "max") - var max: Int? = null -) + @Json(name = "altitude") + val altitude: Int? = null, -@JsonClass(generateAdapter = true) -data class ProbabilityForecastItem( - - @field:Json(name = "dt") - var dt: Long? = null, + @Json(name = "country") + val country: String? = null, - @field:Json(name = "rain") - var rain: Rain? = null, + @Json(name = "french_department") + val frenchDepartment: String? = null, - @field:Json(name = "freezing") - var freezing: Int? = null, + @Json(name = "insee") + val insee: String? = null, - @field:Json(name = "snow") - var snow: Snow? = null -) + @Json(name = "timezone") + val timezone: String? = null, -@JsonClass(generateAdapter = true) -data class Wind( + @Json(name = "probability_forecast") + val probabilityForecast: List? = null, - @field:Json(name = "icon") - var icon: String? = null, + @Json(name = "name") + val name: String? = null, - @field:Json(name = "speed") - var speed: Float? = null, + @Json(name = "forecast") + val forecast: List? = null, - @field:Json(name = "gust") - var gust: Float? = null, + @Json(name = "daily_forecast") + val dailyForecast: List? = null, - @field:Json(name = "direction") - var direction: Int? = null + @Json(name = "rain_product_available") + val rainProductAvailable: Int? = null ) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt index 6414acdb..feb74241 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/MeteoFranceProvider.kt @@ -1,6 +1,7 @@ package com.thewizrd.weather_api.meteofrance.weather import android.util.Log +import androidx.core.net.toUri import com.ibm.icu.util.ULocale import com.thewizrd.shared_resources.exceptions.ErrorStatus import com.thewizrd.shared_resources.exceptions.WeatherException @@ -49,9 +50,6 @@ import java.util.concurrent.TimeUnit class MeteoFranceProvider : WeatherProviderImpl() { companion object { private const val BASE_URL = "https://webservice.meteofrance.com/" - private const val CURRENT_QUERY_URL = BASE_URL + "observation/gridded?%s&lang=%s&token=%s" - private const val FORECAST_QUERY_URL = BASE_URL + "forecast?%s&lang=%s&token=%s" - private const val ALERTS_QUERY_URL = BASE_URL + "warning/full?domain=%s&token=%s" } init { @@ -145,13 +143,33 @@ class MeteoFranceProvider : WeatherProviderImpl() { throw WeatherException(ErrorStatus.INVALIDAPIKEY) } + val df = DecimalFormat.getInstance(Locale.ROOT) as DecimalFormat + df.applyPattern("0.####") + + val currentRequestUri = BASE_URL.toUri().buildUpon() + .appendPath("v2/observation") + .appendQueryParameter("lat", df.format(location.latitude)) + .appendQueryParameter("lon", df.format(location.longitude)) + .appendQueryParameter("lang", locale) + .appendQueryParameter("token", key) + .build() + val currentRequest = Request.Builder() .cacheRequestIfNeeded(isKeyRequired(), 15, TimeUnit.MINUTES) - .url(String.format(CURRENT_QUERY_URL, query, locale, key)) + .url(currentRequestUri.toString()) + .build() + + val forecastRequestUri = BASE_URL.toUri().buildUpon() + .appendPath("v2/forecast") + .appendQueryParameter("lat", df.format(location.latitude)) + .appendQueryParameter("lon", df.format(location.longitude)) + .appendQueryParameter("lang", locale) + .appendQueryParameter("token", key) .build() + val forecastRequest = Request.Builder() .cacheRequestIfNeeded(isKeyRequired(), 1, TimeUnit.HOURS) - .url(String.format(FORECAST_QUERY_URL, query, locale, key)) + .url(forecastRequestUri.toString()) .build() // Connect to webstream @@ -176,10 +194,16 @@ class MeteoFranceProvider : WeatherProviderImpl() { ) var alertsRoot: AlertsResponse? = null - if (foreRoot?.position?.dept != null) { + foreRoot?.properties?.frenchDepartment.let { dept -> + val alertsRequestUri = BASE_URL.toUri().buildUpon() + .appendPath("v3/warning/full") + .appendQueryParameter("domain", dept) + .appendQueryParameter("token", key) + .build() + val alertsRequest = Request.Builder() .cacheRequestIfNeeded(isKeyRequired(), 1, TimeUnit.HOURS) - .url(String.format(ALERTS_QUERY_URL, foreRoot.position!!.dept, key)) + .url(alertsRequestUri.toString()) .build() runCatching { diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/WeatherData.kt index fd96331d..45892327 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/meteofrance/weather/WeatherData.kt @@ -16,12 +16,10 @@ import com.thewizrd.shared_resources.weatherdata.model.Location import com.thewizrd.shared_resources.weatherdata.model.Precipitation import com.thewizrd.shared_resources.weatherdata.model.Weather import com.thewizrd.weather_api.weatherModule -import java.time.Instant -import java.time.LocalDateTime import java.time.ZoneOffset import java.time.ZonedDateTime +import java.time.temporal.ChronoUnit import java.util.Locale -import java.util.concurrent.TimeUnit import kotlin.math.roundToInt @SuppressLint("VisibleForTests") @@ -31,41 +29,40 @@ fun createWeatherData(currRoot: CurrentsResponse, foreRoot: ForecastResponse, location = createLocation(foreRoot) updateTime = ZonedDateTime.now(ZoneOffset.UTC) - forecast = ArrayList(foreRoot.dailyForecast!!.size) - hrForecast = ArrayList(foreRoot.forecast!!.size) - // Forecast - for (daily in foreRoot.dailyForecast!!) { - forecast!!.add(createForecast(daily!!)) + forecast = foreRoot.properties?.dailyForecast?.map { daily -> + createForecast(daily) } - - for (hourly in foreRoot.forecast!!) { - hrForecast!!.add(createHourlyForecast(hourly!!, foreRoot.probabilityForecast)) + hrForecast = foreRoot.properties?.forecast?.map { hourly -> + createHourlyForecast(hourly, foreRoot.properties.probabilityForecast) } condition = createCondition(currRoot) atmosphere = createAtmosphere(currRoot) + precipitation = createPrecipitation(currRoot) ttl = 180 // Observation only gives temp & wind if (!hrForecast.isNullOrEmpty()) { val firstHr = hrForecast!![0] - atmosphere!!.humidity = firstHr.extras.humidity - atmosphere!!.pressureMb = firstHr.extras.pressureMb - atmosphere!!.pressureIn = firstHr.extras.pressureIn - atmosphere!!.dewpointC = firstHr.extras.dewpointC - atmosphere!!.dewpointF = firstHr.extras.dewpointF - atmosphere!!.visibilityKm = firstHr.extras.visibilityKm - atmosphere!!.visibilityMi = firstHr.extras.visibilityMi - - precipitation = Precipitation().apply { - cloudiness = firstHr.extras.cloudiness - pop = firstHr.extras.pop - qpfRainIn = firstHr.extras.qpfRainIn - qpfRainMm = firstHr.extras.qpfRainMm - qpfSnowIn = firstHr.extras.qpfSnowIn - qpfSnowCm = firstHr.extras.qpfSnowCm + atmosphere?.run { + humidity = firstHr.extras?.humidity + pressureMb = firstHr.extras?.pressureMb + pressureIn = firstHr.extras?.pressureIn + dewpointC = firstHr.extras?.dewpointC + dewpointF = firstHr.extras?.dewpointF + visibilityKm = firstHr.extras?.visibilityKm + visibilityMi = firstHr.extras?.visibilityMi + } + + precipitation?.run { + cloudiness = firstHr.extras?.cloudiness + pop = firstHr.extras?.pop + qpfRainIn = firstHr.extras?.qpfRainIn + qpfRainMm = firstHr.extras?.qpfRainMm + qpfSnowIn = firstHr.extras?.qpfSnowIn + qpfSnowCm = firstHr.extras?.qpfSnowCm } } @@ -93,9 +90,9 @@ fun createLocation(foreRoot: ForecastResponse): Location { return Location().apply { // Use location name from location provider name = null - latitude = foreRoot.position?.lat - longitude = foreRoot.position?.lon - tzLong = foreRoot.position?.timezone + latitude = foreRoot.geometry?.coordinates?.getOrNull(1) + longitude = foreRoot.geometry?.coordinates?.getOrNull(0) + tzLong = foreRoot.properties?.timezone } } @@ -104,127 +101,122 @@ fun createForecast(day: DailyForecastItem): Forecast { val provider = weatherModule.weatherManager.getWeatherProvider(WeatherAPI.METEOFRANCE) val locale = LocaleUtils.getLocale() - date = LocalDateTime.ofEpochSecond(day.dt!!, 0, ZoneOffset.UTC) + date = ZonedDateTime.parse(day.time).toLocalDateTime() - day.T?.max?.let { + day.tMax?.let { highC = it highF = ConversionMethods.CtoF(it) } - day.T?.min?.let { + day.tMin?.let { lowC = it lowF = ConversionMethods.CtoF(it) } condition = - if (!day.weather12H?.desc.isNullOrBlank() && locale.toString() == "en" || locale.toString() + if (!day.dailyWeatherDescription.isNullOrBlank() && locale.toString() == "en" || locale.toString() .startsWith("en_") || locale.toString() == "fr" || locale.toString().startsWith("fr_") || locale == Locale.ROOT ) { - day.weather12H?.desc + day.dailyWeatherDescription } else { - provider.getWeatherCondition(provider.getWeatherIcon(false, day.weather12H?.icon)) + provider.getWeatherCondition(provider.getWeatherIcon(false, day.dailyWeatherIcon)) } - icon = day.weather12H?.icon + icon = day.dailyWeatherIcon // Extras extras = ForecastExtras() - if (day.humidity?.max != null && day.humidity?.min != null) { - extras.humidity = ((day.humidity!!.min!! + day.humidity!!.max!!) / 2f).roundToInt() + if (day.relativeHumidityMax != null && day.relativeHumidityMin != null) { + extras.humidity = + ((day.relativeHumidityMin + day.relativeHumidityMax) / 2f).roundToInt() } - day.T?.sea?.let { + day.tSea?.let { extras.pressureMb = it extras.pressureIn = ConversionMethods.mbToInHg(it) } - day.precipitation?.jsonMember24h?.let { + day.totalPrecipitation24h?.let { extras.qpfRainMm = it extras.qpfRainIn = ConversionMethods.mmToIn(it) } - extras.uvIndex = day.uv + extras.uvIndex = day.uvIndex } } fun createHourlyForecast(forecast: ForecastItem, - probabilityForecasts: List?): HourlyForecast { + probabilityForecasts: List? +): HourlyForecast { return HourlyForecast().apply { val provider = weatherModule.weatherManager.getWeatherProvider(WeatherAPI.METEOFRANCE) val locale = LocaleUtils.getLocale() - val date = Instant.ofEpochSecond(forecast.dt!!).atZone(ZoneOffset.UTC) - setDate(date) + date = ZonedDateTime.parse(forecast.time) - forecast.T?.value?.let { + forecast.t?.let { highC = it highF = ConversionMethods.CtoF(it) } condition = - if (!forecast.weather?.desc.isNullOrBlank() && locale.toString() == "en" || locale.toString() + if (!forecast.weatherDescription.isNullOrBlank() && locale.toString() == "en" || locale.toString() .startsWith("en_") || locale.toString() == "fr" || locale.toString().startsWith("fr_") || locale == Locale.ROOT ) { - forecast.weather?.desc + forecast.weatherDescription } else { - provider.getWeatherCondition(provider.getWeatherIcon(forecast.weather?.icon)) + provider.getWeatherCondition(provider.getWeatherIcon(forecast.weatherIcon)) } - icon = forecast.weather?.icon + icon = forecast.weatherIcon // Extras extras = ForecastExtras() - forecast.T?.windchill?.let { + forecast.tWindchill?.let { extras.feelslikeC = it extras.feelslikeF = ConversionMethods.CtoF(it) } - extras.humidity = forecast.humidity + extras.humidity = forecast.relativeHumidity - forecast.seaLevel?.let { + forecast.pSea?.let { extras.pressureMb = it extras.pressureIn = ConversionMethods.mbToInHg(it) } - if (forecast.wind != null) { - if (forecast.wind!!.speed != null && forecast.wind!!.direction != null) { - extras.windDegrees = forecast.wind!!.direction - extras.windMph = ConversionMethods.msecToMph(forecast.wind!!.speed!!) - extras.windKph = ConversionMethods.msecToKph(forecast.wind!!.speed!!) - } - if (forecast.wind!!.gust != null) { - extras.windGustKph = ConversionMethods.msecToKph(forecast.wind!!.gust!!) - extras.windGustMph = ConversionMethods.msecToMph(forecast.wind!!.gust!!) - } + forecast.windSpeed?.let { + extras.windMph = ConversionMethods.msecToMph(it) + extras.windKph = ConversionMethods.msecToKph(it) + extras.windDegrees = forecast.windDirection + } + forecast.windSpeedGust?.let { + extras.windGustKph = ConversionMethods.msecToKph(it) + extras.windGustMph = ConversionMethods.msecToMph(it) } - if (forecast.rain != null) { - if (forecast.rain!!.jsonMember1h != null) { - extras.qpfRainMm = forecast.rain!!.jsonMember1h - extras.qpfRainIn = ConversionMethods.mmToIn(forecast.rain!!.jsonMember1h!!) - } else if (forecast.rain!!.jsonMember3h != null) { - extras.qpfRainMm = forecast.rain!!.jsonMember3h - extras.qpfRainIn = ConversionMethods.mmToIn(forecast.rain!!.jsonMember3h!!) - } else if (forecast.rain!!.jsonMember6h != null) { - extras.qpfRainMm = forecast.rain!!.jsonMember6h - extras.qpfRainIn = ConversionMethods.mmToIn(forecast.rain!!.jsonMember6h!!) - } + if (forecast.rain1h != null) { + extras.qpfRainMm = forecast.rain1h + extras.qpfRainIn = ConversionMethods.mmToIn(forecast.rain1h) + } else if (forecast.rain3h != null) { + extras.qpfRainMm = forecast.rain3h + extras.qpfRainIn = ConversionMethods.mmToIn(forecast.rain3h) + } else if (forecast.rain6h != null) { + extras.qpfRainMm = forecast.rain6h + extras.qpfRainIn = ConversionMethods.mmToIn(forecast.rain6h) } - if (forecast.snow != null) { - if (forecast.snow!!.jsonMember1h != null) { - extras.qpfSnowCm = forecast.snow!!.jsonMember1h!! / 10 - extras.qpfRainIn = ConversionMethods.mmToIn(forecast.snow!!.jsonMember1h!!) - } else if (forecast.snow!!.jsonMember3h != null) { - extras.qpfSnowCm = forecast.snow!!.jsonMember3h!! / 10 - extras.qpfRainIn = ConversionMethods.mmToIn(forecast.snow!!.jsonMember3h!!) - } else if (forecast.snow!!.jsonMember6h != null) { - extras.qpfSnowCm = forecast.snow!!.jsonMember6h!! / 10 - extras.qpfRainIn = ConversionMethods.mmToIn(forecast.snow!!.jsonMember6h!!) - } + if (forecast.snow1h != null) { + extras.qpfSnowCm = forecast.snow1h / 10 + extras.qpfRainIn = ConversionMethods.mmToIn(forecast.snow1h) + } else if (forecast.snow3h != null) { + extras.qpfSnowCm = forecast.snow3h / 10 + extras.qpfRainIn = ConversionMethods.mmToIn(forecast.snow3h) + } else if (forecast.snow6h != null) { + extras.qpfSnowCm = forecast.snow6h / 10 + extras.qpfRainIn = ConversionMethods.mmToIn(forecast.snow6h) } - extras.cloudiness = forecast.clouds + extras.cloudiness = forecast.totalCloudCover if (highC != null && extras.humidity != null) { extras.dewpointC = calculateDewpointC(highC, extras.humidity) @@ -236,48 +228,59 @@ fun createHourlyForecast(forecast: ForecastItem, if (!probabilityForecasts.isNullOrEmpty()) { // Note: probability forecasts are given either every 3 or 6 hours // Rain/Snow object can contain forecast for either next 3 or 6 hrs, or both - val dt = forecast.dt!! // Unix time in seconds - val hrsInSec = TimeUnit.HOURS.toSeconds(1) + val dt = date.truncatedTo(ChronoUnit.HOURS) var found3hrForecast = false var _3hrForecastNA = false for (prob in probabilityForecasts) { + val probDt = ZonedDateTime.parse(prob.time).truncatedTo(ChronoUnit.HOURS) + // Check if timestamp is within 3-hr forecast - if (dt == prob!!.dt!! || dt == (prob.dt!! + hrsInSec) || dt == (prob.dt!! + hrsInSec * 2)) { - if (prob.rain?.jsonMember3h != null) { - extras.pop = prob.rain!!.jsonMember3h!!.toInt() + if (dt.isEqual(probDt) || dt.isEqual(probDt.plusHours(1)) || dt.isEqual( + probDt.plusHours( + 2 + ) + ) + ) { + if (prob.rainHazard3h != null) { + extras.pop = prob.rainHazard3h.toInt() found3hrForecast = true _3hrForecastNA = false } else { found3hrForecast = false _3hrForecastNA = true } - if (extras.pop == null && prob.rain?.jsonMember6h != null) { - extras.pop = prob.rain!!.jsonMember6h!!.toInt() + if (extras.pop == null && prob.rainHazard3h != null) { + extras.pop = prob.rainHazard3h.toInt() _3hrForecastNA = true found3hrForecast = false } if (extras.pop == null) { - if (prob.snow?.jsonMember3h != null) { - extras.pop = prob.snow!!.jsonMember3h!!.toInt() + if (prob.snowHazard3h != null) { + extras.pop = prob.snowHazard3h.toInt() } - if (prob.snow?.jsonMember6h != null) { - extras.pop = prob.snow!!.jsonMember6h!!.toInt() + if (prob.snowHazard6h != null) { + extras.pop = prob.snowHazard6h.toInt() } } } // Timestamp is not within 3-hr forecast; check 6-hr timeframe // Check if timestamp is within 6-hr forecast - if (extras.pop == null && (dt == (prob.dt!! + hrsInSec * 3) || dt == (prob.dt!! + hrsInSec * 4) || dt == (prob.dt!! + hrsInSec * 5))) { - if (prob.rain!!.jsonMember6h != null) { - extras.pop = prob.rain!!.jsonMember6h!!.toInt() + if (extras.pop == null && (dt.isEqual(probDt.plusHours(3)) || dt.isEqual( + probDt.plusHours( + 4 + ) + ) || dt.isEqual(probDt.plusHours(5))) + ) { + if (prob.rainHazard6h != null) { + extras.pop = prob.rainHazard6h.toInt() _3hrForecastNA = true found3hrForecast = false } if (extras.pop == null) { - if (prob.snow!!.jsonMember6h != null) { - extras.pop = prob.snow!!.jsonMember6h!!.toInt() + if (prob.snowHazard6h != null) { + extras.pop = prob.snowHazard6h.toInt() } } } @@ -293,34 +296,35 @@ fun createCondition(currRoot: CurrentsResponse): Condition { val provider = weatherModule.weatherManager.getWeatherProvider(WeatherAPI.METEOFRANCE) val locale = LocaleUtils.getLocale() - currRoot.observation?.T?.let { + currRoot.properties?.gridded?.t?.let { tempC = it tempF = ConversionMethods.CtoF(it) } weather = - if (!currRoot.observation?.weather?.desc.isNullOrBlank() && locale.toString() == "en" || locale.toString() + if (!currRoot.properties?.gridded?.weatherDescription.isNullOrBlank() && locale.toString() == "en" || locale.toString() .startsWith("en_") || locale.toString() == "fr" || locale.toString().startsWith("fr_") || locale == Locale.ROOT ) { - currRoot.observation?.weather?.desc + currRoot.properties?.gridded?.weatherDescription } else { - provider.getWeatherCondition(provider.getWeatherIcon(currRoot.observation?.weather?.icon)) - } - icon = currRoot.observation?.weather?.icon - - if (currRoot.observation!!.wind != null) { - windDegrees = currRoot.observation!!.wind!!.direction - if (currRoot.observation!!.wind!!.speed != null) { - windKph = - ConversionMethods.msecToKph(currRoot.observation!!.wind!!.speed!!) - windMph = - ConversionMethods.msecToMph(currRoot.observation!!.wind!!.speed!!) + provider.getWeatherCondition(provider.getWeatherIcon(currRoot.properties?.gridded?.weatherIcon)) } + icon = currRoot.properties?.gridded?.weatherIcon + + windDegrees = currRoot.properties?.gridded?.windDirection + currRoot.properties?.gridded?.windSpeed?.let { + windKph = ConversionMethods.msecToKph(it) + windMph = ConversionMethods.msecToMph(it) + } + currRoot.properties?.gridded?.windSpeedGust?.let { + windGustKph = ConversionMethods.msecToKph(it) + windGustMph = ConversionMethods.msecToMph(it) } - observationTime = ZonedDateTime.ofInstant(Instant.ofEpochSecond(currRoot.updatedOn!!), ZoneOffset.UTC) + observationTime = + ZonedDateTime.parse(currRoot.properties?.gridded?.time ?: currRoot.updateTime) } } @@ -328,4 +332,10 @@ fun createAtmosphere(currRoot: CurrentsResponse): Atmosphere { return Atmosphere().apply { // no-op } +} + +fun createPrecipitation(currRoot: CurrentsResponse): Precipitation { + return Precipitation().apply { + // no-op + } } \ No newline at end of file From 39fdfbadbff9d0fb760005d1e363776d1c7168d5 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Fri, 3 Jul 2026 23:59:31 -0400 Subject: [PATCH 57/67] OpenWeatherMapProvider: nullables --- .../openweather/weather/Coord.java | 12 ++++---- .../weather_api/openweather/weather/Main.java | 30 +++++++++---------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/Coord.java b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/Coord.java index 74fda99d..e3ca1fe3 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/Coord.java +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/Coord.java @@ -7,24 +7,24 @@ public class Coord { @Json(name = "lon") - private float lon; + private Float lon; @Json(name = "lat") - private float lat; + private Float lat; - public void setLon(float lon) { + public void setLon(Float lon) { this.lon = lon; } - public float getLon() { + public Float getLon() { return lon; } - public void setLat(float lat) { + public void setLat(Float lat) { this.lat = lat; } - public float getLat() { + public Float getLat() { return lat; } } \ No newline at end of file diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/Main.java b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/Main.java index 8a41c06f..40c6207a 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/Main.java +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openweather/weather/Main.java @@ -7,22 +7,22 @@ public class Main { @Json(name = "temp") - private float temp; + private Float temp; @Json(name = "feels_like") private Float feelsLike; @Json(name = "temp_min") - private float tempMin; + private Float tempMin; @Json(name = "temp_max") - private float tempMax; + private Float tempMax; @Json(name = "humidity") - private int humidity; + private Integer humidity; @Json(name = "pressure") - private float pressure; + private Float pressure; @Json(name = "sea_level") private Float seaLevel; @@ -30,11 +30,11 @@ public class Main { @Json(name = "grnd_level") private Float grndLevel; - public void setTemp(float temp) { + public void setTemp(Float temp) { this.temp = temp; } - public float getTemp() { + public Float getTemp() { return temp; } @@ -46,35 +46,35 @@ public Float getFeelsLike() { return feelsLike; } - public void setTempMin(float tempMin) { + public void setTempMin(Float tempMin) { this.tempMin = tempMin; } - public float getTempMin() { + public Float getTempMin() { return tempMin; } - public void setHumidity(int humidity) { + public void setHumidity(Integer humidity) { this.humidity = humidity; } - public int getHumidity() { + public Integer getHumidity() { return humidity; } - public void setPressure(float pressure) { + public void setPressure(Float pressure) { this.pressure = pressure; } - public float getPressure() { + public Float getPressure() { return pressure; } - public void setTempMax(float tempMax) { + public void setTempMax(Float tempMax) { this.tempMax = tempMax; } - public float getTempMax() { + public Float getTempMax() { return tempMax; } From 78fd25e1bfae9b3cfbcd9d6c54bfe98108707345 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 4 Jul 2026 00:06:10 -0400 Subject: [PATCH 58/67] gradle: update dependencies --- gradle/libs.versions.toml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2c009368..039ffdea 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -48,14 +48,15 @@ google_truth_version = '1.4.5' espresso_core_version = "3.7.0" material_version = "1.14.0" -material_compose_version = "1.5.0-alpha22" +material_compose_version = "1.5.0-alpha23" compose_compiler_version = '1.5.15' -compose_bom_version = "2026.06.00" +compose_bom_version = "2026.06.01" wear_version = "1.4.0" wear_compose_version = "1.6.2" wear_input_version = '1.2.0' -wear_tiles_version = "1.6.0" +wear_protolayout_version = "1.4.1" +wear_tiles_version = "1.6.1" wear_watchface_version = "1.3.0" horologist_version = '0.7.15' accompanist_version = '0.37.3' @@ -67,7 +68,7 @@ moshi_version = '1.15.2' okhttp_version = "5.4.0" timber_version = '5.0.1' -revcat_version = "10.11.0" +revcat_version = "10.12.0" [libraries] com-google-devtools-ksp-gradle-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp_version" } @@ -144,8 +145,8 @@ wear-tiles-renderer = { module = "androidx.wear.tiles:tiles-renderer", version.r wear-tiles-testing = { module = "androidx.wear.tiles:tiles-testing", version.ref = "wear_tiles_version" } wear-tiles-tooling = { module = "androidx.wear.tiles:tiles-tooling", version.ref = "wear_tiles_version" } wear-tiles-tooling-preview = { module = "androidx.wear.tiles:tiles-tooling-preview", version.ref = "wear_tiles_version" } -wear-protolayout-material = { module = "androidx.wear.protolayout:protolayout-material", version.ref = "wear_version" } -wear-protolayout-material3 = { module = "androidx.wear.protolayout:protolayout-material3", version.ref = "wear_version" } +wear-protolayout-material = { module = "androidx.wear.protolayout:protolayout-material", version.ref = "wear_protolayout_version" } +wear-protolayout-material3 = { module = "androidx.wear.protolayout:protolayout-material3", version.ref = "wear_protolayout_version" } horologist-tiles = { module = "com.google.android.horologist:horologist-tiles", version.ref = "horologist_version" } activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activity_version" } compose-compiler = { module = "androidx.compose.compiler:compiler", version.ref = "compose_compiler_version" } From 8d3b63ef204a2727103f9cba725da533794217cf Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 4 Jul 2026 00:06:36 -0400 Subject: [PATCH 59/67] SimpleWeather: v5.14.0-build9 --- app/build.gradle | 2 +- wearapp/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e75e15f4..49375fdc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get().toInteger() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code (Android: 0, WearOS: 1) // ex) 345100131 = (34, 5.10, 013, 0) - versionCode 375140080 + versionCode 375140090 versionName "5.14.0" vectorDrawables { diff --git a/wearapp/build.gradle b/wearapp/build.gradle index a72a6cd8..d08a7767 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -16,7 +16,7 @@ android { targetSdkVersion libs.versions.wearTargetSdkVersion.get() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code [Android: 0, WearOS: 1]) // ex) 345100131 = (34, 5.10, 013, 1) - versionCode 365140081 + versionCode 365140091 versionName "5.14.0" vectorDrawables { From d176cb68b00908f46d475a737350723887efd73f Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Fri, 17 Jul 2026 00:19:49 -0400 Subject: [PATCH 60/67] icons: fix google weather icon compatibility --- .../drawable-night-v24/goog_blowing_snow.xml | 79 ++++++++++++ .../res/drawable-night-v24/goog_clear_day.xml | 30 +++++ .../drawable-night-v24/goog_clear_night.xml | 30 +++++ .../res/drawable-night-v24/goog_cloudy.xml | 31 +++++ .../main/res/drawable-night-v24/goog_hail.xml | 77 +++++++++++ .../drawable-night-v24/goog_heavy_rain.xml | 39 ++++++ .../drawable-night-v24/goog_heavy_snow.xml | 121 ++++++++++++++++++ .../drawable-night-v24/goog_light_rain.xml | 38 ++++++ .../drawable-night-v24/goog_light_snow.xml | 46 +++++++ .../goog_mostly_clear_day.xml | 67 ++++++++++ .../goog_mostly_clear_night.xml | 74 +++++++++++ .../goog_mostly_cloudy_day.xml | 70 ++++++++++ .../goog_mostly_cloudy_night.xml | 70 ++++++++++ .../goog_partly_cloudy_day.xml | 67 ++++++++++ .../goog_partly_cloudy_night.xml | 70 ++++++++++ .../res/drawable-night-v24/goog_rain_mix.xml | 49 +++++++ .../goog_scattered_showers.xml | 58 +++++++++ .../goog_scattered_tstorms.xml | 58 +++++++++ .../main/res/drawable-night-v24/goog_snow.xml | 41 ++++++ .../drawable-night-v24/goog_snow_showers.xml | 85 ++++++++++++ .../res/drawable-night-v24/goog_tstorm.xml | 55 ++++++++ .../res/drawable-night-v24/goog_wind_rain.xml | 70 ++++++++++ .../res/drawable-night-v24/goog_windy.xml | 47 +++++++ .../res/drawable-night/goog_blowing_snow.xml | 21 +-- .../res/drawable-night/goog_clear_day.xml | 21 +-- .../res/drawable-night/goog_clear_night.xml | 20 +-- .../main/res/drawable-night/goog_cloudy.xml | 21 +-- .../src/main/res/drawable-night/goog_hail.xml | 40 +----- .../res/drawable-night/goog_heavy_rain.xml | 21 +-- .../res/drawable-night/goog_heavy_snow.xml | 40 +----- .../res/drawable-night/goog_light_rain.xml | 21 +-- .../res/drawable-night/goog_light_snow.xml | 21 +-- .../drawable-night/goog_mostly_clear_day.xml | 61 ++------- .../goog_mostly_clear_night.xml | 60 ++------- .../drawable-night/goog_mostly_cloudy_day.xml | 60 ++------- .../goog_mostly_cloudy_night.xml | 60 ++------- .../drawable-night/goog_partly_cloudy_day.xml | 61 ++------- .../goog_partly_cloudy_night.xml | 59 +-------- .../main/res/drawable-night/goog_rain_mix.xml | 21 +-- .../drawable-night/goog_scattered_showers.xml | 40 +----- .../drawable-night/goog_scattered_tstorms.xml | 40 +----- .../src/main/res/drawable-night/goog_snow.xml | 21 +-- .../res/drawable-night/goog_snow_showers.xml | 40 +----- .../main/res/drawable-night/goog_tstorm.xml | 40 +----- .../res/drawable-night/goog_wind_rain.xml | 40 +----- .../main/res/drawable-night/goog_windy.xml | 21 +-- .../res/drawable-v24/goog_blowing_snow.xml | 57 +++++++++ .../main/res/drawable-v24/goog_clear_day.xml | 34 +++++ .../res/drawable-v24/goog_clear_night.xml | 30 +++++ .../src/main/res/drawable-v24/goog_cloudy.xml | 34 +++++ .../src/main/res/drawable-v24/goog_hail.xml | 66 ++++++++++ .../main/res/drawable-v24/goog_heavy_rain.xml | 57 +++++++++ .../main/res/drawable-v24/goog_heavy_snow.xml | 56 ++++++++ .../main/res/drawable-v24/goog_light_rain.xml | 38 ++++++ .../main/res/drawable-v24/goog_light_snow.xml | 41 ++++++ .../drawable-v24/goog_mostly_clear_day.xml | 72 +++++++++++ .../drawable-v24/goog_mostly_clear_night.xml | 76 +++++++++++ .../drawable-v24/goog_mostly_cloudy_day.xml | 72 +++++++++++ .../drawable-v24/goog_mostly_cloudy_night.xml | 72 +++++++++++ .../drawable-v24/goog_partly_cloudy_day.xml | 72 +++++++++++ .../drawable-v24/goog_partly_cloudy_night.xml | 72 +++++++++++ .../main/res/drawable-v24/goog_rain_mix.xml | 105 +++++++++++++++ .../drawable-v24/goog_scattered_showers.xml | 53 ++++++++ .../drawable-v24/goog_scattered_tstorms.xml | 57 +++++++++ .../src/main/res/drawable-v24/goog_snow.xml | 95 ++++++++++++++ .../res/drawable-v24/goog_snow_showers.xml | 56 ++++++++ .../src/main/res/drawable-v24/goog_tstorm.xml | 61 +++++++++ .../main/res/drawable-v24/goog_wind_rain.xml | 53 ++++++++ .../src/main/res/drawable-v24/goog_windy.xml | 50 ++++++++ .../main/res/drawable/goog_blowing_snow.xml | 20 +-- .../src/main/res/drawable/goog_clear_day.xml | 20 +-- .../main/res/drawable/goog_clear_night.xml | 20 +-- .../src/main/res/drawable/goog_cloudy.xml | 20 +-- .../src/main/res/drawable/goog_hail.xml | 39 +----- .../src/main/res/drawable/goog_heavy_rain.xml | 39 +----- .../src/main/res/drawable/goog_heavy_snow.xml | 39 +----- .../src/main/res/drawable/goog_light_rain.xml | 20 +-- .../src/main/res/drawable/goog_light_snow.xml | 20 +-- .../res/drawable/goog_mostly_clear_day.xml | 59 +-------- .../res/drawable/goog_mostly_clear_night.xml | 59 +-------- .../res/drawable/goog_mostly_cloudy_day.xml | 58 +-------- .../res/drawable/goog_mostly_cloudy_night.xml | 59 +-------- .../res/drawable/goog_partly_cloudy_day.xml | 59 +-------- .../res/drawable/goog_partly_cloudy_night.xml | 59 +-------- .../src/main/res/drawable/goog_rain_mix.xml | 20 +-- .../res/drawable/goog_scattered_showers.xml | 39 +----- .../res/drawable/goog_scattered_tstorms.xml | 39 +----- .../src/main/res/drawable/goog_snow.xml | 20 +-- .../main/res/drawable/goog_snow_showers.xml | 39 +----- .../src/main/res/drawable/goog_tstorm.xml | 39 +----- .../src/main/res/drawable/goog_wind_rain.xml | 39 +----- .../src/main/res/drawable/goog_windy.xml | 20 +-- 92 files changed, 2957 insertions(+), 1489 deletions(-) create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_blowing_snow.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_clear_day.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_clear_night.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_cloudy.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_hail.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_heavy_rain.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_heavy_snow.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_light_rain.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_light_snow.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_mostly_clear_day.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_mostly_clear_night.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_mostly_cloudy_day.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_mostly_cloudy_night.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_partly_cloudy_day.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_partly_cloudy_night.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_rain_mix.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_scattered_showers.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_scattered_tstorms.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_snow.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_snow_showers.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_tstorm.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_wind_rain.xml create mode 100644 shared_resources/src/main/res/drawable-night-v24/goog_windy.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_blowing_snow.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_clear_day.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_clear_night.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_cloudy.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_hail.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_heavy_rain.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_heavy_snow.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_light_rain.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_light_snow.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_mostly_clear_day.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_mostly_clear_night.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_mostly_cloudy_day.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_mostly_cloudy_night.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_partly_cloudy_day.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_partly_cloudy_night.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_rain_mix.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_scattered_showers.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_scattered_tstorms.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_snow.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_snow_showers.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_tstorm.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_wind_rain.xml create mode 100644 shared_resources/src/main/res/drawable-v24/goog_windy.xml diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_blowing_snow.xml b/shared_resources/src/main/res/drawable-night-v24/goog_blowing_snow.xml new file mode 100644 index 00000000..ce20d718 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_blowing_snow.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_clear_day.xml b/shared_resources/src/main/res/drawable-night-v24/goog_clear_day.xml new file mode 100644 index 00000000..d9442652 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_clear_day.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_clear_night.xml b/shared_resources/src/main/res/drawable-night-v24/goog_clear_night.xml new file mode 100644 index 00000000..38a2d7b9 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_clear_night.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_cloudy.xml b/shared_resources/src/main/res/drawable-night-v24/goog_cloudy.xml new file mode 100644 index 00000000..d3866416 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_cloudy.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_hail.xml b/shared_resources/src/main/res/drawable-night-v24/goog_hail.xml new file mode 100644 index 00000000..1d841d24 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_hail.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_heavy_rain.xml b/shared_resources/src/main/res/drawable-night-v24/goog_heavy_rain.xml new file mode 100644 index 00000000..a84ee71d --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_heavy_rain.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_heavy_snow.xml b/shared_resources/src/main/res/drawable-night-v24/goog_heavy_snow.xml new file mode 100644 index 00000000..dade37c4 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_heavy_snow.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_light_rain.xml b/shared_resources/src/main/res/drawable-night-v24/goog_light_rain.xml new file mode 100644 index 00000000..7b124678 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_light_rain.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_light_snow.xml b/shared_resources/src/main/res/drawable-night-v24/goog_light_snow.xml new file mode 100644 index 00000000..654bdd38 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_light_snow.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_mostly_clear_day.xml b/shared_resources/src/main/res/drawable-night-v24/goog_mostly_clear_day.xml new file mode 100644 index 00000000..050c5466 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_mostly_clear_day.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_mostly_clear_night.xml b/shared_resources/src/main/res/drawable-night-v24/goog_mostly_clear_night.xml new file mode 100644 index 00000000..d60859ab --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_mostly_clear_night.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_mostly_cloudy_day.xml b/shared_resources/src/main/res/drawable-night-v24/goog_mostly_cloudy_day.xml new file mode 100644 index 00000000..a33f3307 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_mostly_cloudy_day.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_mostly_cloudy_night.xml b/shared_resources/src/main/res/drawable-night-v24/goog_mostly_cloudy_night.xml new file mode 100644 index 00000000..5c76018c --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_mostly_cloudy_night.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_partly_cloudy_day.xml b/shared_resources/src/main/res/drawable-night-v24/goog_partly_cloudy_day.xml new file mode 100644 index 00000000..07804422 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_partly_cloudy_day.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_partly_cloudy_night.xml b/shared_resources/src/main/res/drawable-night-v24/goog_partly_cloudy_night.xml new file mode 100644 index 00000000..58a8bb84 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_partly_cloudy_night.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_rain_mix.xml b/shared_resources/src/main/res/drawable-night-v24/goog_rain_mix.xml new file mode 100644 index 00000000..3f7c061f --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_rain_mix.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_scattered_showers.xml b/shared_resources/src/main/res/drawable-night-v24/goog_scattered_showers.xml new file mode 100644 index 00000000..e70dee6c --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_scattered_showers.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_scattered_tstorms.xml b/shared_resources/src/main/res/drawable-night-v24/goog_scattered_tstorms.xml new file mode 100644 index 00000000..224eb07a --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_scattered_tstorms.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_snow.xml b/shared_resources/src/main/res/drawable-night-v24/goog_snow.xml new file mode 100644 index 00000000..17fb1d58 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_snow.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_snow_showers.xml b/shared_resources/src/main/res/drawable-night-v24/goog_snow_showers.xml new file mode 100644 index 00000000..568a5432 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_snow_showers.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_tstorm.xml b/shared_resources/src/main/res/drawable-night-v24/goog_tstorm.xml new file mode 100644 index 00000000..dc7c41be --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_tstorm.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_wind_rain.xml b/shared_resources/src/main/res/drawable-night-v24/goog_wind_rain.xml new file mode 100644 index 00000000..e29389c3 --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_wind_rain.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night-v24/goog_windy.xml b/shared_resources/src/main/res/drawable-night-v24/goog_windy.xml new file mode 100644 index 00000000..de5cb2ae --- /dev/null +++ b/shared_resources/src/main/res/drawable-night-v24/goog_windy.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-night/goog_blowing_snow.xml b/shared_resources/src/main/res/drawable-night/goog_blowing_snow.xml index ce20d718..d2ac7140 100644 --- a/shared_resources/src/main/res/drawable-night/goog_blowing_snow.xml +++ b/shared_resources/src/main/res/drawable-night/goog_blowing_snow.xml @@ -1,5 +1,4 @@ - - - - - - - - + - - - - - - - - + - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFFBBC04" /> diff --git a/shared_resources/src/main/res/drawable-night/goog_cloudy.xml b/shared_resources/src/main/res/drawable-night/goog_cloudy.xml index d3866416..7d1f1f9d 100644 --- a/shared_resources/src/main/res/drawable-night/goog_cloudy.xml +++ b/shared_resources/src/main/res/drawable-night/goog_cloudy.xml @@ -1,5 +1,4 @@ - - - - - - - - + - - - - - - - - + - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - - + - - - - - - - - + - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - - + - - - - - - - - + - - - - - - - - - - - - - - - - + + - - - - - - - + android:fillType="evenOdd" + android:fillAlpha="0.5" + android:fillColor="#FFFCD35C" /> - - - - - - - - - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFFBBC04" /> + - - - - - - - + android:fillType="evenOdd" + android:fillAlpha="0.5" + android:fillColor="#FFFCD35C" /> - - - - - - - - - - - - - - - - + + - - - - - - - + android:fillType="evenOdd" + android:fillAlpha="0.5" + android:fillColor="#FFFCD35C" /> - - - - - - - - - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFFBBC04" /> + - - - - - - - + android:fillType="evenOdd" + android:fillAlpha="0.5" + android:fillColor="#FFFCD35C" /> diff --git a/shared_resources/src/main/res/drawable-night/goog_partly_cloudy_day.xml b/shared_resources/src/main/res/drawable-night/goog_partly_cloudy_day.xml index 07804422..19ef6433 100644 --- a/shared_resources/src/main/res/drawable-night/goog_partly_cloudy_day.xml +++ b/shared_resources/src/main/res/drawable-night/goog_partly_cloudy_day.xml @@ -1,5 +1,4 @@ - - - - - - - - - - - - - - - - + + - - - - - - - + android:fillType="evenOdd" + android:fillAlpha="0.5" + android:fillColor="#FFFCD35C" /> - - - - - - - - - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFFBBC04" /> + - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFFCD35C" /> - - - - - - - - + - - - - - - - - + - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - - + - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - - + - - - - - - - - + - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - - + - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - - + - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - - + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_clear_day.xml b/shared_resources/src/main/res/drawable-v24/goog_clear_day.xml new file mode 100644 index 00000000..89dece89 --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_clear_day.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_clear_night.xml b/shared_resources/src/main/res/drawable-v24/goog_clear_night.xml new file mode 100644 index 00000000..a00bb1ff --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_clear_night.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_cloudy.xml b/shared_resources/src/main/res/drawable-v24/goog_cloudy.xml new file mode 100644 index 00000000..aaf8d139 --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_cloudy.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_hail.xml b/shared_resources/src/main/res/drawable-v24/goog_hail.xml new file mode 100644 index 00000000..5b39139a --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_hail.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_heavy_rain.xml b/shared_resources/src/main/res/drawable-v24/goog_heavy_rain.xml new file mode 100644 index 00000000..96a86898 --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_heavy_rain.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_heavy_snow.xml b/shared_resources/src/main/res/drawable-v24/goog_heavy_snow.xml new file mode 100644 index 00000000..f1358486 --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_heavy_snow.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_light_rain.xml b/shared_resources/src/main/res/drawable-v24/goog_light_rain.xml new file mode 100644 index 00000000..dfda62ac --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_light_rain.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_light_snow.xml b/shared_resources/src/main/res/drawable-v24/goog_light_snow.xml new file mode 100644 index 00000000..a7f4e9ec --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_light_snow.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_mostly_clear_day.xml b/shared_resources/src/main/res/drawable-v24/goog_mostly_clear_day.xml new file mode 100644 index 00000000..9af6744f --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_mostly_clear_day.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_mostly_clear_night.xml b/shared_resources/src/main/res/drawable-v24/goog_mostly_clear_night.xml new file mode 100644 index 00000000..b385be48 --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_mostly_clear_night.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_mostly_cloudy_day.xml b/shared_resources/src/main/res/drawable-v24/goog_mostly_cloudy_day.xml new file mode 100644 index 00000000..8d699d75 --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_mostly_cloudy_day.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_mostly_cloudy_night.xml b/shared_resources/src/main/res/drawable-v24/goog_mostly_cloudy_night.xml new file mode 100644 index 00000000..7aeb2e66 --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_mostly_cloudy_night.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_partly_cloudy_day.xml b/shared_resources/src/main/res/drawable-v24/goog_partly_cloudy_day.xml new file mode 100644 index 00000000..36abed8c --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_partly_cloudy_day.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_partly_cloudy_night.xml b/shared_resources/src/main/res/drawable-v24/goog_partly_cloudy_night.xml new file mode 100644 index 00000000..51f1450a --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_partly_cloudy_night.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_rain_mix.xml b/shared_resources/src/main/res/drawable-v24/goog_rain_mix.xml new file mode 100644 index 00000000..63681f1b --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_rain_mix.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_scattered_showers.xml b/shared_resources/src/main/res/drawable-v24/goog_scattered_showers.xml new file mode 100644 index 00000000..6996321f --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_scattered_showers.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_scattered_tstorms.xml b/shared_resources/src/main/res/drawable-v24/goog_scattered_tstorms.xml new file mode 100644 index 00000000..ab67134a --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_scattered_tstorms.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_snow.xml b/shared_resources/src/main/res/drawable-v24/goog_snow.xml new file mode 100644 index 00000000..e781a325 --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_snow.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_snow_showers.xml b/shared_resources/src/main/res/drawable-v24/goog_snow_showers.xml new file mode 100644 index 00000000..52eaceb5 --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_snow_showers.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_tstorm.xml b/shared_resources/src/main/res/drawable-v24/goog_tstorm.xml new file mode 100644 index 00000000..233c2aac --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_tstorm.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_wind_rain.xml b/shared_resources/src/main/res/drawable-v24/goog_wind_rain.xml new file mode 100644 index 00000000..453299fe --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_wind_rain.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable-v24/goog_windy.xml b/shared_resources/src/main/res/drawable-v24/goog_windy.xml new file mode 100644 index 00000000..8cd19dda --- /dev/null +++ b/shared_resources/src/main/res/drawable-v24/goog_windy.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + diff --git a/shared_resources/src/main/res/drawable/goog_blowing_snow.xml b/shared_resources/src/main/res/drawable/goog_blowing_snow.xml index ec9d4238..f109b696 100644 --- a/shared_resources/src/main/res/drawable/goog_blowing_snow.xml +++ b/shared_resources/src/main/res/drawable/goog_blowing_snow.xml @@ -1,5 +1,4 @@ - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFFBBC04" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFFBBC04" /> diff --git a/shared_resources/src/main/res/drawable/goog_cloudy.xml b/shared_resources/src/main/res/drawable/goog_cloudy.xml index aaf8d139..52e0b0a4 100644 --- a/shared_resources/src/main/res/drawable/goog_cloudy.xml +++ b/shared_resources/src/main/res/drawable/goog_cloudy.xml @@ -1,5 +1,4 @@ - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFFBBC04" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDEDFDF" /> - - - - - - - + android:fillType="evenOdd" + android:fillAlpha="0.5" + android:fillColor="#FFFCD35C" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFFBBC04" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDEDFDF" /> - - - - - - - + android:fillType="evenOdd" + android:fillAlpha="0.5" + android:fillColor="#FFFCD35C" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFFBBC04" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillAlpha="0.5" + android:fillColor="#FFFCD35C" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFFBBC04" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillAlpha="0.5" + android:fillColor="#FFFCD35C" /> diff --git a/shared_resources/src/main/res/drawable/goog_partly_cloudy_day.xml b/shared_resources/src/main/res/drawable/goog_partly_cloudy_day.xml index 36abed8c..ff7c26bf 100644 --- a/shared_resources/src/main/res/drawable/goog_partly_cloudy_day.xml +++ b/shared_resources/src/main/res/drawable/goog_partly_cloudy_day.xml @@ -1,5 +1,4 @@ - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFFBBC04" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDEDFDF" /> - - - - - - - + android:fillType="evenOdd" + android:fillAlpha="0.5" + android:fillColor="#FFFCD35C" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFFBBC04" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDEDFDF" /> - - - - - - - + android:fillType="evenOdd" + android:fillAlpha="0.5" + android:fillColor="#FFFCD35C" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDEDFDF" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDEDFDF" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFF1F3F4" /> - - - - - - - + android:fillType="evenOdd" + android:fillColor="#FFDADCE0" /> Date: Fri, 17 Jul 2026 00:52:43 -0400 Subject: [PATCH 61/67] bug fixes --- .../simpleweather/controls/viewmodels/ChartsViewModel.kt | 2 +- .../main/java/com/thewizrd/common/controls/IconControl.kt | 6 +++++- .../java/com/thewizrd/weather_api/openmeteo/WeatherData.kt | 2 +- .../weather_api/weatherapi/weather/WeatherApiProvider.kt | 3 +++ .../thewizrd/weather_api/weatherapi/weather/WeatherData.kt | 6 +++--- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ChartsViewModel.kt b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ChartsViewModel.kt index a29b6543..3cf97a64 100644 --- a/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ChartsViewModel.kt +++ b/app/src/main/java/com/thewizrd/simpleweather/controls/viewmodels/ChartsViewModel.kt @@ -86,7 +86,7 @@ class ChartsViewModel(app: Application) : AndroidViewModel(app) { ?: ZoneOffset.UTC ).truncatedTo(ChronoUnit.HOURS) Pair( - input.first?.minForecast?.filter { !it.date.isBefore(now) }?.take(60), + input.first?.minForecast?.filter { !it.date.isBefore(now) }, input.second ) } else { diff --git a/common/src/main/java/com/thewizrd/common/controls/IconControl.kt b/common/src/main/java/com/thewizrd/common/controls/IconControl.kt index 772707c1..903f063a 100644 --- a/common/src/main/java/com/thewizrd/common/controls/IconControl.kt +++ b/common/src/main/java/com/thewizrd/common/controls/IconControl.kt @@ -166,7 +166,11 @@ class IconControl : AppCompatImageView { } private fun updateIconTint() { - if (showAsMonochrome || wim.isFontIcon) { + val wip = wim.getIconProvider( + iconProvider ?: SettingsManager(context).getIconsProvider() + ) + + if (showAsMonochrome || wip.isFontIcon) { ImageViewCompat.setImageTintList(this, mIconTint) } else { val tint = mIconTint diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/WeatherData.kt index 9e1c9aa5..9358be8e 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/openmeteo/WeatherData.kt @@ -186,7 +186,7 @@ fun createHourlyForecasts(hourly: Hourly): List? { hourly.snowfall?.getOrNull(index)?.let { extras.qpfSnowCm = it - extras.qpfSnowIn = ConversionMethods.mmToIn(it) + extras.qpfSnowIn = ConversionMethods.mmToIn(it * 10) } } } diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt index f505ecf5..fce4a44a 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherApiProvider.kt @@ -431,6 +431,9 @@ class WeatherApiProvider : WeatherProviderImpl(), WeatherAlertProvider, PollenPr ) { weather.astronomy!!.moonset = newAstro.moonset } + if (weather.astronomy!!.moonPhase == null) { + weather.astronomy!!.moonPhase = newAstro.moonPhase + } }.getOrElse { weather.astronomy = newAstro } diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt index 066e5958..32023919 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherapi/weather/WeatherData.kt @@ -237,21 +237,21 @@ fun createCondition(current: Current, tzId: ZoneId): Condition { treePollenValue in 1.0..20.0 -> Pollen.PollenCount.LOW treePollenValue in 20.0..100.0 -> Pollen.PollenCount.MODERATE treePollenValue in 100.0..300.0 -> Pollen.PollenCount.HIGH - treePollenValue >= 300.0 -> Pollen.PollenCount.LOW + treePollenValue >= 300.0 -> Pollen.PollenCount.VERY_HIGH else -> Pollen.PollenCount.UNKNOWN } grassPollenCount = when { grassPollenValue in 1.0..20.0 -> Pollen.PollenCount.LOW grassPollenValue in 20.0..100.0 -> Pollen.PollenCount.MODERATE grassPollenValue in 100.0..300.0 -> Pollen.PollenCount.HIGH - grassPollenValue >= 300.0 -> Pollen.PollenCount.LOW + grassPollenValue >= 300.0 -> Pollen.PollenCount.VERY_HIGH else -> Pollen.PollenCount.UNKNOWN } ragweedPollenCount = when { ragweedPollenValue in 1.0..20.0 -> Pollen.PollenCount.LOW ragweedPollenValue in 20.0..100.0 -> Pollen.PollenCount.MODERATE ragweedPollenValue in 100.0..300.0 -> Pollen.PollenCount.HIGH - ragweedPollenValue >= 300.0 -> Pollen.PollenCount.LOW + ragweedPollenValue >= 300.0 -> Pollen.PollenCount.VERY_HIGH else -> Pollen.PollenCount.UNKNOWN } } From 111c41cf71986af91cf00b2d87c777fc92455ddd Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Fri, 17 Jul 2026 00:56:35 -0400 Subject: [PATCH 62/67] gradle: update dependencies --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 039ffdea..5c5658e6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -61,14 +61,14 @@ wear_watchface_version = "1.3.0" horologist_version = '0.7.15' accompanist_version = '0.37.3' -glide_version = "5.0.7" +glide_version = "5.0.9" icu4j_version = "78.3" jjwt_version = '0.13.0' moshi_version = '1.15.2' okhttp_version = "5.4.0" timber_version = '5.0.1' -revcat_version = "10.12.0" +revcat_version = "10.14.0" [libraries] com-google-devtools-ksp-gradle-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp_version" } From c72fc93af3b2131fb3800bfc622e1efec15ef225 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Fri, 17 Jul 2026 00:59:35 -0400 Subject: [PATCH 63/67] SimpleWeather: v5.14.0-build10 --- app/build.gradle | 2 +- wearapp/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 49375fdc..b09156ec 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get().toInteger() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code (Android: 0, WearOS: 1) // ex) 345100131 = (34, 5.10, 013, 0) - versionCode 375140090 + versionCode 375140100 versionName "5.14.0" vectorDrawables { diff --git a/wearapp/build.gradle b/wearapp/build.gradle index d08a7767..12e20913 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -16,7 +16,7 @@ android { targetSdkVersion libs.versions.wearTargetSdkVersion.get() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code [Android: 0, WearOS: 1]) // ex) 345100131 = (34, 5.10, 013, 1) - versionCode 365140091 + versionCode 365140101 versionName "5.14.0" vectorDrawables { From 3101a7557f0f266b04af7c25528a455065904b44 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Sat, 25 Jul 2026 21:23:53 -0400 Subject: [PATCH 64/67] RainViewerViewProvider: max zoom level is 7 --- .../simpleweather/radar/rainviewer/RainViewerViewProvider.kt | 2 +- .../simpleweather/radar/rainviewer/RainViewerViewProvider.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/fullgms/java/com/thewizrd/simpleweather/radar/rainviewer/RainViewerViewProvider.kt b/app/src/fullgms/java/com/thewizrd/simpleweather/radar/rainviewer/RainViewerViewProvider.kt index 07ec11bb..ca497a00 100644 --- a/app/src/fullgms/java/com/thewizrd/simpleweather/radar/rainviewer/RainViewerViewProvider.kt +++ b/app/src/fullgms/java/com/thewizrd/simpleweather/radar/rainviewer/RainViewerViewProvider.kt @@ -333,7 +333,7 @@ class RainViewerViewProvider(context: Context, rootView: ViewGroup) : MapTileRad */ private fun checkTileExists(x: Int, y: Int, zoom: Int): Boolean { val minZoom = MIN_ZOOM_LEVEL - val maxZoom = MAX_ZOOM_LEVEL + val maxZoom = 7 return zoom in minZoom..maxZoom } diff --git a/app/src/nongms/java/com/thewizrd/simpleweather/radar/rainviewer/RainViewerViewProvider.kt b/app/src/nongms/java/com/thewizrd/simpleweather/radar/rainviewer/RainViewerViewProvider.kt index ed91d352..abcb8fca 100644 --- a/app/src/nongms/java/com/thewizrd/simpleweather/radar/rainviewer/RainViewerViewProvider.kt +++ b/app/src/nongms/java/com/thewizrd/simpleweather/radar/rainviewer/RainViewerViewProvider.kt @@ -333,7 +333,7 @@ class RainViewerViewProvider(context: Context, rootView: ViewGroup) : XYTileSource( "RainViewer", MIN_ZOOM_LEVEL, - MAX_ZOOM_LEVEL, + 7, 256, "${mapFrame?.timeStamp ?: ""}.png", arrayOf(mapFrame?.host) From 2dd08b6383d926cafe1e2b9494fa8fd8e03453dd Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Mon, 27 Jul 2026 11:09:00 -0400 Subject: [PATCH 65/67] gradle: update dependencies * AGP v9.3.1 --- gradle/libs.versions.toml | 10 +++++----- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5c5658e6..660d0c70 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,14 +4,14 @@ minSdkVersion = "23" targetSdkVersion = "37" wearTargetSdkVersion = "36" -gradleVersion = "9.2.1" +gradleVersion = "9.3.1" kotlin_version = "2.3.21" kotlinx_version = "1.11.0" ksp_version = "2.3.6" desugar_version = '2.1.5' -firebase_version = "34.15.0" +firebase_version = "34.16.0" firebaseCrashlyticsGradleVersion = "3.0.7" firebasePerfPluginVersion = "2.0.2" gms_location_version = "21.4.0" @@ -48,7 +48,7 @@ google_truth_version = '1.4.5' espresso_core_version = "3.7.0" material_version = "1.14.0" -material_compose_version = "1.5.0-alpha23" +material_compose_version = "1.5.0-alpha24" compose_compiler_version = '1.5.15' compose_bom_version = "2026.06.01" @@ -68,7 +68,7 @@ moshi_version = '1.15.2' okhttp_version = "5.4.0" timber_version = '5.0.1' -revcat_version = "10.14.0" +revcat_version = "10.15.1" [libraries] com-google-devtools-ksp-gradle-plugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "ksp_version" } @@ -136,7 +136,7 @@ work-runtime-ktx = { module = "androidx.work:work-runtime-ktx", version.ref = "w wear = { module = "androidx.wear:wear", version.ref = "wear_version" } wear-input = { module = "androidx.wear:wear-input", version.ref = "wear_input_version" } wear-input-testing = { module = "androidx.wear:wear-input-testing", version.ref = "wear_input_version" } -wear-phone-interactions = { module = "androidx.wear:wear-phone-interactions", version = "1.1.0" } +wear-phone-interactions = { module = "androidx.wear:wear-phone-interactions", version = "1.1.1" } wear-remote-interactions = { module = "androidx.wear:wear-remote-interactions", version = "1.2.0" } wear-watchface-complications-data = { module = "androidx.wear.watchface:watchface-complications-data", version.ref = "wear_watchface_version" } wear-watchface-complications-data-source-ktx = { module = "androidx.wear.watchface:watchface-complications-data-source-ktx", version.ref = "wear_watchface_version" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9a6304ac..96eb87e0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Aug 31 15:05:29 EDT 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME From 29d556d021401134650c96b9ae4685d4c9192bd9 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Mon, 27 Jul 2026 11:09:57 -0400 Subject: [PATCH 66/67] weatherkit: adjust alert dates --- .../com/thewizrd/weather_api/weatherkit/WeatherAlerts.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherAlerts.kt b/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherAlerts.kt index 4a0e495e..f0e459f3 100644 --- a/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherAlerts.kt +++ b/weather-api/src/main/java/com/thewizrd/weather_api/weatherkit/WeatherAlerts.kt @@ -1,5 +1,6 @@ package com.thewizrd.weather_api.weatherkit +import android.annotation.SuppressLint import com.thewizrd.shared_resources.weatherdata.model.WeatherAlert import com.thewizrd.shared_resources.weatherdata.model.WeatherAlertSeverity import com.thewizrd.shared_resources.weatherdata.model.WeatherAlertType @@ -8,7 +9,7 @@ import java.time.ZonedDateTime fun createWeatherAlerts(alerts: WeatherAlertCollection?): Collection? { if (alerts?.alerts.isNullOrEmpty()) return null - val weatherAlerts = ArrayList(alerts!!.alerts.size) + val weatherAlerts = ArrayList(alerts.alerts.size) for (alert in alerts.alerts) { weatherAlerts.add(createWeatherAlert(alert)) @@ -17,13 +18,14 @@ fun createWeatherAlerts(alerts: WeatherAlertCollection?): Collection WeatherAlertSeverity.EXTREME Severity.SEVERE -> WeatherAlertSeverity.SEVERE From 87f7cf8c095902ed9991fbf09dff1f0571a75273 Mon Sep 17 00:00:00 2001 From: Dave Antoine Date: Mon, 27 Jul 2026 11:10:51 -0400 Subject: [PATCH 67/67] SimpleWeather: v5.14.0-build11 --- app/build.gradle | 2 +- wearapp/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b09156ec..c0cce840 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { targetSdkVersion libs.versions.targetSdkVersion.get().toInteger() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code (Android: 0, WearOS: 1) // ex) 345100131 = (34, 5.10, 013, 0) - versionCode 375140100 + versionCode 375140110 versionName "5.14.0" vectorDrawables { diff --git a/wearapp/build.gradle b/wearapp/build.gradle index 12e20913..afa13ba8 100644 --- a/wearapp/build.gradle +++ b/wearapp/build.gradle @@ -16,7 +16,7 @@ android { targetSdkVersion libs.versions.wearTargetSdkVersion.get() // NOTE: Version Code Format (TargetSDK, Version Name, Build Number, Variant Code [Android: 0, WearOS: 1]) // ex) 345100131 = (34, 5.10, 013, 1) - versionCode 365140101 + versionCode 365140111 versionName "5.14.0" vectorDrawables {