Compare commits
No commits in common. "patch-develop" and "v2.2.2-beta4" have entirely different histories.
patch-deve
...
v2.2.2-bet
180
.idea/assetWizardSettings.xml
generated
@ -19,29 +19,6 @@
|
|||||||
<option name="children">
|
<option name="children">
|
||||||
<map>
|
<map>
|
||||||
<entry key="clipArt">
|
<entry key="clipArt">
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="color" value="000000" />
|
|
||||||
<entry key="imagePath" value="/private/var/folders/cw/tkrg0g5j6lzcqwr0tfkph8w80000gn/T/ic_android_black_24dp.xml" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="text">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="color" value="000000" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="textAsset">
|
|
||||||
<value>
|
<value>
|
||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="values">
|
<option name="values">
|
||||||
@ -68,47 +45,14 @@
|
|||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="children">
|
<option name="children">
|
||||||
<map>
|
<map>
|
||||||
<entry key="foregroundClipArt">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="imagePath" value="/private/var/folders/cw/tkrg0g5j6lzcqwr0tfkph8w80000gn/T/ic_android_black_24dp.xml" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="foregroundImage">
|
<entry key="foregroundImage">
|
||||||
<value>
|
<value>
|
||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="values">
|
<option name="values">
|
||||||
<map>
|
<map>
|
||||||
<entry key="color" value="000000" />
|
<entry key="color" value="000000" />
|
||||||
<entry key="imagePath" value="$USER_HOME$/Desktop/logo-white.png" />
|
|
||||||
<entry key="scalingPercent" value="70" />
|
<entry key="scalingPercent" value="70" />
|
||||||
</map>
|
<entry key="trimmed" value="true" />
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="foregroundText">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="color" value="000000" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="foregroundTextAsset">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="color" value="000000" />
|
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</PersistentState>
|
</PersistentState>
|
||||||
@ -120,6 +64,7 @@
|
|||||||
<map>
|
<map>
|
||||||
<entry key="backgroundAssetType" value="COLOR" />
|
<entry key="backgroundAssetType" value="COLOR" />
|
||||||
<entry key="backgroundColor" value="ffffff" />
|
<entry key="backgroundColor" value="ffffff" />
|
||||||
|
<entry key="foregroundImage" value="$USER_HOME$/Desktop/Artboard Copy 3.png" />
|
||||||
<entry key="legacyIconShape" value="CIRCLE" />
|
<entry key="legacyIconShape" value="CIRCLE" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
@ -132,29 +77,6 @@
|
|||||||
<option name="children">
|
<option name="children">
|
||||||
<map>
|
<map>
|
||||||
<entry key="clipArt">
|
<entry key="clipArt">
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="color" value="000000" />
|
|
||||||
<entry key="imagePath" value="/private/var/folders/cw/tkrg0g5j6lzcqwr0tfkph8w80000gn/T/ic_android_black_24dp.xml" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="text">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="color" value="000000" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="textAsset">
|
|
||||||
<value>
|
<value>
|
||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="values">
|
<option name="values">
|
||||||
@ -176,104 +98,6 @@
|
|||||||
<option name="children">
|
<option name="children">
|
||||||
<map>
|
<map>
|
||||||
<entry key="clipArt">
|
<entry key="clipArt">
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="color" value="000000" />
|
|
||||||
<entry key="imagePath" value="/private/var/folders/cw/tkrg0g5j6lzcqwr0tfkph8w80000gn/T/ic_android_black_24dp.xml" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="text">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="color" value="000000" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="textAsset">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="color" value="000000" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="tvBanner">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="children">
|
|
||||||
<map>
|
|
||||||
<entry key="foregroundText">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="color" value="000000" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="tvChannel">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="children">
|
|
||||||
<map>
|
|
||||||
<entry key="foregroundClipArt">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="imagePath" value="/private/var/folders/cw/tkrg0g5j6lzcqwr0tfkph8w80000gn/T/ic_android_black_24dp.xml" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="foregroundImage">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="color" value="000000" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="foregroundText">
|
|
||||||
<value>
|
|
||||||
<PersistentState>
|
|
||||||
<option name="values">
|
|
||||||
<map>
|
|
||||||
<entry key="color" value="000000" />
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</PersistentState>
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="foregroundTextAsset">
|
|
||||||
<value>
|
<value>
|
||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="values">
|
<option name="values">
|
||||||
|
BIN
.idea/caches/build_file_checksums.ser
generated
5
.idea/gradle.xml
generated
@ -4,16 +4,17 @@
|
|||||||
<component name="GradleSettings">
|
<component name="GradleSettings">
|
||||||
<option name="linkedExternalProjectsSettings">
|
<option name="linkedExternalProjectsSettings">
|
||||||
<GradleProjectSettings>
|
<GradleProjectSettings>
|
||||||
<option name="testRunner" value="GRADLE" />
|
<option name="testRunner" value="PLATFORM" />
|
||||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
<option name="gradleJvm" value="Embedded JDK" />
|
|
||||||
<option name="modules">
|
<option name="modules">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
|
<option name="useQualifiedModuleNames" value="true" />
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
2
.idea/misc.xml
generated
@ -61,7 +61,7 @@
|
|||||||
</profile-state>
|
</profile-state>
|
||||||
</entry>
|
</entry>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
3
.idea/modules.xml
generated
@ -4,9 +4,6 @@
|
|||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/Another_Widget.iml" filepath="$PROJECT_DIR$/.idea/modules/Another_Widget.iml" />
|
<module fileurl="file://$PROJECT_DIR$/.idea/modules/Another_Widget.iml" filepath="$PROJECT_DIR$/.idea/modules/Another_Widget.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/Another_Widget.app.iml" filepath="$PROJECT_DIR$/.idea/modules/app/Another_Widget.app.iml" />
|
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/Another_Widget.app.iml" filepath="$PROJECT_DIR$/.idea/modules/app/Another_Widget.app.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/Another_Widget.app.androidTest.iml" filepath="$PROJECT_DIR$/.idea/modules/app/Another_Widget.app.androidTest.iml" />
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/Another_Widget.app.main.iml" filepath="$PROJECT_DIR$/.idea/modules/app/Another_Widget.app.main.iml" />
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/Another_Widget.app.unitTest.iml" filepath="$PROJECT_DIR$/.idea/modules/app/Another_Widget.app.unitTest.iml" />
|
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
12
.idea/runConfigurations.xml
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RunConfigurationProducerService">
|
||||||
|
<option name="ignoredProducers">
|
||||||
|
<set>
|
||||||
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||||
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||||
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||||
|
</set>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
@ -1,20 +1,32 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
apply plugin: 'com.google.gms.google-services'
|
||||||
|
|
||||||
|
// Apply the Crashlytics Gradle plugin
|
||||||
|
apply plugin: 'com.google.firebase.crashlytics'
|
||||||
|
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlin-kapt'
|
apply plugin: 'kotlin-kapt'
|
||||||
|
|
||||||
|
apply plugin: 'realm-android'
|
||||||
|
|
||||||
|
def apikeyPropertiesFile = rootProject.file("apikey.properties")
|
||||||
|
def apikeyProperties = new Properties()
|
||||||
|
apikeyProperties.load(new FileInputStream(apikeyPropertiesFile))
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|
||||||
compileSdkVersion 30
|
compileSdkVersion 30
|
||||||
|
buildToolsVersion "29.0.3"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.tommasoberlose.anotherwidget"
|
applicationId "com.tommasoberlose.anotherwidget"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode 139
|
versionCode 122
|
||||||
versionName "2.3.3"
|
versionName "2.2.2"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY'])
|
||||||
|
|
||||||
renderscriptSupportModeEnabled true
|
renderscriptSupportModeEnabled true
|
||||||
}
|
}
|
||||||
@ -53,14 +65,14 @@ dependencies {
|
|||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.1'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
implementation 'androidx.appcompat:appcompat:1.3.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||||
implementation 'com.google.android.material:material:1.3.0'
|
implementation 'com.google.android.material:material:1.3.0-beta01'
|
||||||
implementation 'androidx.browser:browser:1.3.0'
|
implementation 'androidx.browser:browser:1.3.0'
|
||||||
implementation 'net.idik:slimadapter:2.1.2'
|
implementation 'net.idik:slimadapter:2.1.2'
|
||||||
implementation 'com.google.android:flexbox:2.0.1'
|
implementation 'com.google.android:flexbox:2.0.1'
|
||||||
@ -68,21 +80,17 @@ dependencies {
|
|||||||
|
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
|
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
|
||||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
|
||||||
|
|
||||||
implementation "androidx.work:work-runtime-ktx:2.5.0"
|
implementation "androidx.work:work-runtime-ktx:2.4.0"
|
||||||
|
|
||||||
// EventBus
|
// EventBus
|
||||||
implementation 'org.greenrobot:eventbus:3.2.0'
|
implementation 'org.greenrobot:eventbus:3.2.0'
|
||||||
|
|
||||||
// Room
|
|
||||||
implementation "androidx.room:room-runtime:2.3.0"
|
|
||||||
kapt "androidx.room:room-compiler:2.3.0"
|
|
||||||
|
|
||||||
// Navigation
|
// Navigation
|
||||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
|
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.2'
|
||||||
implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
|
implementation 'androidx.navigation:navigation-ui-ktx:2.3.2'
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
implementation 'androidx.multidex:multidex:2.0.1'
|
implementation 'androidx.multidex:multidex:2.0.1'
|
||||||
@ -91,17 +99,26 @@ dependencies {
|
|||||||
implementation 'com.github.warkiz.widget:indicatorseekbar:2.1.2'
|
implementation 'com.github.warkiz.widget:indicatorseekbar:2.1.2'
|
||||||
|
|
||||||
//Glide
|
//Glide
|
||||||
implementation 'com.github.bumptech.glide:glide:4.12.0'
|
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||||
kapt 'com.github.bumptech.glide:compiler:4.11.0'
|
kapt 'com.github.bumptech.glide:compiler:4.11.0'
|
||||||
|
|
||||||
|
// Fitness
|
||||||
|
implementation 'com.google.android.gms:play-services-fitness:20.0.0'
|
||||||
|
implementation 'com.google.android.gms:play-services-auth:18.1.0'
|
||||||
|
|
||||||
//Weather
|
//Weather
|
||||||
implementation 'com.github.KwabenBerko:OpenWeatherMap-Android-Library:2.0.2'
|
implementation 'com.github.KwabenBerko:OpenWeatherMap-Android-Library:2.0.2'
|
||||||
|
implementation 'com.google.android.gms:play-services-location:17.1.0'
|
||||||
|
|
||||||
|
// Billing
|
||||||
|
implementation 'com.android.billingclient:billing:3.0.2'
|
||||||
|
implementation 'com.android.billingclient:billing-ktx:3.0.2'
|
||||||
|
|
||||||
// KTX
|
// KTX
|
||||||
implementation "androidx.core:core-ktx:1.5.0"
|
implementation "androidx.core:core-ktx:1.3.2"
|
||||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
|
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
|
||||||
implementation "androidx.palette:palette-ktx:1.0.0"
|
implementation "androidx.palette:palette-ktx:1.0.0"
|
||||||
implementation 'androidx.core:core-ktx:1.5.0'
|
implementation 'androidx.core:core-ktx:1.3.2'
|
||||||
|
|
||||||
//Retrofit
|
//Retrofit
|
||||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||||
@ -111,11 +128,14 @@ dependencies {
|
|||||||
implementation "com.github.haroldadmin:NetworkResponseAdapter:4.0.1"
|
implementation "com.github.haroldadmin:NetworkResponseAdapter:4.0.1"
|
||||||
|
|
||||||
//Coroutines
|
//Coroutines
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
|
||||||
|
|
||||||
|
// Add the Firebase SDK for Crashlytics.
|
||||||
|
implementation 'com.google.firebase:firebase-crashlytics:17.3.0'
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
implementation 'com.chibatching.kotpref:kotpref:2.13.1'
|
implementation 'com.chibatching.kotpref:kotpref:2.11.0'
|
||||||
implementation 'com.chibatching.kotpref:livedata-support:2.13.1'
|
implementation 'com.chibatching.kotpref:livedata-support:2.10.0'
|
||||||
implementation 'androidx.preference:preference-ktx:1.1.1'
|
implementation 'androidx.preference:preference-ktx:1.1.1'
|
||||||
|
|
||||||
// Permissions
|
// Permissions
|
||||||
|
@ -6,15 +6,13 @@
|
|||||||
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="com.android.vending.BILLING" />
|
<uses-permission android:name="com.android.vending.BILLING" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
|
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
|
||||||
<uses-permission android:name="android.gms.permission.ACTIVITY_RECOGNITION"/>
|
<uses-permission android:name="android.gms.permission.ACTIVITY_RECOGNITION"/>
|
||||||
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
|
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
|
||||||
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
@ -26,28 +24,29 @@
|
|||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
tools:ignore="LockedOrientationActivity">
|
tools:ignore="LockedOrientationActivity">
|
||||||
<activity android:name=".ui.activities.SplashActivity" android:exported="true" android:theme="@style/AppTheme.Main" android:screenOrientation="portrait">
|
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" android:theme="@style/AppTheme.Main" android:screenOrientation="portrait">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".ui.activities.MainActivity" android:theme="@style/AppTheme" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.ChooseApplicationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.ChooseApplicationActivity" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.CustomFontActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.CustomFontActivity" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.CustomLocationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.CustomLocationActivity" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.WeatherProviderActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.WeatherProviderActivity" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.settings.SupportDevActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.CustomDateActivity" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.CustomDateActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.settings.IntegrationsActivity" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.settings.IntegrationsActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.MusicPlayersFilterActivity" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.MusicPlayersFilterActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.AppNotificationsFilterActivity" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.AppNotificationsFilterActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.MediaInfoFormatActivity" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.MediaInfoFormatActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.TimeZoneSelectorActivity" android:screenOrientation="portrait" />
|
|
||||||
|
|
||||||
<receiver android:name=".ui.widgets.MainWidget" android:exported="true">
|
<receiver android:name=".ui.widgets.MainWidget">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/the_widget_info" />
|
android:resource="@xml/the_widget_info" />
|
||||||
@ -73,8 +72,8 @@
|
|||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
<action android:name="com.tommasoberlose.anotherwidget.action.CALENDAR_UPDATE" />
|
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_CALENDAR_UPDATE" />
|
||||||
<action android:name="com.tommasoberlose.anotherwidget.action.TIME_UPDATE" />
|
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_TIME_UPDATE" />
|
||||||
<action android:name="com.sec.android.widgetapp.APPWIDGET_RESIZE" />
|
<action android:name="com.sec.android.widgetapp.APPWIDGET_RESIZE" />
|
||||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||||
<action android:name="android.app.action.NEXT_ALARM_CLOCK_CHANGED" />
|
<action android:name="android.app.action.NEXT_ALARM_CLOCK_CHANGED" />
|
||||||
@ -89,7 +88,8 @@
|
|||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.tommasoberlose.anotherwidget.action.WEATHER_UPDATE" />
|
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_WEATHER_UPDATE" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
<action android:name="android.intent.action.TIME_SET" />
|
<action android:name="android.intent.action.TIME_SET" />
|
||||||
@ -101,13 +101,26 @@
|
|||||||
<receiver
|
<receiver
|
||||||
android:name=".receivers.WidgetClickListenerReceiver"
|
android:name=".receivers.WidgetClickListenerReceiver"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true">
|
android:exported="false">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="com.tommasoberlose.anotherwidget.action.OPEN_WEATHER_INTENT" />
|
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_OPEN_WEATHER_INTENT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<service android:name=".receivers.NotificationListener" android:exported="true"
|
<receiver
|
||||||
|
android:name=".receivers.CrashlyticsReceiver"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_REPORT_CRASH" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<service android:name=".services.EventListenerJob" android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||||
|
|
||||||
|
<service android:name=".services.BatteryListenerJob" android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||||
|
|
||||||
|
<service android:name=".receivers.NotificationListener"
|
||||||
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
|
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.service.notification.NotificationListenerService" />
|
<action android:name="android.service.notification.NotificationListenerService" />
|
||||||
@ -125,6 +138,27 @@
|
|||||||
<action android:name="android.intent.action.BATTERY_CHANGED"/>
|
<action android:name="android.intent.action.BATTERY_CHANGED"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
<receiver android:name=".receivers.ActivityDetectionReceiver"
|
||||||
|
android:exported="false"
|
||||||
|
android:permission="com.google.android.gms.permission.ACTIVITY_RECOGNITION">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.mypackage.ACTION_PROCESS_ACTIVITY_TRANSITIONS" />
|
||||||
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name=".services.UpdateCalendarService"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false"
|
||||||
|
android:foregroundServiceType="dataSync" />
|
||||||
|
<service
|
||||||
|
android:name=".services.LocationService"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false"
|
||||||
|
android:foregroundServiceType="location" />
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
<queries>
|
<queries>
|
||||||
|
BIN
app/src/main/assets/fonts/google_sans_black.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_black_italic.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_bold.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_bold_italic.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_italic.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_light.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_light_italic.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_medium.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_medium_italic.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_regular.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_thin.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_thin_italic.ttf
Normal file
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 13 KiB |
BIN
app/src/main/ic_launcher-web.png
Normal file
After Width: | Height: | Size: 45 KiB |
@ -1,18 +1,52 @@
|
|||||||
package com.tommasoberlose.anotherwidget
|
package com.tommasoberlose.anotherwidget
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.util.Log
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import com.chibatching.kotpref.Kotpref
|
import com.chibatching.kotpref.Kotpref
|
||||||
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
|
import io.realm.Realm
|
||||||
|
import io.realm.RealmConfiguration
|
||||||
|
import net.danlew.android.joda.JodaTimeAndroid
|
||||||
|
|
||||||
class AWApplication : Application() {
|
class AWApplication : Application() {
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
|
// Firebase crashlitycs
|
||||||
|
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(!BuildConfig.DEBUG)
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
Kotpref.init(this)
|
Kotpref.init(this)
|
||||||
|
|
||||||
// Dark theme
|
// Dark theme
|
||||||
AppCompatDelegate.setDefaultNightMode(Preferences.darkThemePreference)
|
AppCompatDelegate.setDefaultNightMode(Preferences.darkThemePreference)
|
||||||
|
|
||||||
|
// Realm
|
||||||
|
Realm.init(this)
|
||||||
|
val config = RealmConfiguration.Builder()
|
||||||
|
.deleteRealmIfMigrationNeeded()
|
||||||
|
.build()
|
||||||
|
Realm.setDefaultConfiguration(config)
|
||||||
|
|
||||||
|
calibrateVersions()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private fun calibrateVersions() {
|
||||||
|
// 2.0 Tolerance
|
||||||
|
if (Preferences.clockTextSize > 50f) {
|
||||||
|
Preferences.clockTextSize = 32f
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Preferences.textMainSize > 36f) {
|
||||||
|
Preferences.textMainSize = 32f
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Preferences.textSecondSize > 28f) {
|
||||||
|
Preferences.textSecondSize = 24f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,30 +3,40 @@ package com.tommasoberlose.anotherwidget.components
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.FrameLayout
|
import android.widget.GridLayout
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.SeekBar
|
||||||
|
import androidx.annotation.ColorInt
|
||||||
import androidx.appcompat.widget.AppCompatImageView
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.core.widget.addTextChangedListener
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.databinding.BottomSheetMenuHorBinding
|
import com.tommasoberlose.anotherwidget.databinding.BottomSheetMenuHorBinding
|
||||||
import com.tommasoberlose.anotherwidget.databinding.BottomSheetMenuListBinding
|
import com.tommasoberlose.anotherwidget.databinding.BottomSheetMenuListBinding
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.copyToClipboard
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isClipboardColor
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.pasteFromClipboard
|
import com.tommasoberlose.anotherwidget.utils.expand
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.reveal
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||||
import com.warkiz.widget.IndicatorSeekBar
|
import com.warkiz.widget.IndicatorSeekBar
|
||||||
import com.warkiz.widget.OnSeekChangeListener
|
import com.warkiz.widget.OnSeekChangeListener
|
||||||
import com.warkiz.widget.SeekParams
|
import com.warkiz.widget.SeekParams
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import net.idik.lib.slimadapter.SlimAdapter
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
|
import java.lang.Exception
|
||||||
|
import java.util.prefs.Preferences
|
||||||
|
|
||||||
class BottomSheetColorPicker(
|
class BottomSheetColorPicker(
|
||||||
context: Context,
|
context: Context,
|
||||||
@ -36,45 +46,20 @@ class BottomSheetColorPicker(
|
|||||||
private val onColorSelected: ((selectedValue: Int) -> Unit)? = null,
|
private val onColorSelected: ((selectedValue: Int) -> Unit)? = null,
|
||||||
private val showAlphaSelector: Boolean = false,
|
private val showAlphaSelector: Boolean = false,
|
||||||
private val alpha: Int = 0,
|
private val alpha: Int = 0,
|
||||||
private val onAlphaChangeListener: ((alpha: Int) -> Unit)? = null,
|
private val onAlphaChangeListener: ((alpha: Int) -> Unit)? = null
|
||||||
private val hideCopyPaste: Boolean = false,
|
|
||||||
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||||
|
|
||||||
private var loadingJobs: ArrayList<Job> = ArrayList()
|
private var loadingJobs: ArrayList<Job> = ArrayList()
|
||||||
private lateinit var adapter: SlimAdapter
|
private lateinit var adapter: SlimAdapter
|
||||||
private var alphaDebouncing: Job? = null
|
|
||||||
|
|
||||||
private var binding: BottomSheetMenuHorBinding = BottomSheetMenuHorBinding.inflate(LayoutInflater.from(context))
|
private var binding: BottomSheetMenuHorBinding = BottomSheetMenuHorBinding.inflate(LayoutInflater.from(context))
|
||||||
private var listBinding: BottomSheetMenuListBinding = BottomSheetMenuListBinding.inflate(LayoutInflater.from(context))
|
private var listBinding: BottomSheetMenuListBinding = BottomSheetMenuListBinding.inflate(LayoutInflater.from(context))
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {
|
||||||
window?.setDimAmount(0f)
|
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
binding.header.isVisible = header != null
|
binding.header.isVisible = header != null
|
||||||
binding.headerText.text = header ?: ""
|
binding.headerText.text = header ?: ""
|
||||||
|
|
||||||
if (hideCopyPaste) {
|
|
||||||
binding.actionContainer.isVisible = false
|
|
||||||
} else {
|
|
||||||
binding.actionContainer.isVisible = true
|
|
||||||
binding.actionCopy.setOnClickListener {
|
|
||||||
context.copyToClipboard(getSelected?.invoke(), alpha)
|
|
||||||
}
|
|
||||||
binding.actionPaste.setOnClickListener {
|
|
||||||
context.pasteFromClipboard { color, alpha ->
|
|
||||||
binding.alphaSelector.setProgress(alpha.toIntValue().toFloat())
|
|
||||||
|
|
||||||
adapter.notifyItemChanged(adapter.data.indexOf(getSelected?.invoke()))
|
|
||||||
onColorSelected?.invoke(Color.parseColor(color))
|
|
||||||
val idx = colors.toList().indexOf(getSelected?.invoke())
|
|
||||||
adapter.notifyItemChanged(idx)
|
|
||||||
(listBinding.root.layoutManager as GridLayoutManager).scrollToPositionWithOffset(idx,0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.actionPaste.isVisible = context.isClipboardColor()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alpha
|
// Alpha
|
||||||
binding.alphaSelectorContainer.isVisible = showAlphaSelector
|
binding.alphaSelectorContainer.isVisible = showAlphaSelector
|
||||||
binding.alphaSelector.setProgress(alpha.toFloat())
|
binding.alphaSelector.setProgress(alpha.toFloat())
|
||||||
@ -82,15 +67,8 @@ class BottomSheetColorPicker(
|
|||||||
binding.alphaSelector.onSeekChangeListener = object : OnSeekChangeListener {
|
binding.alphaSelector.onSeekChangeListener = object : OnSeekChangeListener {
|
||||||
override fun onSeeking(seekParams: SeekParams?) {
|
override fun onSeeking(seekParams: SeekParams?) {
|
||||||
seekParams?.let {
|
seekParams?.let {
|
||||||
binding.textAlpha.text =
|
binding.textAlpha.text = "%s: %s%%".format(context.getString(R.string.alpha), it.progress)
|
||||||
"%s: %s%%".format(context.getString(R.string.alpha), it.progress)
|
onAlphaChangeListener?.invoke(it.progress)
|
||||||
alphaDebouncing?.cancel()
|
|
||||||
alphaDebouncing = GlobalScope.launch(Dispatchers.IO) {
|
|
||||||
delay(150)
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
onAlphaChangeListener?.invoke(it.progress)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override fun onStartTrackingTouch(seekBar: IndicatorSeekBar?) {
|
override fun onStartTrackingTouch(seekBar: IndicatorSeekBar?) {
|
||||||
@ -100,6 +78,7 @@ class BottomSheetColorPicker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List
|
// List
|
||||||
|
|
||||||
adapter = SlimAdapter.create()
|
adapter = SlimAdapter.create()
|
||||||
|
|
||||||
loadingJobs.add(GlobalScope.launch(Dispatchers.IO) {
|
loadingJobs.add(GlobalScope.launch(Dispatchers.IO) {
|
||||||
@ -141,20 +120,14 @@ class BottomSheetColorPicker(
|
|||||||
adapter.updateData(colors.toList())
|
adapter.updateData(colors.toList())
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
binding.loader.isVisible = false
|
binding.colorLoader.isVisible = false
|
||||||
binding.listContainer.addView(listBinding.root)
|
binding.listContainer.addView(listBinding.root)
|
||||||
|
this@BottomSheetColorPicker.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
binding.listContainer.isVisible = true
|
binding.listContainer.isVisible = true
|
||||||
|
|
||||||
val idx = colors.toList().indexOf(getSelected?.invoke())
|
|
||||||
(listBinding.root.layoutManager as GridLayoutManager).scrollToPositionWithOffset(idx,0)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
behavior.run {
|
|
||||||
skipCollapsed = true
|
|
||||||
state = BottomSheetBehavior.STATE_EXPANDED
|
|
||||||
}
|
|
||||||
super.show()
|
super.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import android.view.View
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
@ -108,10 +107,6 @@ open class BottomSheetMenu<T>(context: Context, private val header: String? = nu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
behavior.run {
|
|
||||||
skipCollapsed = true
|
|
||||||
state = com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
|
||||||
}
|
|
||||||
super.show()
|
super.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,111 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.components
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.appcompat.widget.AppCompatImageView
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
|
||||||
import com.google.android.material.card.MaterialCardView
|
|
||||||
import com.tommasoberlose.anotherwidget.R
|
|
||||||
import com.tommasoberlose.anotherwidget.databinding.BottomSheetMenuHorBinding
|
|
||||||
import com.tommasoberlose.anotherwidget.databinding.BottomSheetMenuListBinding
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.copyToClipboard
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isClipboardColor
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.pasteFromClipboard
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
|
||||||
import com.warkiz.widget.IndicatorSeekBar
|
|
||||||
import com.warkiz.widget.OnSeekChangeListener
|
|
||||||
import com.warkiz.widget.SeekParams
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import net.idik.lib.slimadapter.SlimAdapter
|
|
||||||
|
|
||||||
class BottomSheetPicker<T>(
|
|
||||||
context: Context,
|
|
||||||
private val items: List<MenuItem<T>> = arrayListOf(),
|
|
||||||
private val getSelected: (() -> T)? = null,
|
|
||||||
private val header: String? = null,
|
|
||||||
private val onItemSelected: ((selectedValue: T?) -> Unit)? = null,
|
|
||||||
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
|
||||||
|
|
||||||
private var loadingJobs: ArrayList<Job> = ArrayList()
|
|
||||||
private lateinit var adapter: SlimAdapter
|
|
||||||
|
|
||||||
private var binding: BottomSheetMenuHorBinding = BottomSheetMenuHorBinding.inflate(
|
|
||||||
LayoutInflater.from(context))
|
|
||||||
private var listBinding: BottomSheetMenuListBinding = BottomSheetMenuListBinding.inflate(
|
|
||||||
LayoutInflater.from(context))
|
|
||||||
|
|
||||||
override fun show() {
|
|
||||||
window?.setDimAmount(0f)
|
|
||||||
|
|
||||||
// Header
|
|
||||||
binding.header.isVisible = header != null
|
|
||||||
binding.headerText.text = header ?: ""
|
|
||||||
|
|
||||||
// Alpha
|
|
||||||
binding.alphaSelectorContainer.isVisible = false
|
|
||||||
binding.actionContainer.isVisible = false
|
|
||||||
|
|
||||||
// List
|
|
||||||
adapter = SlimAdapter.create()
|
|
||||||
|
|
||||||
loadingJobs.add(GlobalScope.launch(Dispatchers.IO) {
|
|
||||||
listBinding.root.setHasFixedSize(true)
|
|
||||||
val mLayoutManager = LinearLayoutManager(context)
|
|
||||||
listBinding.root.layoutManager = mLayoutManager
|
|
||||||
|
|
||||||
adapter
|
|
||||||
.register<Int>(R.layout.bottom_sheet_menu_item) { position, injector ->
|
|
||||||
val item = items[position]
|
|
||||||
val isSelected = item.value == getSelected?.invoke()
|
|
||||||
injector
|
|
||||||
.text(R.id.label, item.title)
|
|
||||||
.textColor(R.id.label, ContextCompat.getColor(context, if (isSelected) R.color.colorAccent else R.color.colorSecondaryText))
|
|
||||||
.selected(R.id.item, isSelected)
|
|
||||||
.clicked(R.id.item) {
|
|
||||||
val oldIdx = items.toList().indexOfFirst { it.value == getSelected?.invoke() }
|
|
||||||
onItemSelected?.invoke(item.value)
|
|
||||||
adapter.notifyItemChanged(position)
|
|
||||||
adapter.notifyItemChanged(oldIdx)
|
|
||||||
(listBinding.root.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(position,0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.attachTo(listBinding.root)
|
|
||||||
|
|
||||||
adapter.updateData((items.indices).toList())
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
binding.loader.isVisible = false
|
|
||||||
binding.listContainer.addView(listBinding.root)
|
|
||||||
binding.listContainer.isVisible = true
|
|
||||||
|
|
||||||
val idx = items.toList().indexOfFirst { it.value == getSelected?.invoke() }
|
|
||||||
(listBinding.root.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(idx,0)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
setContentView(binding.root)
|
|
||||||
behavior.run {
|
|
||||||
skipCollapsed = true
|
|
||||||
state = BottomSheetBehavior.STATE_EXPANDED
|
|
||||||
}
|
|
||||||
super.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStop() {
|
|
||||||
loadingJobs.forEach { it.cancel() }
|
|
||||||
super.onStop()
|
|
||||||
}
|
|
||||||
|
|
||||||
class MenuItem<T>(val title: String, val value: T? = null)
|
|
||||||
|
|
||||||
}
|
|
@ -61,9 +61,5 @@ class BottomSheetWeatherProviderSettings(context: Context, callback: () -> Unit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
behavior.run {
|
|
||||||
skipCollapsed = true
|
|
||||||
state = com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,9 +26,5 @@ class CustomNotesDialog(context: Context, callback: (() -> Unit)?) : BottomSheet
|
|||||||
binding.notes.requestFocus()
|
binding.notes.requestFocus()
|
||||||
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
behavior.run {
|
|
||||||
skipCollapsed = true
|
|
||||||
state = com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,8 +18,8 @@ class FixedFocusScrollView @JvmOverloads constructor(
|
|||||||
var isScrollable = true
|
var isScrollable = true
|
||||||
|
|
||||||
override fun scrollTo(x: Int, y: Int) {
|
override fun scrollTo(x: Int, y: Int) {
|
||||||
if (isScrollable || !isLaidOut) {
|
if (isScrollable) {
|
||||||
super.scrollTo(x, y)
|
super.scrollTo(x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,9 +6,20 @@ import android.app.AlarmManager
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.navigation.Navigation
|
||||||
|
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
||||||
|
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
||||||
|
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
import com.karumi.dexter.Dexter
|
||||||
|
import com.karumi.dexter.MultiplePermissionsReport
|
||||||
|
import com.karumi.dexter.PermissionToken
|
||||||
|
import com.karumi.dexter.listener.PermissionRequest
|
||||||
|
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.databinding.GlanceProviderSettingsLayoutBinding
|
import com.tommasoberlose.anotherwidget.databinding.GlanceProviderSettingsLayoutBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
@ -17,6 +28,7 @@ import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
|
|||||||
import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
|
import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.GreetingsHelper
|
import com.tommasoberlose.anotherwidget.helpers.GreetingsHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.tabs.AppNotificationsFilterActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.tabs.AppNotificationsFilterActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.tabs.MediaInfoFormatActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.tabs.MediaInfoFormatActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.tabs.MusicPlayersFilterActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.tabs.MusicPlayersFilterActivity
|
||||||
@ -41,7 +53,6 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_title)
|
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_title)
|
||||||
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_title)
|
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_title)
|
||||||
Constants.GlanceProviderId.EVENTS -> context.getString(R.string.settings_show_events_as_glance_provider_title)
|
Constants.GlanceProviderId.EVENTS -> context.getString(R.string.settings_show_events_as_glance_provider_title)
|
||||||
Constants.GlanceProviderId.WEATHER -> context.getString(R.string.settings_show_weather_as_glance_provider_title)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SUBTITLE*/
|
/* SUBTITLE*/
|
||||||
@ -54,7 +65,6 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_subtitle)
|
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_subtitle)
|
||||||
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_subtitle)
|
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_subtitle)
|
||||||
Constants.GlanceProviderId.EVENTS -> context.getString(R.string.settings_show_events_as_glance_provider_subtitle)
|
Constants.GlanceProviderId.EVENTS -> context.getString(R.string.settings_show_events_as_glance_provider_subtitle)
|
||||||
Constants.GlanceProviderId.WEATHER -> context.getString(R.string.settings_show_weather_as_glance_provider_subtitle)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SONG */
|
/* SONG */
|
||||||
@ -80,6 +90,14 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
checkNextAlarm()
|
checkNextAlarm()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* GOOGLE STEPS */
|
||||||
|
binding.actionToggleGoogleFit.isVisible = provider == Constants.GlanceProviderId.GOOGLE_FIT_STEPS
|
||||||
|
if (provider == Constants.GlanceProviderId.GOOGLE_FIT_STEPS) {
|
||||||
|
binding.warningContainer.isVisible = false
|
||||||
|
checkFitnessPermission()
|
||||||
|
checkGoogleFitConnection()
|
||||||
|
}
|
||||||
|
|
||||||
/* BATTERY INFO */
|
/* BATTERY INFO */
|
||||||
if (provider == Constants.GlanceProviderId.BATTERY_LEVEL_LOW) {
|
if (provider == Constants.GlanceProviderId.BATTERY_LEVEL_LOW) {
|
||||||
binding.warningContainer.isVisible = false
|
binding.warningContainer.isVisible = false
|
||||||
@ -101,7 +119,7 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
binding.actionChangeNotificationTimer.setOnClickListener {
|
binding.actionChangeNotificationTimer.setOnClickListener {
|
||||||
val dialog = BottomSheetMenu<Int>(context, header = context.getString(R.string.glance_notification_hide_timeout_title)).setSelectedValue(Preferences.hideNotificationAfter)
|
val dialog = BottomSheetMenu<Int>(context, header = context.getString(R.string.glance_notification_hide_timeout_title)).setSelectedValue(Preferences.hideNotificationAfter)
|
||||||
Constants.GlanceNotificationTimer.values().forEachIndexed { index, timeout ->
|
Constants.GlanceNotificationTimer.values().forEachIndexed { index, timeout ->
|
||||||
dialog.addItem(stringArray[index], timeout.rawValue)
|
dialog.addItem(stringArray[index], timeout.value)
|
||||||
}
|
}
|
||||||
dialog.addOnSelectItemListener { value ->
|
dialog.addOnSelectItemListener { value ->
|
||||||
Preferences.hideNotificationAfter = value
|
Preferences.hideNotificationAfter = value
|
||||||
@ -124,13 +142,6 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
checkCalendarConfig()
|
checkCalendarConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* WEATHER */
|
|
||||||
if (provider == Constants.GlanceProviderId.WEATHER) {
|
|
||||||
binding.header.isVisible = false
|
|
||||||
binding.divider.isVisible = false
|
|
||||||
checkWeatherConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TOGGLE */
|
/* TOGGLE */
|
||||||
binding.providerSwitch.setCheckedImmediatelyNoEvent(when (provider) {
|
binding.providerSwitch.setCheckedImmediatelyNoEvent(when (provider) {
|
||||||
Constants.GlanceProviderId.PLAYING_SONG -> Preferences.showMusic
|
Constants.GlanceProviderId.PLAYING_SONG -> Preferences.showMusic
|
||||||
@ -141,7 +152,6 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
Constants.GlanceProviderId.NOTIFICATIONS -> Preferences.showNotifications
|
Constants.GlanceProviderId.NOTIFICATIONS -> Preferences.showNotifications
|
||||||
Constants.GlanceProviderId.GREETINGS -> Preferences.showGreetings
|
Constants.GlanceProviderId.GREETINGS -> Preferences.showGreetings
|
||||||
Constants.GlanceProviderId.EVENTS -> Preferences.showEventsAsGlanceProvider
|
Constants.GlanceProviderId.EVENTS -> Preferences.showEventsAsGlanceProvider
|
||||||
Constants.GlanceProviderId.WEATHER -> Preferences.showWeatherAsGlanceProvider
|
|
||||||
})
|
})
|
||||||
|
|
||||||
var job: Job? = null
|
var job: Job? = null
|
||||||
@ -159,8 +169,6 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
||||||
Preferences.showNextAlarm = isChecked
|
Preferences.showNextAlarm = isChecked
|
||||||
checkNextAlarm()
|
checkNextAlarm()
|
||||||
if (!isChecked)
|
|
||||||
AlarmHelper.clearTimeout(context)
|
|
||||||
}
|
}
|
||||||
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
||||||
Preferences.showBatteryCharging = isChecked
|
Preferences.showBatteryCharging = isChecked
|
||||||
@ -168,24 +176,39 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
Constants.GlanceProviderId.NOTIFICATIONS -> {
|
Constants.GlanceProviderId.NOTIFICATIONS -> {
|
||||||
Preferences.showNotifications = isChecked
|
Preferences.showNotifications = isChecked
|
||||||
checkLastNotificationsPermission()
|
checkLastNotificationsPermission()
|
||||||
if (!isChecked)
|
|
||||||
ActiveNotificationsHelper.clearLastNotification(context)
|
|
||||||
}
|
}
|
||||||
Constants.GlanceProviderId.GREETINGS -> {
|
Constants.GlanceProviderId.GREETINGS -> {
|
||||||
Preferences.showGreetings = isChecked
|
Preferences.showGreetings = isChecked
|
||||||
GreetingsHelper.toggleGreetings(context)
|
GreetingsHelper.toggleGreetings(context)
|
||||||
}
|
}
|
||||||
|
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||||
|
if (isChecked) {
|
||||||
|
val account: GoogleSignInAccount? =
|
||||||
|
GoogleSignIn.getLastSignedInAccount(context)
|
||||||
|
if (!GoogleSignIn.hasPermissions(account,
|
||||||
|
ActivityDetectionReceiver.FITNESS_OPTIONS
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
val mGoogleSignInClient =
|
||||||
|
GoogleSignIn.getClient(context, GoogleSignInOptions.Builder(
|
||||||
|
GoogleSignInOptions.DEFAULT_SIGN_IN).addExtension(
|
||||||
|
ActivityDetectionReceiver.FITNESS_OPTIONS
|
||||||
|
).build())
|
||||||
|
context.startActivityForResult(mGoogleSignInClient.signInIntent,
|
||||||
|
2)
|
||||||
|
} else {
|
||||||
|
Preferences.showDailySteps = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Preferences.showDailySteps = false
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.warningContainer.isVisible = false
|
||||||
|
checkFitnessPermission()
|
||||||
|
checkGoogleFitConnection()
|
||||||
|
}
|
||||||
Constants.GlanceProviderId.EVENTS -> {
|
Constants.GlanceProviderId.EVENTS -> {
|
||||||
Preferences.showEventsAsGlanceProvider = isChecked
|
Preferences.showEventsAsGlanceProvider = isChecked
|
||||||
if (isChecked) {
|
|
||||||
com.tommasoberlose.anotherwidget.db.EventRepository(context).run {
|
|
||||||
resetNextEventData()
|
|
||||||
close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.WEATHER -> {
|
|
||||||
Preferences.showWeatherAsGlanceProvider = isChecked
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
}
|
}
|
||||||
@ -196,10 +219,6 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
}
|
}
|
||||||
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
behavior.run {
|
|
||||||
skipCollapsed = true
|
|
||||||
state = com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
|
||||||
}
|
|
||||||
super.show()
|
super.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,19 +257,6 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkWeatherConfig() {
|
|
||||||
if (!Preferences.showWeather || (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-") || Preferences.weatherProviderLocationError != "") {
|
|
||||||
binding.warningContainer.isVisible = true
|
|
||||||
binding.warningTitle.text = context.getString(R.string.settings_show_weather_as_glance_provider_error)
|
|
||||||
binding.warningContainer.setOnClickListener {
|
|
||||||
dismiss()
|
|
||||||
EventBus.getDefault().post(MainFragment.ChangeTabEvent(1))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
binding.warningContainer.isVisible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkNotificationPermission() {
|
private fun checkNotificationPermission() {
|
||||||
when {
|
when {
|
||||||
ActiveNotificationsHelper.checkNotificationAccess(context) -> {
|
ActiveNotificationsHelper.checkNotificationAccess(context) -> {
|
||||||
@ -289,4 +295,89 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
}
|
}
|
||||||
statusCallback?.invoke()
|
statusCallback?.invoke()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkFitnessPermission() {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || context.checkGrantedPermission(
|
||||||
|
Manifest.permission.ACTIVITY_RECOGNITION)
|
||||||
|
) {
|
||||||
|
if (Preferences.showDailySteps) {
|
||||||
|
ActivityDetectionReceiver.registerFence(context)
|
||||||
|
} else {
|
||||||
|
ActivityDetectionReceiver.unregisterFence(context)
|
||||||
|
}
|
||||||
|
} else if (Preferences.showDailySteps) {
|
||||||
|
ActivityDetectionReceiver.unregisterFence(context)
|
||||||
|
binding.warningContainer.isVisible = true
|
||||||
|
binding.warningTitle.text = context.getString(R.string.settings_request_fitness_access)
|
||||||
|
binding.warningContainer.setOnClickListener {
|
||||||
|
requireFitnessPermission()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ActivityDetectionReceiver.unregisterFence(context)
|
||||||
|
}
|
||||||
|
statusCallback?.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkGoogleFitConnection() {
|
||||||
|
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
|
||||||
|
if (!GoogleSignIn.hasPermissions(account,
|
||||||
|
ActivityDetectionReceiver.FITNESS_OPTIONS
|
||||||
|
)) {
|
||||||
|
binding.warningContainer.isVisible = true
|
||||||
|
binding.warningTitle.text = context.getString(R.string.settings_request_fitness_access)
|
||||||
|
binding.warningContainer.setOnClickListener {
|
||||||
|
GoogleSignIn.requestPermissions(
|
||||||
|
context,
|
||||||
|
1,
|
||||||
|
account,
|
||||||
|
ActivityDetectionReceiver.FITNESS_OPTIONS)
|
||||||
|
}
|
||||||
|
binding.actionConnectToGoogleFit.isVisible = true
|
||||||
|
binding.actionDisconnectToGoogleFit.isVisible = false
|
||||||
|
binding.actionConnectToGoogleFit.setOnClickListener {
|
||||||
|
GoogleSignIn.requestPermissions(
|
||||||
|
context,
|
||||||
|
1,
|
||||||
|
account,
|
||||||
|
ActivityDetectionReceiver.FITNESS_OPTIONS)
|
||||||
|
}
|
||||||
|
binding.actionDisconnectToGoogleFit.setOnClickListener(null)
|
||||||
|
binding.googleFitStatusLabel.text = context.getString(R.string.google_fit_account_not_connected)
|
||||||
|
} else {
|
||||||
|
binding.actionConnectToGoogleFit.isVisible = false
|
||||||
|
binding.actionDisconnectToGoogleFit.isVisible = true
|
||||||
|
binding.actionConnectToGoogleFit.setOnClickListener(null)
|
||||||
|
binding.actionDisconnectToGoogleFit.setOnClickListener {
|
||||||
|
GoogleSignIn.getClient(context, GoogleSignInOptions.Builder(
|
||||||
|
GoogleSignInOptions.DEFAULT_SIGN_IN).addExtension(
|
||||||
|
ActivityDetectionReceiver.FITNESS_OPTIONS
|
||||||
|
).build()).signOut().addOnCompleteListener {
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.googleFitStatusLabel.text = context.getString(R.string.google_fit_account_connected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun requireFitnessPermission() {
|
||||||
|
Dexter.withContext(context)
|
||||||
|
.withPermissions(
|
||||||
|
"com.google.android.gms.permission.ACTIVITY_RECOGNITION",
|
||||||
|
"android.gms.permission.ACTIVITY_RECOGNITION",
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACTIVITY_RECOGNITION else "com.google.android.gms.permission.ACTIVITY_RECOGNITION"
|
||||||
|
).withListener(object: MultiplePermissionsListener {
|
||||||
|
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
||||||
|
checkFitnessPermission()
|
||||||
|
}
|
||||||
|
override fun onPermissionRationaleShouldBeShown(
|
||||||
|
permissions: MutableList<PermissionRequest>?,
|
||||||
|
token: PermissionToken?
|
||||||
|
) {
|
||||||
|
// Remember to invoke this method when the custom rationale is closed
|
||||||
|
// or just by default if you don't want to use any custom rationale.
|
||||||
|
token?.continuePermissionRequest()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.check()
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ package com.tommasoberlose.anotherwidget.components
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
@ -27,13 +28,13 @@ class IconPackSelector(context: Context, private val header: String? = null) : B
|
|||||||
// Menu
|
// Menu
|
||||||
for (item in Constants.WeatherIconPack.values()) {
|
for (item in Constants.WeatherIconPack.values()) {
|
||||||
val itemBinding = IconPackMenuItemBinding.inflate(LayoutInflater.from(context))
|
val itemBinding = IconPackMenuItemBinding.inflate(LayoutInflater.from(context))
|
||||||
itemBinding.label.text = context.getString(R.string.settings_weather_icon_pack_default).format(item.rawValue + 1)
|
itemBinding.label.text = context.getString(R.string.settings_weather_icon_pack_default).format(item.value + 1)
|
||||||
itemBinding.root.isSelected = item.rawValue == Preferences.weatherIconPack
|
itemBinding.root.isSelected = item.value == Preferences.weatherIconPack
|
||||||
|
|
||||||
itemBinding.icon1.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "01d", item.rawValue)))
|
itemBinding.icon1.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "01d", item.value)))
|
||||||
itemBinding.icon2.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "01n", item.rawValue)))
|
itemBinding.icon2.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "01n", item.value)))
|
||||||
itemBinding.icon3.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "10d", item.rawValue)))
|
itemBinding.icon3.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "10d", item.value)))
|
||||||
itemBinding.icon4.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "09n", item.rawValue)))
|
itemBinding.icon4.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "09n", item.value)))
|
||||||
|
|
||||||
listOf<ImageView>(itemBinding.icon1, itemBinding.icon2, itemBinding.icon3, itemBinding.icon4).forEach {
|
listOf<ImageView>(itemBinding.icon1, itemBinding.icon2, itemBinding.icon3, itemBinding.icon4).forEach {
|
||||||
if (item == Constants.WeatherIconPack.MINIMAL) {
|
if (item == Constants.WeatherIconPack.MINIMAL) {
|
||||||
@ -44,16 +45,12 @@ class IconPackSelector(context: Context, private val header: String? = null) : B
|
|||||||
}
|
}
|
||||||
|
|
||||||
itemBinding.root.setOnClickListener {
|
itemBinding.root.setOnClickListener {
|
||||||
Preferences.weatherIconPack = item.rawValue
|
Preferences.weatherIconPack = item.value
|
||||||
this.dismiss()
|
this.dismiss()
|
||||||
}
|
}
|
||||||
binding.menu.addView(itemBinding.root)
|
binding.menu.addView(itemBinding.root)
|
||||||
}
|
}
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
behavior.run {
|
|
||||||
skipCollapsed = true
|
|
||||||
state = com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
|
||||||
}
|
|
||||||
super.show()
|
super.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -57,10 +57,6 @@ class MaterialBottomSheetDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
behavior.run {
|
|
||||||
skipCollapsed = true
|
|
||||||
state = com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
|
||||||
}
|
|
||||||
super.show()
|
super.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.components
|
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
|
|
||||||
class OnSingleClickListener : View.OnClickListener {
|
|
||||||
|
|
||||||
private val onClickListener: View.OnClickListener
|
|
||||||
|
|
||||||
constructor(listener: View.OnClickListener) {
|
|
||||||
onClickListener = listener
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(listener: (View) -> Unit) {
|
|
||||||
onClickListener = View.OnClickListener { listener.invoke(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onClick(v: View) {
|
|
||||||
val currentTimeMillis = System.currentTimeMillis()
|
|
||||||
|
|
||||||
if (currentTimeMillis >= previousClickTimeMillis + DELAY_MILLIS) {
|
|
||||||
previousClickTimeMillis = currentTimeMillis
|
|
||||||
onClickListener.onClick(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val DELAY_MILLIS = 200L
|
|
||||||
private var previousClickTimeMillis = 0L
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -3,51 +3,52 @@ package com.tommasoberlose.anotherwidget.db
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.provider.CalendarContract
|
import android.provider.CalendarContract
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.room.Dao
|
|
||||||
import androidx.room.Database
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.Query
|
|
||||||
import androidx.room.Room
|
|
||||||
import androidx.room.RoomDatabase
|
|
||||||
import com.chibatching.kotpref.bulk
|
import com.chibatching.kotpref.bulk
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.applyFilters
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.applyFilters
|
||||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.sortEvents
|
|
||||||
import com.tommasoberlose.anotherwidget.models.Event
|
import com.tommasoberlose.anotherwidget.models.Event
|
||||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
import io.realm.Realm
|
||||||
|
import io.realm.RealmResults
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.Comparator
|
import kotlin.Comparator
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class EventRepository(val context: Context) {
|
class EventRepository(val context: Context) {
|
||||||
private val db by lazy { EventDatabase.getDatabase(context) }
|
private val realm by lazy { Realm.getDefaultInstance() }
|
||||||
|
|
||||||
fun saveEvents(eventList: List<Event>) {
|
fun saveEvents(eventList: List<Event>) {
|
||||||
db.runInTransaction{
|
realm.executeTransaction { realm ->
|
||||||
db.dao().run {
|
realm.where(Event::class.java).findAll().deleteAllFromRealm()
|
||||||
deleteAll()
|
realm.copyToRealm(eventList)
|
||||||
insert(eventList)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearEvents() {
|
fun clearEvents() {
|
||||||
db.dao().deleteAll()
|
realm.executeTransaction { realm ->
|
||||||
|
realm.where(Event::class.java).findAll().deleteAllFromRealm()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resetNextEventData() {
|
fun resetNextEventData() {
|
||||||
Preferences.bulk {
|
Preferences.bulk {
|
||||||
remove(Preferences::nextEventId)
|
remove(Preferences::nextEventId)
|
||||||
|
remove(Preferences::nextEventName)
|
||||||
|
remove(Preferences::nextEventStartDate)
|
||||||
|
remove(Preferences::nextEventAllDay)
|
||||||
|
remove(Preferences::nextEventLocation)
|
||||||
|
remove(Preferences::nextEventEndDate)
|
||||||
|
remove(Preferences::nextEventCalendarId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveNextEventData(event: Event) {
|
fun saveNextEventData(event: Event) {
|
||||||
Preferences.nextEventId = event.id
|
Preferences.nextEventId = event.eventID
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNextEvent(): Event? {
|
fun getNextEvent(): Event? {
|
||||||
val nextEvent = getEventById(Preferences.nextEventId)
|
val nextEvent = getEventByEventId(Preferences.nextEventId)
|
||||||
val now = Calendar.getInstance().timeInMillis
|
val now = Calendar.getInstance().timeInMillis
|
||||||
val limit = Calendar.getInstance().apply {
|
val limit = Calendar.getInstance().apply {
|
||||||
timeInMillis = now
|
timeInMillis = now
|
||||||
@ -63,63 +64,75 @@ class EventRepository(val context: Context) {
|
|||||||
else -> add(Calendar.HOUR, 6)
|
else -> add(Calendar.HOUR, 6)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return if (nextEvent != null && nextEvent.endDate > now && nextEvent.startDate <= limit.timeInMillis) {
|
val event = if (nextEvent != null && nextEvent.endDate > now && nextEvent.startDate < limit.timeInMillis) {
|
||||||
nextEvent
|
nextEvent
|
||||||
} else {
|
} else {
|
||||||
val events = getEvents()
|
val events = getEvents()
|
||||||
if (events.isNotEmpty()) {
|
if (events.isNotEmpty()) {
|
||||||
val newNextEvent = events.first()
|
val newNextEvent = events.first()
|
||||||
saveNextEventData(newNextEvent)
|
Preferences.nextEventId = newNextEvent.eventID
|
||||||
newNextEvent
|
newNextEvent
|
||||||
} else {
|
} else {
|
||||||
resetNextEventData()
|
resetNextEventData()
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return try {
|
||||||
|
realm.copyFromRealm(event!!)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
event
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEventById(id: Long): Event? {
|
fun getEventByEventId(id: Long): Event? {
|
||||||
return db.dao().findById(id)
|
val event = realm.where(Event::class.java).equalTo("eventID", id).findFirst()
|
||||||
|
return try {
|
||||||
|
realm.copyFromRealm(event!!)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
event
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun goToNextEvent() {
|
fun goToNextEvent() {
|
||||||
val eventList = getEvents()
|
val eventList = getEvents()
|
||||||
if (eventList.isNotEmpty()) {
|
if (eventList.isNotEmpty()) {
|
||||||
val index = eventList.indexOfFirst { it.id == Preferences.nextEventId }
|
val index = eventList.indexOfFirst { it.eventID == Preferences.nextEventId }
|
||||||
if (index > -1 && index < eventList.size - 1) {
|
if (index > -1 && index < eventList.size - 1) {
|
||||||
saveNextEventData(eventList[index + 1])
|
Preferences.nextEventId = eventList[index + 1].eventID
|
||||||
} else {
|
} else {
|
||||||
saveNextEventData(eventList.first())
|
Preferences.nextEventId = eventList.first().eventID
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
resetNextEventData()
|
resetNextEventData()
|
||||||
}
|
}
|
||||||
|
UpdatesReceiver.setUpdates(context)
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
org.greenrobot.eventbus.EventBus.getDefault().post(
|
|
||||||
com.tommasoberlose.anotherwidget.ui.fragments.MainFragment.UpdateUiMessageEvent()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun goToPreviousEvent() {
|
fun goToPreviousEvent() {
|
||||||
val eventList = getEvents()
|
val eventList = getEvents()
|
||||||
if (eventList.isNotEmpty()) {
|
if (eventList.isNotEmpty()) {
|
||||||
val index = eventList.indexOfFirst { it.id == Preferences.nextEventId }
|
val index = eventList.indexOfFirst { it.eventID == Preferences.nextEventId }
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
saveNextEventData(eventList[index - 1])
|
Preferences.nextEventId = eventList[index - 1].eventID
|
||||||
} else {
|
} else {
|
||||||
saveNextEventData(eventList.last())
|
Preferences.nextEventId = eventList.last().eventID
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
resetNextEventData()
|
resetNextEventData()
|
||||||
}
|
}
|
||||||
|
UpdatesReceiver.setUpdates(context)
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
org.greenrobot.eventbus.EventBus.getDefault().post(
|
|
||||||
com.tommasoberlose.anotherwidget.ui.fragments.MainFragment.UpdateUiMessageEvent()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFutureEvents(): List<Event> {
|
fun getFutureEvents(): List<Event> {
|
||||||
return db.dao().find(Calendar.getInstance().timeInMillis).sortEvents()
|
val now = Calendar.getInstance().timeInMillis
|
||||||
|
realm.refresh()
|
||||||
|
return realm
|
||||||
|
.where(Event::class.java)
|
||||||
|
.greaterThan("endDate", now)
|
||||||
|
.findAll()
|
||||||
|
.applyFilters()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getEvents(): List<Event> {
|
private fun getEvents(): List<Event> {
|
||||||
@ -138,54 +151,18 @@ class EventRepository(val context: Context) {
|
|||||||
else -> add(Calendar.HOUR, 6)
|
else -> add(Calendar.HOUR, 6)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return db.dao().find(now, limit.timeInMillis).sortEvents()
|
realm.refresh()
|
||||||
|
return realm
|
||||||
|
.where(Event::class.java)
|
||||||
|
.greaterThan("endDate", now)
|
||||||
|
.lessThanOrEqualTo("startDate", limit.timeInMillis)
|
||||||
|
.findAll()
|
||||||
|
.applyFilters()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEventsCount(): Int = getEvents().size
|
fun getEventsCount(): Int = getEvents().size
|
||||||
|
|
||||||
fun close() {
|
fun close() {
|
||||||
// db.close()
|
realm.close()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@Dao
|
|
||||||
interface EventDao {
|
|
||||||
@Query("SELECT * FROM events WHERE id = :id LIMIT 1")
|
|
||||||
fun findById(id: Long): Event?
|
|
||||||
|
|
||||||
@Query("SELECT * FROM events WHERE end_date > :from")
|
|
||||||
fun find(from: Long): List<Event>
|
|
||||||
|
|
||||||
@Query("SELECT * FROM events WHERE end_date > :from AND start_date <= :to")
|
|
||||||
fun find(from: Long, to: Long): List<Event>
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
fun insert(events: List<Event>)
|
|
||||||
|
|
||||||
@Query("DELETE FROM events")
|
|
||||||
fun deleteAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Database(entities = arrayOf(Event::class), version = 1, exportSchema = false)
|
|
||||||
abstract class EventDatabase : RoomDatabase() {
|
|
||||||
abstract fun dao(): EventDao
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private var INSTANCE: EventDatabase? = null
|
|
||||||
|
|
||||||
fun getDatabase(context: Context): EventDatabase {
|
|
||||||
// if the INSTANCE is not null, then return it,
|
|
||||||
// if it is, then create the database
|
|
||||||
return INSTANCE ?: synchronized(this) {
|
|
||||||
val instance = Room.databaseBuilder(
|
|
||||||
context.applicationContext,
|
|
||||||
EventDatabase::class.java,
|
|
||||||
"events"
|
|
||||||
).allowMainThreadQueries().build()
|
|
||||||
INSTANCE = instance
|
|
||||||
// return instance
|
|
||||||
instance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ package com.tommasoberlose.anotherwidget.global
|
|||||||
|
|
||||||
object Actions {
|
object Actions {
|
||||||
const val ACTION_EXTRA_OPEN_WEATHER_PROVIDER = "ACTION_EXTRA_OPEN_WEATHER_PROVIDER"
|
const val ACTION_EXTRA_OPEN_WEATHER_PROVIDER = "ACTION_EXTRA_OPEN_WEATHER_PROVIDER"
|
||||||
|
const val ACTION_EXTRA_DISABLE_GPS_NOTIFICATION = "ACTION_EXTRA_DISABLE_GPS_NOTIFICATION"
|
||||||
|
|
||||||
const val ACTION_TIME_UPDATE = "com.tommasoberlose.anotherwidget.action.TIME_UPDATE"
|
const val ACTION_TIME_UPDATE = "com.tommasoberlose.anotherwidget.action.TIME_UPDATE"
|
||||||
const val ACTION_ALARM_UPDATE = "com.tommasoberlose.anotherwidget.action.ALARM_UPDATE"
|
const val ACTION_ALARM_UPDATE = "com.tommasoberlose.anotherwidget.action.ALARM_UPDATE"
|
||||||
@ -10,8 +11,7 @@ object Actions {
|
|||||||
const val ACTION_OPEN_WEATHER_INTENT = "com.tommasoberlose.anotherwidget.action.OPEN_WEATHER_INTENT"
|
const val ACTION_OPEN_WEATHER_INTENT = "com.tommasoberlose.anotherwidget.action.OPEN_WEATHER_INTENT"
|
||||||
const val ACTION_GO_TO_NEXT_EVENT = "com.tommasoberlose.anotherwidget.action.GO_TO_NEXT_EVENT"
|
const val ACTION_GO_TO_NEXT_EVENT = "com.tommasoberlose.anotherwidget.action.GO_TO_NEXT_EVENT"
|
||||||
const val ACTION_GO_TO_PREVIOUS_EVENT = "com.tommasoberlose.anotherwidget.action.GO_TO_PREVIOUS_EVENT"
|
const val ACTION_GO_TO_PREVIOUS_EVENT = "com.tommasoberlose.anotherwidget.action.GO_TO_PREVIOUS_EVENT"
|
||||||
|
const val ACTION_REPORT_CRASH = "com.tommasoberlose.anotherwidget.action.REPORT_CRASH"
|
||||||
const val ACTION_CLEAR_NOTIFICATION = "com.tommasoberlose.anotherwidget.action.CLEAR_NOTIFICATION"
|
const val ACTION_CLEAR_NOTIFICATION = "com.tommasoberlose.anotherwidget.action.CLEAR_NOTIFICATION"
|
||||||
const val ACTION_UPDATE_GREETINGS = "com.tommasoberlose.anotherwidget.action.UPDATE_GREETINGS"
|
const val ACTION_UPDATE_GREETINGS = "com.tommasoberlose.anotherwidget.action.UPDATE_GREETINGS"
|
||||||
|
|
||||||
const val ACTION_REFRESH = "com.tommasoberlose.anotherwidget.action.REFRESH"
|
|
||||||
}
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package com.tommasoberlose.anotherwidget.global
|
package com.tommasoberlose.anotherwidget.global
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
|
||||||
object Constants {
|
object Constants {
|
||||||
const val RESULT_CODE_CUSTOM_LOCATION = 45
|
const val RESULT_CODE_CUSTOM_LOCATION = 45
|
||||||
const val RESULT_APP_NAME = "RESULT_APP_NAME"
|
const val RESULT_APP_NAME = "RESULT_APP_NAME"
|
||||||
@ -9,27 +11,20 @@ object Constants {
|
|||||||
const val CUSTOM_FONT_DOWNLOADED = 2
|
const val CUSTOM_FONT_DOWNLOADED = 2
|
||||||
const val CUSTOM_FONT_DOWNLOAD_NEW = 3
|
const val CUSTOM_FONT_DOWNLOAD_NEW = 3
|
||||||
|
|
||||||
enum class ClockBottomMargin(val rawValue: Int) {
|
enum class ClockBottomMargin(val value: Int) {
|
||||||
NONE(0),
|
NONE(0),
|
||||||
SMALL(1),
|
SMALL(1),
|
||||||
MEDIUM(2),
|
MEDIUM(2),
|
||||||
LARGE(3)
|
LARGE(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class SecondRowTopMargin(val rawValue: Int) {
|
enum class SecondRowTopMargin(val value: Int) {
|
||||||
NONE(0),
|
NONE(0),
|
||||||
SMALL(1),
|
SMALL(1),
|
||||||
MEDIUM(2),
|
MEDIUM(2),
|
||||||
LARGE(3)
|
LARGE(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class Dimension(val rawValue: Float) {
|
|
||||||
NONE(0f),
|
|
||||||
SMALL(8f),
|
|
||||||
MEDIUM(16f),
|
|
||||||
LARGE(24f)
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class GlanceProviderId(val id: String) {
|
enum class GlanceProviderId(val id: String) {
|
||||||
PLAYING_SONG("PLAYING_SONG"),
|
PLAYING_SONG("PLAYING_SONG"),
|
||||||
NEXT_CLOCK_ALARM("NEXT_CLOCK_ALARM"),
|
NEXT_CLOCK_ALARM("NEXT_CLOCK_ALARM"),
|
||||||
@ -38,8 +33,7 @@ object Constants {
|
|||||||
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS"),
|
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS"),
|
||||||
NOTIFICATIONS("NOTIFICATIONS"),
|
NOTIFICATIONS("NOTIFICATIONS"),
|
||||||
GREETINGS("GREETINGS"),
|
GREETINGS("GREETINGS"),
|
||||||
EVENTS("EVENTS"),
|
EVENTS("EVENTS");
|
||||||
WEATHER("WEATHER");
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val map = GlanceProviderId.values().associateBy(GlanceProviderId::id)
|
private val map = GlanceProviderId.values().associateBy(GlanceProviderId::id)
|
||||||
@ -47,13 +41,13 @@ object Constants {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class WidgetUpdateFrequency(val rawValue: Int) {
|
enum class WidgetUpdateFrequency(val value: Int) {
|
||||||
LOW(0),
|
LOW(0),
|
||||||
DEFAULT(1),
|
DEFAULT(1),
|
||||||
HIGH(2)
|
HIGH(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class WeatherProvider(val rawValue: Int) {
|
enum class WeatherProvider(val value: Int) {
|
||||||
OPEN_WEATHER(0),
|
OPEN_WEATHER(0),
|
||||||
WEATHER_BIT(1),
|
WEATHER_BIT(1),
|
||||||
WEATHER_API(2),
|
WEATHER_API(2),
|
||||||
@ -63,12 +57,12 @@ object Constants {
|
|||||||
YR(6);
|
YR(6);
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val map = WeatherProvider.values().associateBy(WeatherProvider::rawValue)
|
private val map = WeatherProvider.values().associateBy(WeatherProvider::value)
|
||||||
fun fromInt(type: Int) = map[type]
|
fun fromInt(type: Int) = map[type]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class GlanceNotificationTimer(val rawValue: Int) {
|
enum class GlanceNotificationTimer(val value: Int) {
|
||||||
HALF_MINUTE(0),
|
HALF_MINUTE(0),
|
||||||
ONE_MINUTE(1),
|
ONE_MINUTE(1),
|
||||||
FIVE_MINUTES(2),
|
FIVE_MINUTES(2),
|
||||||
@ -77,21 +71,15 @@ object Constants {
|
|||||||
WHEN_DISMISSED(5);
|
WHEN_DISMISSED(5);
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val map = values().associateBy(GlanceNotificationTimer::rawValue)
|
private val map = values().associateBy(GlanceNotificationTimer::value)
|
||||||
fun fromInt(type: Int) = map[type]
|
fun fromInt(type: Int) = map[type]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class WeatherIconPack(val rawValue: Int) {
|
enum class WeatherIconPack(val value: Int) {
|
||||||
DEFAULT(0),
|
DEFAULT(0),
|
||||||
MINIMAL(1),
|
MINIMAL(1),
|
||||||
COOL(2),
|
COOL(2),
|
||||||
GOOGLE_NEWS(3)
|
GOOGLE_NEWS(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class WidgetAlign(val rawValue: Int) {
|
|
||||||
LEFT(0),
|
|
||||||
RIGHT(1),
|
|
||||||
CENTER(2)
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,11 +1,13 @@
|
|||||||
package com.tommasoberlose.anotherwidget.global
|
package com.tommasoberlose.anotherwidget.global
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
import androidx.appcompat.app.AppCompatDelegate.*
|
import androidx.appcompat.app.AppCompatDelegate.*
|
||||||
import androidx.core.os.ConfigurationCompat
|
import androidx.core.os.ConfigurationCompat
|
||||||
import com.chibatching.kotpref.KotprefModel
|
import com.chibatching.kotpref.KotprefModel
|
||||||
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||||
import com.tommasoberlose.anotherwidget.utils.isMetric
|
import com.tommasoberlose.anotherwidget.utils.isMetric
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
object Preferences : KotprefModel() {
|
object Preferences : KotprefModel() {
|
||||||
override val commitAllPropertiesByDefault: Boolean = true
|
override val commitAllPropertiesByDefault: Boolean = true
|
||||||
@ -23,6 +25,12 @@ object Preferences : KotprefModel() {
|
|||||||
var calendarFilter by stringPref(key = "PREF_CALENDAR_FILTER", default = "")
|
var calendarFilter by stringPref(key = "PREF_CALENDAR_FILTER", default = "")
|
||||||
|
|
||||||
var nextEventId by longPref(key = "PREF_NEXT_EVENT_ID", default = -1)
|
var nextEventId by longPref(key = "PREF_NEXT_EVENT_ID", default = -1)
|
||||||
|
var nextEventName by stringPref(key = "PREF_NEXT_EVENT_NAME")
|
||||||
|
var nextEventStartDate by longPref(key = "PREF_NEXT_EVENT_START_DATE")
|
||||||
|
var nextEventAllDay by booleanPref(key = "PREF_NEXT_EVENT_ALL_DAY")
|
||||||
|
var nextEventLocation by stringPref(key = "PREF_NEXT_EVENT_LOCATION")
|
||||||
|
var nextEventEndDate by longPref(key = "PREF_NEXT_EVENT_END_DATE")
|
||||||
|
var nextEventCalendarId by intPref(key = "PREF_NEXT_EVENT_CALENDAR_ID")
|
||||||
var customLocationLat by stringPref(key = "PREF_CUSTOM_LOCATION_LAT", default = "")
|
var customLocationLat by stringPref(key = "PREF_CUSTOM_LOCATION_LAT", default = "")
|
||||||
var customLocationLon by stringPref(key = "PREF_CUSTOM_LOCATION_LON", default = "")
|
var customLocationLon by stringPref(key = "PREF_CUSTOM_LOCATION_LON", default = "")
|
||||||
var customLocationAdd by stringPref(key = "PREF_CUSTOM_LOCATION_ADD", default = "")
|
var customLocationAdd by stringPref(key = "PREF_CUSTOM_LOCATION_ADD", default = "")
|
||||||
@ -40,14 +48,14 @@ object Preferences : KotprefModel() {
|
|||||||
var weatherProviderApiWeatherApi by stringPref(default = "")
|
var weatherProviderApiWeatherApi by stringPref(default = "")
|
||||||
var weatherProviderApiWeatherBit by stringPref(default = "")
|
var weatherProviderApiWeatherBit by stringPref(default = "")
|
||||||
var weatherProviderApiAccuweather by stringPref(default = "")
|
var weatherProviderApiAccuweather by stringPref(default = "")
|
||||||
var weatherProvider by intPref(default = if (ConfigurationCompat.getLocales(context.resources.configuration)[0].isMetric()) Constants.WeatherProvider.YR.rawValue else Constants.WeatherProvider.WEATHER_GOV.rawValue)
|
var weatherProvider by intPref(default = if (ConfigurationCompat.getLocales(context.resources.configuration)[0].isMetric()) Constants.WeatherProvider.YR.value else Constants.WeatherProvider.WEATHER_GOV.value)
|
||||||
var weatherProviderError by stringPref(default = "")
|
var weatherProviderError by stringPref(default = "")
|
||||||
var weatherProviderLocationError by stringPref(default = "")
|
var weatherProviderLocationError by stringPref(default = "")
|
||||||
var eventAppName by stringPref(key = "PREF_EVENT_APP_NAME", default = "")
|
var eventAppName by stringPref(key = "PREF_EVENT_APP_NAME", default = "")
|
||||||
var eventAppPackage by stringPref(key = "PREF_EVENT_APP_PACKAGE", default = "")
|
var eventAppPackage by stringPref(key = "PREF_EVENT_APP_PACKAGE", default = "")
|
||||||
var openEventDetails by booleanPref(default = true)
|
var openEventDetails by booleanPref(default = true)
|
||||||
|
|
||||||
var widgetUpdateFrequency by intPref(default = Constants.WidgetUpdateFrequency.DEFAULT.rawValue)
|
var widgetUpdateFrequency by intPref(default = Constants.WidgetUpdateFrequency.DEFAULT.value)
|
||||||
|
|
||||||
var textGlobalColor by stringPref(key = "PREF_TEXT_COLOR", default = "#FFFFFF")
|
var textGlobalColor by stringPref(key = "PREF_TEXT_COLOR", default = "#FFFFFF")
|
||||||
var textGlobalAlpha by stringPref(default = "FF")
|
var textGlobalAlpha by stringPref(default = "FF")
|
||||||
@ -76,22 +84,14 @@ object Preferences : KotprefModel() {
|
|||||||
|
|
||||||
var showAMPMIndicator by booleanPref(default = true)
|
var showAMPMIndicator by booleanPref(default = true)
|
||||||
|
|
||||||
var weatherIconPack by intPref(default = Constants.WeatherIconPack.DEFAULT.rawValue)
|
var weatherIconPack by intPref(default = Constants.WeatherIconPack.DEFAULT.value)
|
||||||
|
|
||||||
// UI
|
|
||||||
var widgetMargin by floatPref(default = Constants.Dimension.NONE.rawValue)
|
|
||||||
var widgetPadding by floatPref(default = Constants.Dimension.SMALL.rawValue)
|
|
||||||
|
|
||||||
// Clock
|
|
||||||
var altTimezoneLabel by stringPref(default = "")
|
|
||||||
var altTimezoneId by stringPref(default = "")
|
|
||||||
|
|
||||||
// Global
|
// Global
|
||||||
var textMainSize by floatPref(key = "PREF_TEXT_MAIN_SIZE", default = 24f)
|
var textMainSize by floatPref(key = "PREF_TEXT_MAIN_SIZE", default = 26f)
|
||||||
var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 16f)
|
var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 18f)
|
||||||
var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 72f)
|
var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 90f)
|
||||||
var clockBottomMargin by intPref(default = Constants.ClockBottomMargin.MEDIUM.rawValue)
|
var clockBottomMargin by intPref(default = Constants.ClockBottomMargin.MEDIUM.value)
|
||||||
var secondRowTopMargin by intPref(default = Constants.SecondRowTopMargin.SMALL.rawValue)
|
var secondRowTopMargin by intPref(default = Constants.SecondRowTopMargin.NONE.value)
|
||||||
var showClock by booleanPref(key = "PREF_SHOW_CLOCK", default = false)
|
var showClock by booleanPref(key = "PREF_SHOW_CLOCK", default = false)
|
||||||
var clockAppName by stringPref(key = "PREF_CLOCK_APP_NAME", default = "")
|
var clockAppName by stringPref(key = "PREF_CLOCK_APP_NAME", default = "")
|
||||||
var clockAppPackage by stringPref(key = "PREF_CLOCK_APP_PACKAGE", default = "")
|
var clockAppPackage by stringPref(key = "PREF_CLOCK_APP_PACKAGE", default = "")
|
||||||
@ -108,12 +108,9 @@ object Preferences : KotprefModel() {
|
|||||||
var customFontName by stringPref(default = "")
|
var customFontName by stringPref(default = "")
|
||||||
var customFontVariant by stringPref(default = "regular")
|
var customFontVariant by stringPref(default = "regular")
|
||||||
var showNextEvent by booleanPref(key = "PREF_SHOW_NEXT_EVENT", default = true)
|
var showNextEvent by booleanPref(key = "PREF_SHOW_NEXT_EVENT", default = true)
|
||||||
var showNextEventOnMultipleLines by booleanPref(default = false)
|
|
||||||
|
|
||||||
var showDividers by booleanPref(default = true)
|
var showDividers by booleanPref(default = true)
|
||||||
|
|
||||||
var widgetAlign by intPref(default = Constants.WidgetAlign.CENTER.rawValue)
|
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
var showWallpaper by booleanPref(default = true)
|
var showWallpaper by booleanPref(default = true)
|
||||||
var showPreview by booleanPref(default = true)
|
var showPreview by booleanPref(default = true)
|
||||||
@ -130,7 +127,7 @@ object Preferences : KotprefModel() {
|
|||||||
var showDailySteps by booleanPref(default = false)
|
var showDailySteps by booleanPref(default = false)
|
||||||
var showGreetings by booleanPref(default = false)
|
var showGreetings by booleanPref(default = false)
|
||||||
var showNotifications by booleanPref(default = false)
|
var showNotifications by booleanPref(default = false)
|
||||||
var hideNotificationAfter by intPref(default = Constants.GlanceNotificationTimer.ONE_MINUTE.rawValue)
|
var hideNotificationAfter by intPref(default = Constants.GlanceNotificationTimer.ONE_MINUTE.value)
|
||||||
|
|
||||||
var lastNotificationId by intPref(default = -1)
|
var lastNotificationId by intPref(default = -1)
|
||||||
var lastNotificationTitle by stringPref(default = "")
|
var lastNotificationTitle by stringPref(default = "")
|
||||||
@ -147,7 +144,6 @@ object Preferences : KotprefModel() {
|
|||||||
var appNotificationsFilter by stringPref(default = "")
|
var appNotificationsFilter by stringPref(default = "")
|
||||||
|
|
||||||
var showEventsAsGlanceProvider by booleanPref(default = false)
|
var showEventsAsGlanceProvider by booleanPref(default = false)
|
||||||
var showWeatherAsGlanceProvider by booleanPref(default = false)
|
|
||||||
|
|
||||||
// Integrations
|
// Integrations
|
||||||
var installedIntegrations by intPref(default = 0)
|
var installedIntegrations by intPref(default = 0)
|
||||||
|
@ -25,7 +25,6 @@ object ActiveNotificationsHelper {
|
|||||||
remove(Preferences::lastNotificationIcon)
|
remove(Preferences::lastNotificationIcon)
|
||||||
}
|
}
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
NotificationListener.clearTimeout(context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkNotificationAccess(context: Context): Boolean {
|
fun checkNotificationAccess(context: Context): Boolean {
|
||||||
|
@ -5,9 +5,10 @@ import android.app.PendingIntent
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
|
import android.util.Log
|
||||||
import com.tommasoberlose.anotherwidget.global.Actions
|
import com.tommasoberlose.anotherwidget.global.Actions
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
|
||||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||||
import com.tommasoberlose.anotherwidget.utils.setExactIfCanSchedule
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -43,27 +44,19 @@ object AlarmHelper {
|
|||||||
val intent = Intent(context, UpdatesReceiver::class.java).apply {
|
val intent = Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
action = Actions.ACTION_ALARM_UPDATE
|
action = Actions.ACTION_ALARM_UPDATE
|
||||||
}
|
}
|
||||||
setExactIfCanSchedule(
|
cancel(PendingIntent.getBroadcast(context, ALARM_UPDATE_ID, intent, 0))
|
||||||
|
setExact(
|
||||||
AlarmManager.RTC,
|
AlarmManager.RTC,
|
||||||
trigger,
|
trigger,
|
||||||
PendingIntent.getBroadcast(
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
ALARM_UPDATE_ID,
|
ALARM_UPDATE_ID,
|
||||||
intent,
|
intent,
|
||||||
PendingIntent.FLAG_IMMUTABLE
|
0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearTimeout(context: Context) {
|
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
|
||||||
val intent = Intent(context, UpdatesReceiver::class.java).apply {
|
|
||||||
action = Actions.ACTION_ALARM_UPDATE
|
|
||||||
}
|
|
||||||
cancel(PendingIntent.getBroadcast(context, ALARM_UPDATE_ID, intent, PendingIntent.FLAG_IMMUTABLE))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private const val ALARM_UPDATE_ID = 24953
|
private const val ALARM_UPDATE_ID = 24953
|
||||||
}
|
}
|
@ -4,9 +4,11 @@ import android.content.Context
|
|||||||
import android.graphics.*
|
import android.graphics.*
|
||||||
import android.graphics.drawable.BitmapDrawable
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.graphics.drawable.DrawableCompat
|
import androidx.core.graphics.drawable.DrawableCompat
|
||||||
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
|
|
||||||
|
|
||||||
object BitmapHelper {
|
object BitmapHelper {
|
||||||
@ -37,6 +39,15 @@ object BitmapHelper {
|
|||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (draw) {
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("WIDTH SPEC", measuredWidth)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("HEIGHT SPEC", measuredHeight)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("VIEW measuredWidth", view.measuredWidth)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("VIEW measuredHeight", view.measuredHeight)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("WIDGET final width", measuredWidth)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("WIDGET final height", view.measuredHeight)
|
||||||
|
}
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
val btm = Bitmap.createBitmap(
|
val btm = Bitmap.createBitmap(
|
||||||
widgetWidth,
|
widgetWidth,
|
||||||
@ -47,12 +58,13 @@ object BitmapHelper {
|
|||||||
//Bind a canvas to it
|
//Bind a canvas to it
|
||||||
val canvas = Canvas(btm)
|
val canvas = Canvas(btm)
|
||||||
// draw the view on the canvas
|
// draw the view on the canvas
|
||||||
view.layout(0, 0, widgetWidth, widgetHeight)
|
view.layout(0, 0, measuredWidth, measuredHeight)
|
||||||
view.draw(canvas)
|
view.draw(canvas)
|
||||||
//return the bitmap
|
//return the bitmap
|
||||||
}
|
}
|
||||||
btm
|
btm
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
|
FirebaseCrashlytics.getInstance().recordException(ex)
|
||||||
Bitmap.createBitmap(5, 5, Bitmap.Config.ALPHA_8)
|
Bitmap.createBitmap(5, 5, Bitmap.Config.ALPHA_8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,10 @@ import android.Manifest
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.provider.CalendarContract
|
import android.provider.CalendarContract
|
||||||
|
import com.tommasoberlose.anotherwidget.services.EventListenerJob
|
||||||
import com.tommasoberlose.anotherwidget.models.Event
|
import com.tommasoberlose.anotherwidget.models.Event
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.services.UpdateCalendarWorker
|
import com.tommasoberlose.anotherwidget.services.UpdateCalendarService
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
import me.everything.providers.android.calendar.CalendarProvider
|
import me.everything.providers.android.calendar.CalendarProvider
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -18,7 +19,7 @@ import kotlin.collections.ArrayList
|
|||||||
|
|
||||||
object CalendarHelper {
|
object CalendarHelper {
|
||||||
fun updateEventList(context: Context) {
|
fun updateEventList(context: Context) {
|
||||||
UpdateCalendarWorker.enqueue(context)
|
UpdateCalendarService.enqueueWork(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCalendarList(context: Context): List<me.everything.providers.android.calendar.Calendar> {
|
fun getCalendarList(context: Context): List<me.everything.providers.android.calendar.Calendar> {
|
||||||
@ -49,11 +50,11 @@ object CalendarHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setEventUpdatesAndroidN(context: Context) {
|
fun setEventUpdatesAndroidN(context: Context) {
|
||||||
UpdateCalendarWorker.enqueueTrigger(context)
|
EventListenerJob.schedule(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeEventUpdatesAndroidN(context: Context) {
|
fun removeEventUpdatesAndroidN(context: Context) {
|
||||||
UpdateCalendarWorker.cancelTrigger(context)
|
EventListenerJob.remove(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun List<Event>.applyFilters() : List<Event> {
|
fun List<Event>.applyFilters() : List<Event> {
|
||||||
|
@ -1,20 +1,10 @@
|
|||||||
package com.tommasoberlose.anotherwidget.helpers
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.ClipData
|
|
||||||
import android.content.ClipboardManager
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Context.CLIPBOARD_SERVICE
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.util.Log
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import com.tommasoberlose.anotherwidget.R
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.toast
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
||||||
object ColorHelper {
|
object ColorHelper {
|
||||||
fun getFontColor(isDark: Boolean): Int {
|
fun getFontColor(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
@ -154,40 +144,4 @@ object ColorHelper {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("DefaultLocale")
|
|
||||||
fun Context.copyToClipboard(color: Int?, alpha: Int) {
|
|
||||||
if (color == null) return toast(getString(R.string.error_copy_color))
|
|
||||||
with(getSystemService(CLIPBOARD_SERVICE) as ClipboardManager) {
|
|
||||||
try {
|
|
||||||
val colorString = Integer.toHexString(color)
|
|
||||||
val clip = "#%s%s".format(
|
|
||||||
alpha.toHexValue(),
|
|
||||||
if (colorString.length > 6) colorString.substring(2) else colorString
|
|
||||||
).toUpperCase()
|
|
||||||
setPrimaryClip(ClipData.newPlainText(clip, clip))
|
|
||||||
toast(getString(R.string.color_copied))
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
toast(getString(R.string.error_copy_color))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Context.isClipboardColor(): Boolean {
|
|
||||||
with(getSystemService(CLIPBOARD_SERVICE) as ClipboardManager) {
|
|
||||||
return try { primaryClip?.getItemAt(0)?.text?.toString()?.isColor() ?: false } catch (ex: Exception) { false }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Context.pasteFromClipboard(pasteColor: (color: String, alpha: String) -> Unit) {
|
|
||||||
with(getSystemService(CLIPBOARD_SERVICE) as ClipboardManager) {
|
|
||||||
primaryClip?.let {
|
|
||||||
val item = it.getItemAt(0).text.toString().replace("#", "")
|
|
||||||
val color = if (item.length > 6) item.substring(2) else item
|
|
||||||
val alpha = if (item.length > 6) item.substring(0, 2) else "00"
|
|
||||||
pasteColor("#$color", alpha)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -90,12 +90,6 @@ object GlanceProviderHelper {
|
|||||||
R.drawable.round_event_note_24
|
R.drawable.round_event_note_24
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Constants.GlanceProviderId.WEATHER -> {
|
|
||||||
GlanceProvider(providerId.id,
|
|
||||||
context.getString(R.string.settings_show_weather_as_glance_provider_title),
|
|
||||||
R.drawable.round_brightness_5_24
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,11 +108,10 @@ object GlanceProviderHelper {
|
|||||||
(MediaPlayerHelper.isSomeonePlaying(context)) ||
|
(MediaPlayerHelper.isSomeonePlaying(context)) ||
|
||||||
(Preferences.showBatteryCharging && Preferences.isCharging || Preferences.isBatteryLevelLow) ||
|
(Preferences.showBatteryCharging && Preferences.isCharging || Preferences.isBatteryLevelLow) ||
|
||||||
(Preferences.customNotes.isNotEmpty()) ||
|
(Preferences.customNotes.isNotEmpty()) ||
|
||||||
(Preferences.showWeatherAsGlanceProvider && Preferences.showWeather && Preferences.weatherIcon != "") ||
|
|
||||||
(Preferences.showDailySteps && Preferences.googleFitSteps > 0) ||
|
(Preferences.showDailySteps && Preferences.googleFitSteps > 0) ||
|
||||||
(Preferences.showGreetings && GreetingsHelper.showGreetings()) ||
|
(Preferences.showGreetings && GreetingsHelper.showGreetings()) ||
|
||||||
(Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(
|
(Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(
|
||||||
Manifest.permission.READ_CALENDAR) && eventRepository.getNextEvent() != null)
|
Manifest.permission.READ_CALENDAR) && eventRepository.getNextEvent() != null)
|
||||||
)
|
)
|
||||||
eventRepository.close()
|
eventRepository.close()
|
||||||
return showGlance
|
return showGlance
|
||||||
|
@ -37,7 +37,7 @@ object GreetingsHelper {
|
|||||||
Intent(context, UpdatesReceiver::class.java).apply {
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
action = Actions.ACTION_UPDATE_GREETINGS
|
action = Actions.ACTION_UPDATE_GREETINGS
|
||||||
},
|
},
|
||||||
PendingIntent.FLAG_IMMUTABLE)
|
0)
|
||||||
)
|
)
|
||||||
|
|
||||||
setRepeating(
|
setRepeating(
|
||||||
@ -51,7 +51,7 @@ object GreetingsHelper {
|
|||||||
Intent(context, UpdatesReceiver::class.java).apply {
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
action = Actions.ACTION_UPDATE_GREETINGS
|
action = Actions.ACTION_UPDATE_GREETINGS
|
||||||
},
|
},
|
||||||
PendingIntent.FLAG_IMMUTABLE)
|
0)
|
||||||
)
|
)
|
||||||
|
|
||||||
setRepeating(
|
setRepeating(
|
||||||
@ -65,7 +65,7 @@ object GreetingsHelper {
|
|||||||
Intent(context, UpdatesReceiver::class.java).apply {
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
action = Actions.ACTION_UPDATE_GREETINGS
|
action = Actions.ACTION_UPDATE_GREETINGS
|
||||||
},
|
},
|
||||||
PendingIntent.FLAG_IMMUTABLE)
|
0)
|
||||||
)
|
)
|
||||||
|
|
||||||
setRepeating(
|
setRepeating(
|
||||||
@ -79,14 +79,14 @@ object GreetingsHelper {
|
|||||||
Intent(context, UpdatesReceiver::class.java).apply {
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
action = Actions.ACTION_UPDATE_GREETINGS
|
action = Actions.ACTION_UPDATE_GREETINGS
|
||||||
},
|
},
|
||||||
PendingIntent.FLAG_IMMUTABLE)
|
0)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
listOf(MORNING_TIME, MORNING_TIME_END, EVENING_TIME, NIGHT_TIME).forEach {
|
listOf(MORNING_TIME, MORNING_TIME_END, EVENING_TIME, NIGHT_TIME).forEach {
|
||||||
cancel(PendingIntent.getBroadcast(context, it, Intent(context,
|
cancel(PendingIntent.getBroadcast(context, it, Intent(context,
|
||||||
UpdatesReceiver::class.java).apply {
|
UpdatesReceiver::class.java).apply {
|
||||||
action = Actions.ACTION_UPDATE_GREETINGS
|
action = Actions.ACTION_UPDATE_GREETINGS
|
||||||
}, PendingIntent.FLAG_IMMUTABLE))
|
}, 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,9 +102,9 @@ object GreetingsHelper {
|
|||||||
val array = when {
|
val array = when {
|
||||||
hour in 5..8 -> context.resources.getStringArray(R.array.morning_greetings)
|
hour in 5..8 -> context.resources.getStringArray(R.array.morning_greetings)
|
||||||
hour in 19..21 -> context.resources.getStringArray(R.array.evening_greetings)
|
hour in 19..21 -> context.resources.getStringArray(R.array.evening_greetings)
|
||||||
hour >= 22 || hour < 5 -> context.resources.getStringArray(R.array.night_greetings)
|
hour >= 22 && hour < 5 -> context.resources.getStringArray(R.array.night_greetings)
|
||||||
else -> emptyArray()
|
else -> emptyArray()
|
||||||
}
|
}
|
||||||
return if (array.isNotEmpty()) array[Random().nextInt(array.size)] else ""
|
return if (array.isNotEmpty()) array[Random().nextInt(array.size)] else ""
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,10 +17,10 @@ object ImageHelper {
|
|||||||
0 -> 0f * factor
|
0 -> 0f * factor
|
||||||
1 -> 8f * factor
|
1 -> 8f * factor
|
||||||
2 -> 16f * factor
|
2 -> 16f * factor
|
||||||
else -> 8f * factor
|
else -> 0f * factor
|
||||||
}, resources.displayMetrics)
|
}, resources.displayMetrics)
|
||||||
|
|
||||||
if (originalView.drawable != null && originalView.drawable.intrinsicWidth > 0 && originalView.drawable.intrinsicHeight > 0) {
|
if (originalView.drawable != null) {
|
||||||
val btm = originalView.drawable.toBitmap().copy(Bitmap.Config.ARGB_8888, true)
|
val btm = originalView.drawable.toBitmap().copy(Bitmap.Config.ARGB_8888, true)
|
||||||
val comb = Bitmap.createBitmap(btm)
|
val comb = Bitmap.createBitmap(btm)
|
||||||
val shadowBitmap = generateShadowBitmap(context, cElevation, btm, factor)
|
val shadowBitmap = generateShadowBitmap(context, cElevation, btm, factor)
|
||||||
@ -58,7 +58,7 @@ object ImageHelper {
|
|||||||
0 -> 0f * factor
|
0 -> 0f * factor
|
||||||
1 -> 0.8f * factor
|
1 -> 0.8f * factor
|
||||||
2 -> 1f * factor
|
2 -> 1f * factor
|
||||||
else -> 0.8f * factor
|
else -> 0f
|
||||||
}))
|
}))
|
||||||
|
|
||||||
colorMatrixScript.setColorMatrix(matrix)
|
colorMatrixScript.setColorMatrix(matrix)
|
||||||
@ -73,9 +73,6 @@ object ImageHelper {
|
|||||||
|
|
||||||
allocationIn.destroy()
|
allocationIn.destroy()
|
||||||
allocationOut.destroy()
|
allocationOut.destroy()
|
||||||
colorMatrixScript.destroy()
|
|
||||||
blurScript.destroy()
|
|
||||||
//rs.destroy()
|
|
||||||
|
|
||||||
return bitmap
|
return bitmap
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.tommasoberlose.anotherwidget.helpers
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.appwidget.AppWidgetManager
|
import android.appwidget.AppWidgetManager
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.ContentUris
|
import android.content.ContentUris
|
||||||
@ -13,10 +12,8 @@ import android.provider.CalendarContract
|
|||||||
import android.provider.CalendarContract.Events
|
import android.provider.CalendarContract.Events
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.global.Actions
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.models.Event
|
import com.tommasoberlose.anotherwidget.models.Event
|
||||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import com.tommasoberlose.anotherwidget.utils.toast
|
import com.tommasoberlose.anotherwidget.utils.toast
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -28,13 +25,6 @@ object IntentHelper {
|
|||||||
const val DO_NOTHING_OPTION = "DO_NOTHING"
|
const val DO_NOTHING_OPTION = "DO_NOTHING"
|
||||||
const val REFRESH_WIDGET_OPTION = "REFRESH_WIDGET"
|
const val REFRESH_WIDGET_OPTION = "REFRESH_WIDGET"
|
||||||
|
|
||||||
fun getPendingIntent(context: Context, requestCode: Int, intent: Intent, flags: Int): PendingIntent {
|
|
||||||
return if (intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK == Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
PendingIntent.getActivity(context, requestCode, intent, flags)
|
|
||||||
else
|
|
||||||
PendingIntent.getBroadcast(context, requestCode, intent, flags)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getWidgetUpdateIntent(context: Context): Intent {
|
fun getWidgetUpdateIntent(context: Context): Intent {
|
||||||
val widgetManager = AppWidgetManager.getInstance(context)
|
val widgetManager = AppWidgetManager.getInstance(context)
|
||||||
val widgetComponent = ComponentName(context, MainWidget::class.java)
|
val widgetComponent = ComponentName(context, MainWidget::class.java)
|
||||||
@ -45,22 +35,17 @@ object IntentHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getWidgetRefreshIntent(context: Context): Intent {
|
|
||||||
return Intent(context, UpdatesReceiver::class.java).apply {
|
|
||||||
action = Actions.ACTION_REFRESH
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getGoogleMapsIntentFromAddress(context: Context, address: String): Intent {
|
fun getGoogleMapsIntentFromAddress(context: Context, address: String): Intent {
|
||||||
val gmmIntentUri: Uri = Uri.parse("geo:0,0?q=${Uri.encode(address)}")
|
val gmmIntentUri: Uri = Uri.parse("geo:0,0?q=$address")
|
||||||
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
|
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
|
||||||
//mapIntent.`package` = "com.google.android.apps.maps"
|
mapIntent.`package` = "com.google.android.apps.maps"
|
||||||
|
|
||||||
return if (mapIntent.resolveActivity(context.packageManager) != null) {
|
return if (mapIntent.resolveActivity(context.packageManager) != null) {
|
||||||
mapIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
mapIntent
|
||||||
} else {
|
} else {
|
||||||
val map = "https://www.google.com/maps/search/?api=1&query=${Uri.encode(address)}"
|
val map = "http://maps.google.co.in/maps?q=$address"
|
||||||
Intent(Intent.ACTION_VIEW, Uri.parse(map)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
val i = Intent(Intent.ACTION_VIEW, Uri.parse(map));
|
||||||
|
i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,17 +53,17 @@ object IntentHelper {
|
|||||||
return when (Preferences.weatherAppPackage) {
|
return when (Preferences.weatherAppPackage) {
|
||||||
DEFAULT_OPTION -> {
|
DEFAULT_OPTION -> {
|
||||||
Intent(Intent.ACTION_VIEW).apply {
|
Intent(Intent.ACTION_VIEW).apply {
|
||||||
|
addCategory(Intent.CATEGORY_DEFAULT)
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
data = Uri.parse("dynact://velour/weather/ProxyActivity")
|
data = Uri.parse("dynact://velour/weather/ProxyActivity")
|
||||||
component = ComponentName("com.google.android.googlequicksearchbox", "com.google.android.apps.gsa.velour.DynamicActivityTrampoline")
|
component = ComponentName("com.google.android.googlequicksearchbox", "com.google.android.apps.gsa.velour.DynamicActivityTrampoline")
|
||||||
setClassName("com.google.android.googlequicksearchbox", "com.google.android.apps.gsa.velour.DynamicActivityTrampoline")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DO_NOTHING_OPTION -> {
|
DO_NOTHING_OPTION -> {
|
||||||
Intent()
|
Intent()
|
||||||
}
|
}
|
||||||
REFRESH_WIDGET_OPTION -> {
|
REFRESH_WIDGET_OPTION -> {
|
||||||
getWidgetRefreshIntent(context)
|
getWidgetUpdateIntent(context)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val pm: PackageManager = context.packageManager
|
val pm: PackageManager = context.packageManager
|
||||||
@ -94,16 +79,15 @@ object IntentHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCalendarIntent(context: Context, time: Long? = null): Intent {
|
fun getCalendarIntent(context: Context): Intent {
|
||||||
val calendarUri = CalendarContract.CONTENT_URI
|
val calendarUri = CalendarContract.CONTENT_URI
|
||||||
.buildUpon()
|
.buildUpon()
|
||||||
.appendPath("time")
|
.appendPath("time")
|
||||||
.appendPath((time ?: Calendar.getInstance().timeInMillis).toString())
|
.appendPath(Calendar.getInstance().timeInMillis.toString())
|
||||||
.build()
|
.build()
|
||||||
return when (Preferences.calendarAppPackage) {
|
return when (Preferences.calendarAppPackage) {
|
||||||
DEFAULT_OPTION -> {
|
DEFAULT_OPTION -> {
|
||||||
Intent(Intent.ACTION_VIEW).apply {
|
Intent(Intent.ACTION_VIEW).apply {
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
||||||
data = calendarUri
|
data = calendarUri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,14 +95,12 @@ object IntentHelper {
|
|||||||
Intent()
|
Intent()
|
||||||
}
|
}
|
||||||
REFRESH_WIDGET_OPTION -> {
|
REFRESH_WIDGET_OPTION -> {
|
||||||
getWidgetRefreshIntent(context)
|
getWidgetUpdateIntent(context)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val pm: PackageManager = context.packageManager
|
val pm: PackageManager = context.packageManager
|
||||||
try {
|
try {
|
||||||
pm.getLaunchIntentForPackage(Preferences.calendarAppPackage)!!.apply {
|
pm.getLaunchIntentForPackage(Preferences.calendarAppPackage)!!.apply {
|
||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
||||||
action = Intent.ACTION_VIEW
|
action = Intent.ACTION_VIEW
|
||||||
data = calendarUri
|
data = calendarUri
|
||||||
}
|
}
|
||||||
@ -185,7 +167,7 @@ object IntentHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
false -> {
|
false -> {
|
||||||
getCalendarIntent(context, e.startDate)
|
getCalendarIntent(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,7 +183,7 @@ object IntentHelper {
|
|||||||
Intent()
|
Intent()
|
||||||
}
|
}
|
||||||
REFRESH_WIDGET_OPTION -> {
|
REFRESH_WIDGET_OPTION -> {
|
||||||
getWidgetRefreshIntent(context)
|
getWidgetUpdateIntent(context)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val pm: PackageManager = context.packageManager
|
val pm: PackageManager = context.packageManager
|
||||||
@ -217,7 +199,7 @@ object IntentHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getBatteryIntent(): Intent {
|
fun getBatteryIntent(): Intent {
|
||||||
return Intent(Intent.ACTION_POWER_USAGE_SUMMARY).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
return Intent(Intent.ACTION_POWER_USAGE_SUMMARY)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMusicIntent(context: Context): Intent {
|
fun getMusicIntent(context: Context): Intent {
|
||||||
@ -230,7 +212,6 @@ object IntentHelper {
|
|||||||
try {
|
try {
|
||||||
pm.getLaunchIntentForPackage(Preferences.mediaPlayerPackage)!!.apply {
|
pm.getLaunchIntentForPackage(Preferences.mediaPlayerPackage)!!.apply {
|
||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Intent()
|
Intent()
|
||||||
@ -244,7 +225,6 @@ object IntentHelper {
|
|||||||
return try {
|
return try {
|
||||||
pm.getLaunchIntentForPackage("com.google.android.apps.fitness")!!.apply {
|
pm.getLaunchIntentForPackage("com.google.android.apps.fitness")!!.apply {
|
||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Intent()
|
Intent()
|
||||||
@ -256,7 +236,6 @@ object IntentHelper {
|
|||||||
return try {
|
return try {
|
||||||
pm.getLaunchIntentForPackage(Preferences.lastNotificationPackage)!!.apply {
|
pm.getLaunchIntentForPackage(Preferences.lastNotificationPackage)!!.apply {
|
||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Intent()
|
Intent()
|
||||||
|
@ -12,7 +12,6 @@ import com.chibatching.kotpref.bulk
|
|||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.receivers.NotificationListener
|
import com.tommasoberlose.anotherwidget.receivers.NotificationListener
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import com.tommasoberlose.anotherwidget.utils.ignoreExceptions
|
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
|
|
||||||
object MediaPlayerHelper {
|
object MediaPlayerHelper {
|
||||||
@ -34,14 +33,12 @@ object MediaPlayerHelper {
|
|||||||
DEFAULT_MEDIA_INFO_FORMAT.replace(MEDIA_INFO_TITLE, title)
|
DEFAULT_MEDIA_INFO_FORMAT.replace(MEDIA_INFO_TITLE, title)
|
||||||
.replace(MEDIA_INFO_ARTIST, artist)
|
.replace(MEDIA_INFO_ARTIST, artist)
|
||||||
.replace(MEDIA_INFO_ALBUM, album)
|
.replace(MEDIA_INFO_ALBUM, album)
|
||||||
.replace("\\n", System.getProperty("line.separator") ?: " ")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
format.replace(MEDIA_INFO_TITLE, title)
|
format.replace(MEDIA_INFO_TITLE, title)
|
||||||
.replace(MEDIA_INFO_ARTIST, artist)
|
.replace(MEDIA_INFO_ARTIST, artist)
|
||||||
.replace(MEDIA_INFO_ALBUM, album)
|
.replace(MEDIA_INFO_ALBUM, album)
|
||||||
.replace("\\n", System.getProperty("line.separator") ?: " ")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,24 +67,15 @@ object MediaPlayerHelper {
|
|||||||
isSomeonePlaying = true
|
isSomeonePlaying = true
|
||||||
if (metadata != null) {
|
if (metadata != null) {
|
||||||
Preferences.bulk {
|
Preferences.bulk {
|
||||||
ignoreExceptions {
|
mediaPlayerTitle =
|
||||||
mediaPlayerTitle =
|
metadata.getText(MediaMetadata.METADATA_KEY_TITLE)?.toString()
|
||||||
metadata.getText(MediaMetadata.METADATA_KEY_TITLE)
|
?: ""
|
||||||
?.toString()
|
mediaPlayerArtist =
|
||||||
?: ""
|
metadata.getText(MediaMetadata.METADATA_KEY_ARTIST)?.toString()
|
||||||
}
|
?: ""
|
||||||
ignoreExceptions {
|
mediaPlayerAlbum =
|
||||||
mediaPlayerArtist =
|
metadata.getText(MediaMetadata.METADATA_KEY_ALBUM)?.toString()
|
||||||
metadata.getText(MediaMetadata.METADATA_KEY_ARTIST)
|
?: ""
|
||||||
?.toString()
|
|
||||||
?: ""
|
|
||||||
}
|
|
||||||
ignoreExceptions {
|
|
||||||
mediaPlayerAlbum =
|
|
||||||
metadata.getText(MediaMetadata.METADATA_KEY_ALBUM)
|
|
||||||
?.toString()
|
|
||||||
?: ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,26 +88,43 @@ object SettingsStringHelper {
|
|||||||
fun getDifferenceText(context: Context, now: Long, start: Long): String {
|
fun getDifferenceText(context: Context, now: Long, start: Long): String {
|
||||||
val nowDate = DateTime(now)
|
val nowDate = DateTime(now)
|
||||||
val eventDate = DateTime(start)
|
val eventDate = DateTime(start)
|
||||||
val difference = start - now
|
|
||||||
|
var difference = start - now
|
||||||
|
difference += 60 * 1000 - (difference % (60 * 1000))
|
||||||
|
|
||||||
when {
|
when {
|
||||||
difference <= 0 -> {
|
difference <= 0 -> {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.HIGH.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) >= 5 -> {
|
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.HIGH.value && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> {
|
||||||
return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - TimeUnit.MILLISECONDS.toMinutes(difference) % 5), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 5), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
||||||
}
|
}
|
||||||
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.DEFAULT.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) >= 15 -> {
|
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.DEFAULT.value && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> {
|
||||||
return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - TimeUnit.MILLISECONDS.toMinutes(difference) % 15), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 15), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
||||||
}
|
}
|
||||||
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.LOW.rawValue -> {
|
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.LOW.value -> {
|
||||||
return context.getString(R.string.soon)
|
return context.getString(R.string.soon)
|
||||||
}
|
}
|
||||||
TimeUnit.MILLISECONDS.toHours(difference) < 1 -> {
|
TimeUnit.MILLISECONDS.toHours(difference) < 1 -> {
|
||||||
return context.getString(R.string.now)
|
return context.getString(R.string.now)
|
||||||
}
|
}
|
||||||
TimeUnit.MILLISECONDS.toHours(difference) < 12 -> {
|
TimeUnit.MILLISECONDS.toHours(difference) < 12 -> {
|
||||||
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.HOUR_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
val minutes = TimeUnit.MILLISECONDS.toMinutes(difference) - 60 * TimeUnit.MILLISECONDS.toHours(difference)
|
||||||
|
return if (minutes < 1 || minutes > 30) {
|
||||||
|
DateUtils.getRelativeTimeSpanString(
|
||||||
|
start,
|
||||||
|
now - 1000 * 60 * 40,
|
||||||
|
DateUtils.HOUR_IN_MILLIS,
|
||||||
|
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||||
|
).toString()
|
||||||
|
} else {
|
||||||
|
DateUtils.getRelativeTimeSpanString(
|
||||||
|
start,
|
||||||
|
now,
|
||||||
|
DateUtils.HOUR_IN_MILLIS,
|
||||||
|
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||||
|
).toString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
eventDate.dayOfYear == nowDate.plusDays(1).dayOfYear -> {
|
eventDate.dayOfYear == nowDate.plusDays(1).dayOfYear -> {
|
||||||
return String.format("%s", context.getString(R.string.tomorrow))
|
return String.format("%s", context.getString(R.string.tomorrow))
|
||||||
@ -126,6 +143,9 @@ object SettingsStringHelper {
|
|||||||
val nowDate = DateTime(now)
|
val nowDate = DateTime(now)
|
||||||
val eventDate = DateTime(start)
|
val eventDate = DateTime(start)
|
||||||
|
|
||||||
|
var difference = start - now
|
||||||
|
difference += 60 * 1000 - (difference % (60 * 1000))
|
||||||
|
|
||||||
return when (eventDate.dayOfYear) {
|
return when (eventDate.dayOfYear) {
|
||||||
nowDate.dayOfYear -> {
|
nowDate.dayOfYear -> {
|
||||||
""
|
""
|
||||||
|
@ -2,15 +2,23 @@ package com.tommasoberlose.anotherwidget.helpers
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.Log
|
||||||
import com.chibatching.kotpref.Kotpref
|
import com.chibatching.kotpref.Kotpref
|
||||||
|
import com.google.android.gms.location.LocationServices
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
||||||
import com.tommasoberlose.anotherwidget.services.WeatherWorker
|
import com.tommasoberlose.anotherwidget.services.LocationService
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,14 +27,13 @@ import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
|||||||
|
|
||||||
object WeatherHelper {
|
object WeatherHelper {
|
||||||
|
|
||||||
fun updateWeather(context: Context, force: Boolean = false) {
|
suspend fun updateWeather(context: Context) {
|
||||||
if (Preferences.showWeather || force)
|
Kotpref.init(context)
|
||||||
WeatherWorker.enqueue(context, replace = force)
|
val networkApi = WeatherNetworkApi(context)
|
||||||
else {
|
if (Preferences.customLocationAdd != "") {
|
||||||
removeWeather(context)
|
networkApi.updateWeather()
|
||||||
org.greenrobot.eventbus.EventBus.getDefault().post(
|
} else if (context.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
|
||||||
com.tommasoberlose.anotherwidget.ui.fragments.MainFragment.UpdateUiMessageEvent()
|
LocationService.requestNewLocation(context)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,97 +122,97 @@ object WeatherHelper {
|
|||||||
return when (icon) {
|
return when (icon) {
|
||||||
"01d" -> {
|
"01d" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.clear_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.clear_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.clear_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.clear_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.clear_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.clear_day_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.clear_day_5 else R.drawable.clear_day_5_light
|
else -> if (context.isDarkTheme()) R.drawable.clear_day_5 else R.drawable.clear_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"02d" -> {
|
"02d" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.partly_cloudy_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.partly_cloudy_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.partly_cloudy_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.partly_cloudy_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.partly_cloudy_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.partly_cloudy_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.partly_cloudy_5 else R.drawable.partly_cloudy_5_light
|
else -> if (context.isDarkTheme()) R.drawable.partly_cloudy_5 else R.drawable.partly_cloudy_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"03d" -> {
|
"03d" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.mostly_cloudy_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.mostly_cloudy_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.mostly_cloudy_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.mostly_cloudy_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.mostly_cloudy_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.mostly_cloudy_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.mostly_cloudy_5 else R.drawable.mostly_cloudy_5_light
|
else -> if (context.isDarkTheme()) R.drawable.mostly_cloudy_5 else R.drawable.mostly_cloudy_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"04d" -> {
|
"04d" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.cloudy_weather_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.cloudy_weather_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.cloudy_weather_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.cloudy_weather_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.cloudy_weather_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.cloudy_weather_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.cloudy_weather_5 else R.drawable.cloudy_weather_5_light
|
else -> if (context.isDarkTheme()) R.drawable.cloudy_weather_5 else R.drawable.cloudy_weather_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"09d" -> {
|
"09d" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.storm_weather_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.storm_weather_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.storm_weather_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.storm_weather_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.storm_weather_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.storm_weather_day_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.storm_weather_day_5 else R.drawable.storm_weather_day_5_light
|
else -> if (context.isDarkTheme()) R.drawable.storm_weather_day_5 else R.drawable.storm_weather_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"10d" -> {
|
"10d" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.rainy_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.rainy_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.rainy_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rainy_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.rainy_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rainy_day_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.rainy_day_5 else R.drawable.rainy_day_5_light
|
else -> if (context.isDarkTheme()) R.drawable.rainy_day_5 else R.drawable.rainy_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"11d" -> {
|
"11d" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.thunder_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.thunder_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.thunder_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.thunder_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.thunder_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.thunder_day_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.thunder_day_5 else R.drawable.thunder_day_5_light
|
else -> if (context.isDarkTheme()) R.drawable.thunder_day_5 else R.drawable.thunder_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"13d" -> {
|
"13d" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.snow_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.snow_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.snow_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.snow_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.snow_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.snow_day_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.snow_day_5 else R.drawable.snow_day_5_light
|
else -> if (context.isDarkTheme()) R.drawable.snow_day_5 else R.drawable.snow_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"50d" -> {
|
"50d" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.haze_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.haze_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.haze_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_day_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.haze_day_5 else R.drawable.haze_day_5_light
|
else -> if (context.isDarkTheme()) R.drawable.haze_day_5 else R.drawable.haze_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"80d" -> {
|
"80d" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.windy_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.windy_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.windy_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.windy_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.windy_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.windy_day_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.windy_day_5 else R.drawable.windy_day_5_light
|
else -> if (context.isDarkTheme()) R.drawable.windy_day_5 else R.drawable.windy_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"81d" -> {
|
"81d" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.rain_snow_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.rain_snow_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.rain_snow_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rain_snow_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.rain_snow_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rain_snow_day_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.rain_snow_day_5 else R.drawable.rain_snow_day_5_light
|
else -> if (context.isDarkTheme()) R.drawable.rain_snow_day_5 else R.drawable.rain_snow_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"82d" -> {
|
"82d" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.haze_weather_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_weather_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.haze_weather_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_weather_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.haze_weather_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_weather_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.haze_weather_5 else R.drawable.haze_weather_5_light
|
else -> if (context.isDarkTheme()) R.drawable.haze_weather_5 else R.drawable.haze_weather_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -214,97 +221,97 @@ object WeatherHelper {
|
|||||||
|
|
||||||
"01n" -> {
|
"01n" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.clear_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.clear_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.clear_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.clear_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.clear_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.clear_night_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.clear_night_5 else R.drawable.clear_night_5_light
|
else -> if (context.isDarkTheme()) R.drawable.clear_night_5 else R.drawable.clear_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"02n" -> {
|
"02n" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.partly_cloudy_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.partly_cloudy_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.partly_cloudy_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.partly_cloudy_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.partly_cloudy_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.partly_cloudy_night_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.partly_cloudy_night_5 else R.drawable.partly_cloudy_night_5_light
|
else -> if (context.isDarkTheme()) R.drawable.partly_cloudy_night_5 else R.drawable.partly_cloudy_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"03n" -> {
|
"03n" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.mostly_cloudy_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.mostly_cloudy_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.mostly_cloudy_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.mostly_cloudy_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.mostly_cloudy_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.mostly_cloudy_night_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.mostly_cloudy_night_5 else R.drawable.mostly_cloudy_night_5_light
|
else -> if (context.isDarkTheme()) R.drawable.mostly_cloudy_night_5 else R.drawable.mostly_cloudy_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"04n" -> {
|
"04n" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.cloudy_weather_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.cloudy_weather_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.cloudy_weather_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.cloudy_weather_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.cloudy_weather_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.cloudy_weather_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.cloudy_weather_5 else R.drawable.cloudy_weather_5_light
|
else -> if (context.isDarkTheme()) R.drawable.cloudy_weather_5 else R.drawable.cloudy_weather_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"09n" -> {
|
"09n" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.storm_weather_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.storm_weather_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.storm_weather_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.storm_weather_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.storm_weather_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.storm_weather_night_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.storm_weather_night_5 else R.drawable.storm_weather_night_5_light
|
else -> if (context.isDarkTheme()) R.drawable.storm_weather_night_5 else R.drawable.storm_weather_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"10n" -> {
|
"10n" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.rainy_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.rainy_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.rainy_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rainy_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.rainy_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rainy_night_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.rainy_night_5 else R.drawable.rainy_night_5_light
|
else -> if (context.isDarkTheme()) R.drawable.rainy_night_5 else R.drawable.rainy_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"11n" -> {
|
"11n" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.thunder_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.thunder_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.thunder_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.thunder_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.thunder_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.thunder_night_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.thunder_night_5 else R.drawable.thunder_night_5_light
|
else -> if (context.isDarkTheme()) R.drawable.thunder_night_5 else R.drawable.thunder_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"13n" -> {
|
"13n" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.snow_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.snow_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.snow_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.snow_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.snow_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.snow_night_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.snow_night_5 else R.drawable.snow_night_5_light
|
else -> if (context.isDarkTheme()) R.drawable.snow_night_5 else R.drawable.snow_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"50n" -> {
|
"50n" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.haze_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.haze_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.haze_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_night_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.haze_night_5 else R.drawable.haze_night_5_light
|
else -> if (context.isDarkTheme()) R.drawable.haze_night_5 else R.drawable.haze_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"80n" -> {
|
"80n" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.windy_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.windy_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.windy_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.windy_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.windy_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.windy_night_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.windy_night_5 else R.drawable.windy_night_5_light
|
else -> if (context.isDarkTheme()) R.drawable.windy_night_5 else R.drawable.windy_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"81n" -> {
|
"81n" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.rain_snow_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.rain_snow_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.rain_snow_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rain_snow_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.rain_snow_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rain_snow_night_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.rain_snow_night_5 else R.drawable.rain_snow_night_5_light
|
else -> if (context.isDarkTheme()) R.drawable.rain_snow_night_5 else R.drawable.rain_snow_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"82n" -> {
|
"82n" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.rawValue -> R.drawable.haze_weather_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_weather_3
|
||||||
Constants.WeatherIconPack.MINIMAL.rawValue -> R.drawable.haze_weather_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_weather_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.rawValue -> R.drawable.haze_weather_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_weather_4
|
||||||
else -> if (context.isDarkTheme()) R.drawable.haze_weather_5 else R.drawable.haze_weather_5_light
|
else -> if (context.isDarkTheme()) R.drawable.haze_weather_5 else R.drawable.haze_weather_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -314,111 +321,92 @@ object WeatherHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getWeatherLabel(context: Context, icon: String): String {
|
fun getWeatherGovIcon(iconString: String, isDaytime: Boolean): String = when {
|
||||||
return when (icon) {
|
iconString.contains("skc") -> "01"
|
||||||
"01d", "01n" -> context.getString(R.string.weather_label_clear)
|
iconString.contains("few") -> "02"
|
||||||
"02d", "02n" -> context.getString(R.string.weather_label_partly_cloudy)
|
iconString.contains("sct") -> "03"
|
||||||
"03d", "03n" -> context.getString(R.string.weather_label_mostly_cloudy)
|
iconString.contains("bkn") -> "04"
|
||||||
"04d", "04n" -> context.getString(R.string.weather_label_cloudy_weather)
|
iconString.contains("ovc") -> "04"
|
||||||
"09d", "09n" -> context.getString(R.string.weather_label_storm_weather)
|
iconString.contains("wind_skc") -> "01"
|
||||||
"10d", "10n" -> context.getString(R.string.weather_label_rainy)
|
iconString.contains("wind_few") -> "02"
|
||||||
"11d", "11n" -> context.getString(R.string.weather_label_thunder)
|
iconString.contains("wind_sct") -> "03"
|
||||||
"13d", "13n" -> context.getString(R.string.weather_label_snow)
|
iconString.contains("wind_bkn") -> "04"
|
||||||
"50d", "50n", "82d", "82n" -> context.getString(R.string.weather_label_haze)
|
iconString.contains("wind_ovc") -> "04"
|
||||||
"80d", "80n" -> context.getString(R.string.weather_label_windy)
|
iconString.contains("snow") -> "13"
|
||||||
"81d", "81n" -> context.getString(R.string.weather_label_rain_snow)
|
iconString.contains("rain_snow") -> "81"
|
||||||
else -> context.getString(R.string.weather_label_unknown)
|
iconString.contains("rain_sleet") -> "81"
|
||||||
}
|
iconString.contains("snow_sleet") -> "81"
|
||||||
}
|
iconString.contains("fzra") -> "81"
|
||||||
|
iconString.contains("rain_fzra") -> "81"
|
||||||
fun getWeatherGovIcon(iconString: String, isDaytime: Boolean): String = when (
|
iconString.contains("snow_fzra") -> "81"
|
||||||
iconString.substringBefore('?').substringAfterLast('/').substringBefore(',')
|
iconString.contains("sleet") -> "81"
|
||||||
) {
|
iconString.contains("rain") -> "10"
|
||||||
"skc" -> "01"
|
iconString.contains("rain_showers") -> "10"
|
||||||
"few" -> "02"
|
iconString.contains("rain_showers_hi") -> "10"
|
||||||
"sct" -> "02"
|
iconString.contains("tsra") -> "82"
|
||||||
"bkn" -> "03"
|
iconString.contains("tsra_sct") -> "82"
|
||||||
"ovc" -> "04"
|
iconString.contains("tsra_hi") -> "82"
|
||||||
"wind_skc" -> "01"
|
iconString.contains("tornado") -> "80"
|
||||||
"wind_few" -> "02"
|
iconString.contains("hurricane") -> "80"
|
||||||
"wind_sct" -> "02"
|
iconString.contains("tropical_storm") -> "09"
|
||||||
"wind_bkn" -> "03"
|
iconString.contains("dust") -> "Dust"
|
||||||
"wind_ovc" -> "04"
|
iconString.contains("smoke") -> "Smoke"
|
||||||
"snow" -> "13"
|
iconString.contains("haze") -> "50"
|
||||||
"rain_snow" -> "81"
|
iconString.contains("hot") -> "01"
|
||||||
"rain_sleet" -> "81"
|
iconString.contains("cold") -> "13"
|
||||||
"snow_sleet" -> "81"
|
iconString.contains("blizzard") -> "80"
|
||||||
"fzra" -> "81"
|
iconString.contains("fog") -> "82"
|
||||||
"rain_fzra" -> "81"
|
|
||||||
"snow_fzra" -> "81"
|
|
||||||
"sleet" -> "81"
|
|
||||||
"rain" -> "10"
|
|
||||||
"rain_showers" -> "10"
|
|
||||||
"rain_showers_hi" -> "10"
|
|
||||||
"tsra" -> "09"
|
|
||||||
"tsra_sct" -> "11"
|
|
||||||
"tsra_hi" -> "11"
|
|
||||||
"tornado" -> "80"
|
|
||||||
"hurricane" -> "80"
|
|
||||||
"tropical_storm" -> "09"
|
|
||||||
"dust" -> "50"
|
|
||||||
"smoke" -> "50"
|
|
||||||
"haze" -> "50"
|
|
||||||
"hot" -> "01"
|
|
||||||
"cold" -> "13"
|
|
||||||
"blizzard" -> "13"
|
|
||||||
"fog" -> "82"
|
|
||||||
else -> ""
|
else -> ""
|
||||||
} + if (isDaytime) "d" else "n"
|
} + if (isDaytime) "d" else "n"
|
||||||
|
|
||||||
fun getWeatherBitIcon(iconString: String): String = when (iconString.substring(0, 3)) {
|
fun getWeatherBitIcon(iconString: String): String = when {
|
||||||
"t01" -> "11"
|
iconString.contains("t01") -> "11"
|
||||||
"t02" -> "11"
|
iconString.contains("t02") -> "09"
|
||||||
"t03" -> "09"
|
iconString.contains("t03") -> "09"
|
||||||
"t04" -> "11"
|
iconString.contains("t04") -> "09"
|
||||||
"t05" -> "11"
|
iconString.contains("t05") -> "09"
|
||||||
"d01" -> "10"
|
iconString.contains("d01") -> "10"
|
||||||
"d02" -> "10"
|
iconString.contains("d02") -> "10"
|
||||||
"d03" -> "10"
|
iconString.contains("d03") -> "10"
|
||||||
"r01" -> "10"
|
iconString.contains("r01") -> "10"
|
||||||
"r02" -> "10"
|
iconString.contains("r02") -> "10"
|
||||||
"r03" -> "10"
|
iconString.contains("r03") -> "10"
|
||||||
"f01" -> "10"
|
iconString.contains("f01") -> "10"
|
||||||
"r04" -> "10"
|
iconString.contains("r04") -> "10"
|
||||||
"r05" -> "10"
|
iconString.contains("r05") -> "10"
|
||||||
"r06" -> "10"
|
iconString.contains("r06") -> "10"
|
||||||
"s01" -> "13"
|
iconString.contains("s01") -> "13"
|
||||||
"s02" -> "13"
|
iconString.contains("s02") -> "13"
|
||||||
"s03" -> "13"
|
iconString.contains("s03") -> "13"
|
||||||
"s04" -> "81"
|
iconString.contains("s04") -> "81"
|
||||||
"s05" -> "81"
|
iconString.contains("s05") -> "90"
|
||||||
"s06" -> "13"
|
iconString.contains("s06") -> "13"
|
||||||
"a01" -> "50"
|
iconString.contains("a01") -> "82"
|
||||||
"a02" -> "50"
|
iconString.contains("a02") -> "82"
|
||||||
"a03" -> "50"
|
iconString.contains("a03") -> "82"
|
||||||
"a04" -> "50"
|
iconString.contains("a04") -> "82"
|
||||||
"a05" -> "82"
|
iconString.contains("a05") -> "82"
|
||||||
"a06" -> "82"
|
iconString.contains("a06") -> "82"
|
||||||
"c01" -> "01"
|
iconString.contains("c01") -> "01"
|
||||||
"c02" -> "02"
|
iconString.contains("c02") -> "02"
|
||||||
"c03" -> "03"
|
iconString.contains("c03") -> "04"
|
||||||
"c04" -> "04"
|
iconString.contains("c04") -> "04"
|
||||||
else -> ""
|
else -> ""
|
||||||
} + iconString.substring(3)
|
} + if (iconString.contains("d")) "d" else "n"
|
||||||
|
|
||||||
fun getWeatherApiIcon(icon: Int, isDaytime: Boolean): String = when(icon) {
|
fun getWeatherApiIcon(icon: Int, isDaytime: Boolean): String = when(icon) {
|
||||||
1000 -> "01"
|
1000 -> "01"
|
||||||
1003 -> "02"
|
1003 -> "02"
|
||||||
1006 -> "03"
|
1006 -> "03"
|
||||||
1009 -> "04"
|
1009 -> "04"
|
||||||
1030 -> "50"
|
1030 -> "82"
|
||||||
1063 -> "10"
|
1063 -> "10"
|
||||||
1066 -> "13"
|
1066 -> "10"
|
||||||
1069 -> "81"
|
1069 -> "10"
|
||||||
1072 -> "81"
|
1072 -> "81"
|
||||||
1087 -> "11"
|
1087 -> "11"
|
||||||
1114 -> "13"
|
1114 -> "13"
|
||||||
1117 -> "13"
|
1117 -> "09"
|
||||||
1135 -> "82"
|
1135 -> "82"
|
||||||
1147 -> "82"
|
1147 -> "82"
|
||||||
1150 -> "10"
|
1150 -> "10"
|
||||||
@ -433,8 +421,8 @@ object WeatherHelper {
|
|||||||
1195 -> "10"
|
1195 -> "10"
|
||||||
1198 -> "81"
|
1198 -> "81"
|
||||||
1201 -> "81"
|
1201 -> "81"
|
||||||
1204 -> "81"
|
1204 -> "13"
|
||||||
1207 -> "81"
|
1207 -> "13"
|
||||||
1210 -> "13"
|
1210 -> "13"
|
||||||
1213 -> "13"
|
1213 -> "13"
|
||||||
1216 -> "13"
|
1216 -> "13"
|
||||||
@ -445,62 +433,62 @@ object WeatherHelper {
|
|||||||
1240 -> "10"
|
1240 -> "10"
|
||||||
1243 -> "10"
|
1243 -> "10"
|
||||||
1246 -> "10"
|
1246 -> "10"
|
||||||
1249 -> "81"
|
1249 -> "13"
|
||||||
1252 -> "81"
|
1252 -> "13"
|
||||||
1255 -> "13"
|
1255 -> "13"
|
||||||
1258 -> "13"
|
1258 -> "13"
|
||||||
1261 -> "13"
|
1261 -> "13"
|
||||||
1264 -> "13"
|
1264 -> "13"
|
||||||
1273 -> "11"
|
1273 -> "09"
|
||||||
1276 -> "09"
|
1276 -> "09"
|
||||||
1279 -> "13"
|
1279 -> "13"
|
||||||
1282 -> "13"
|
1282 -> "13"
|
||||||
else -> ""
|
else -> ""
|
||||||
} + if (isDaytime) "d" else "n"
|
} + if (isDaytime) "d" else "n"
|
||||||
|
|
||||||
fun getYRIcon(iconCode: String): String = when (iconCode.substringBefore('_')) {
|
fun getYRIcon(iconCode: String, isDaytime: Boolean): String = when {
|
||||||
"clearsky" -> "01"
|
iconCode.contains("clearsky") -> "01"
|
||||||
"cloudy" -> "04"
|
iconCode.contains("cloudy") -> "04"
|
||||||
"fair" -> "02"
|
iconCode.contains("fair") -> "02"
|
||||||
"fog" -> "82"
|
iconCode.contains("fog") -> "82"
|
||||||
"heavyrain" -> "10"
|
iconCode.contains("heavyrain") -> "10"
|
||||||
"heavyrainandthunder" -> "09"
|
iconCode.contains("heavyrainandthunder") -> "11"
|
||||||
"heavyrainshowers" -> "10"
|
iconCode.contains("heavyrainshowers") -> "10"
|
||||||
"heavyrainshowersandthunder" -> "09"
|
iconCode.contains("heavyrainshowersandthunder") -> "11"
|
||||||
"heavysleet" -> "81"
|
iconCode.contains("heavysleet") -> "10"
|
||||||
"heavysleetandthunder" -> "81"
|
iconCode.contains("heavysleetandthunder") -> "11"
|
||||||
"heavysleetshowers" -> "81"
|
iconCode.contains("heavysleetshowers") -> "10"
|
||||||
"heavysleetshowersandthunder" -> "81"
|
iconCode.contains("heavysleetshowersandthunder") -> "11"
|
||||||
"heavysnow" -> "13"
|
iconCode.contains("heavysnow") -> "13"
|
||||||
"heavysnowandthunder" -> "13"
|
iconCode.contains("heavysnowandthunder") -> "13"
|
||||||
"heavysnowshowers" -> "13"
|
iconCode.contains("heavysnowshowers") -> "13"
|
||||||
"heavysnowshowersandthunder" -> "13"
|
iconCode.contains("heavysnowshowersandthunder") -> "13"
|
||||||
"lightrain" -> "10"
|
iconCode.contains("lightrain") -> "10"
|
||||||
"lightrainandthunder" -> "11"
|
iconCode.contains("lightrainandthunder") -> "11"
|
||||||
"lightrainshowers" -> "10"
|
iconCode.contains("lightrainshowers") -> "10"
|
||||||
"lightrainshowersandthunder" -> "11"
|
iconCode.contains("lightrainshowersandthunder") -> "11"
|
||||||
"lightsleet" -> "81"
|
iconCode.contains("lightsleet") -> "10"
|
||||||
"lightsleetandthunder" -> "81"
|
iconCode.contains("lightsleetandthunder") -> "11"
|
||||||
"lightsleetshowers" -> "81"
|
iconCode.contains("lightsleetshowers") -> "10"
|
||||||
"lightsnow" -> "13"
|
iconCode.contains("lightsnow") -> "13"
|
||||||
"lightsnowandthunder" -> "13"
|
iconCode.contains("lightsnowandthunder") -> "13"
|
||||||
"lightsnowshowers" -> "13"
|
iconCode.contains("lightsnowshowers") -> "13"
|
||||||
"lightssleetshowersandthunder" -> "81"
|
iconCode.contains("lightssleetshowersandthunder") -> "81"
|
||||||
"lightssnowshowersandthunder" -> "81"
|
iconCode.contains("lightssnowshowersandthunder") -> "81"
|
||||||
"partlycloudy" -> "03"
|
iconCode.contains("partlycloudy") -> "03"
|
||||||
"rain" -> "10"
|
iconCode.contains("rain") -> "10"
|
||||||
"rainandthunder" -> "11"
|
iconCode.contains("rainandthunder") -> "11"
|
||||||
"rainshowers" -> "10"
|
iconCode.contains("rainshowers") -> "10"
|
||||||
"rainshowersandthunder" -> "11"
|
iconCode.contains("rainshowersandthunder") -> "11"
|
||||||
"sleet" -> "81"
|
iconCode.contains("sleet") -> "10"
|
||||||
"sleetandthunder" -> "81"
|
iconCode.contains("sleetandthunder") -> "11"
|
||||||
"sleetshowers" -> "81"
|
iconCode.contains("sleetshowers") -> "10"
|
||||||
"sleetshowersandthunder" -> "81"
|
iconCode.contains("sleetshowersandthunder") -> "11"
|
||||||
"snow" -> "13"
|
iconCode.contains("snow") -> "13"
|
||||||
"snowandthunder" -> "13"
|
iconCode.contains("snowandthunder") -> "13"
|
||||||
"snowshowers" -> "13"
|
iconCode.contains("snowshowers") -> "13"
|
||||||
"snowshowersandthunder" -> "13"
|
iconCode.contains("snowshowersandthunder") -> "13"
|
||||||
else -> ""
|
else -> ""
|
||||||
} + if (iconCode.substringAfter('_', "day") == "day") "d" else "n"
|
} + if (isDaytime) "d" else "n"
|
||||||
|
|
||||||
}
|
}
|
@ -6,10 +6,17 @@ import android.content.res.Configuration.ORIENTATION_PORTRAIT
|
|||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.HandlerThread
|
import android.os.HandlerThread
|
||||||
|
import android.os.Looper
|
||||||
|
import android.util.Log
|
||||||
import androidx.core.provider.FontRequest
|
import androidx.core.provider.FontRequest
|
||||||
import androidx.core.provider.FontsContractCompat
|
import androidx.core.provider.FontsContractCompat
|
||||||
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
object WidgetHelper {
|
object WidgetHelper {
|
||||||
class WidgetSizeProvider(
|
class WidgetSizeProvider(
|
||||||
@ -18,17 +25,12 @@ object WidgetHelper {
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
fun getWidgetsSize(widgetId: Int): Pair<Int, Int> {
|
fun getWidgetsSize(widgetId: Int): Pair<Int, Int> {
|
||||||
val portrait = context.resources.configuration.orientation == ORIENTATION_PORTRAIT
|
val width = getWidgetWidth(widgetId)
|
||||||
val width = getWidgetSizeInDp(
|
val height = getWidgetHeight(widgetId)
|
||||||
widgetId,
|
|
||||||
if (portrait) AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH else AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH
|
|
||||||
)
|
|
||||||
val height = getWidgetSizeInDp(
|
|
||||||
widgetId,
|
|
||||||
if (portrait) AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT else AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT
|
|
||||||
)
|
|
||||||
val widthInPx = context.dip(width)
|
val widthInPx = context.dip(width)
|
||||||
val heightInPx = context.dip(height)
|
val heightInPx = context.dip(height)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("widthInPx", widthInPx)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("heightInPx", heightInPx)
|
||||||
return widthInPx to heightInPx
|
return widthInPx to heightInPx
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,23 +63,21 @@ object WidgetHelper {
|
|||||||
R.array.com_google_android_gms_fonts_certs
|
R.array.com_google_android_gms_fonts_certs
|
||||||
)
|
)
|
||||||
|
|
||||||
val handlerThread = HandlerThread("generateView")
|
|
||||||
val callback = object : FontsContractCompat.FontRequestCallback() {
|
val callback = object : FontsContractCompat.FontRequestCallback() {
|
||||||
override fun onTypefaceRetrieved(typeface: Typeface) {
|
override fun onTypefaceRetrieved(typeface: Typeface) {
|
||||||
handlerThread.quit()
|
|
||||||
function.invoke(typeface)
|
function.invoke(typeface)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTypefaceRequestFailed(reason: Int) {
|
override fun onTypefaceRequestFailed(reason: Int) {
|
||||||
handlerThread.quit()
|
|
||||||
function.invoke(null)
|
function.invoke(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val handlerThread = HandlerThread("generateView")
|
||||||
handlerThread.start()
|
handlerThread.start()
|
||||||
//if (Looper.myLooper() == null) {
|
if (Looper.myLooper() == null) {
|
||||||
// Looper.prepare()
|
Looper.prepare()
|
||||||
//}
|
}
|
||||||
|
|
||||||
Handler(handlerThread.looper).run {
|
Handler(handlerThread.looper).run {
|
||||||
FontsContractCompat.requestFont(context, request, callback, this)
|
FontsContractCompat.requestFont(context, request, callback, this)
|
||||||
|
@ -1,35 +1,26 @@
|
|||||||
package com.tommasoberlose.anotherwidget.models
|
package com.tommasoberlose.anotherwidget.models
|
||||||
|
|
||||||
import android.provider.CalendarContract
|
import android.provider.CalendarContract
|
||||||
import androidx.room.ColumnInfo
|
import io.realm.RealmObject
|
||||||
import androidx.room.Entity
|
import java.util.Date
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by tommaso on 05/10/17.
|
* Created by tommaso on 05/10/17.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Entity(tableName = "events")
|
open class Event(
|
||||||
data class Event(
|
var id: Long = 0,
|
||||||
@PrimaryKey
|
var eventID: Long = 0,
|
||||||
val id: Long = 0,
|
var title: String = "",
|
||||||
@ColumnInfo(name = "event_id")
|
var startDate: Long = 0,
|
||||||
val eventID: Long = 0,
|
var endDate: Long = 0,
|
||||||
val title: String = "",
|
var calendarID: Int = 0,
|
||||||
@ColumnInfo(name = "start_date")
|
var allDay: Boolean = false,
|
||||||
val startDate: Long = 0,
|
var address: String = "",
|
||||||
@ColumnInfo(name = "end_date")
|
var selfAttendeeStatus: Int = CalendarContract.Attendees.ATTENDEE_STATUS_NONE,
|
||||||
val endDate: Long = 0,
|
var availability: Int = CalendarContract.EventsEntity.AVAILABILITY_BUSY
|
||||||
@ColumnInfo(name = "calendar_id")
|
) : RealmObject() {
|
||||||
val calendarID: Long = 0,
|
|
||||||
@ColumnInfo(name = "all_day")
|
|
||||||
val allDay: Boolean = false,
|
|
||||||
val address: String = "",
|
|
||||||
@ColumnInfo(name = "self_attendee_status")
|
|
||||||
val selfAttendeeStatus: Int = CalendarContract.Attendees.ATTENDEE_STATUS_NONE,
|
|
||||||
val availability: Int = CalendarContract.EventsEntity.AVAILABILITY_BUSY
|
|
||||||
)/* {
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "Event:\nEVENT ID: " + eventID + "\nTITLE: " + title + "\nSTART DATE: " + Date(startDate) + "\nEND DATE: " + Date(endDate) + "\nCAL ID: " + calendarID + "\nADDRESS: " + address
|
return "Event:\nEVENT ID: " + eventID + "\nTITLE: " + title + "\nSTART DATE: " + Date(startDate) + "\nEND DATE: " + Date(endDate) + "\nCAL ID: " + calendarID + "\nADDRESS: " + address
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.network
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.Log
|
|
||||||
import com.chibatching.kotpref.Kotpref
|
|
||||||
import com.google.gson.internal.LinkedTreeMap
|
|
||||||
import com.haroldadmin.cnradapter.NetworkResponse
|
|
||||||
import com.tommasoberlose.anotherwidget.R
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.network.repository.TimeZonesRepository
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
import java.lang.Exception
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class TimeZonesApi(val context: Context) {
|
|
||||||
suspend fun getTimeZone(lat: String, long: String): String? {
|
|
||||||
Kotpref.init(context)
|
|
||||||
val repository = TimeZonesRepository()
|
|
||||||
var id: String? = null
|
|
||||||
|
|
||||||
when (val response = repository.getTimeZone(lat, long)) {
|
|
||||||
is NetworkResponse.Success -> {
|
|
||||||
try {
|
|
||||||
id = response.body["timezoneId"] as String
|
|
||||||
} catch(ex: Exception) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,11 +17,13 @@ import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
|||||||
import com.tommasoberlose.anotherwidget.network.repository.*
|
import com.tommasoberlose.anotherwidget.network.repository.*
|
||||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import kotlin.coroutines.resume
|
import java.util.*
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
|
|
||||||
class WeatherNetworkApi(val context: Context) {
|
class WeatherNetworkApi(val context: Context) {
|
||||||
suspend fun updateWeather() {
|
suspend fun updateWeather() {
|
||||||
@ -29,7 +31,7 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
Preferences.weatherProviderError = "-"
|
Preferences.weatherProviderError = "-"
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
if (Preferences.customLocationLat != "" && Preferences.customLocationLon != "") {
|
if (Preferences.showWeather && Preferences.customLocationLat != "" && Preferences.customLocationLon != "") {
|
||||||
when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
|
when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
|
||||||
Constants.WeatherProvider.OPEN_WEATHER -> useOpenWeatherMap(context)
|
Constants.WeatherProvider.OPEN_WEATHER -> useOpenWeatherMap(context)
|
||||||
Constants.WeatherProvider.WEATHER_GOV -> useWeatherGov(context)
|
Constants.WeatherProvider.WEATHER_GOV -> useWeatherGov(context)
|
||||||
@ -40,67 +42,39 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
Constants.WeatherProvider.YR -> useYrProvider(context)
|
Constants.WeatherProvider.YR -> useYrProvider(context)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_missing_location)
|
|
||||||
Preferences.weatherProviderError = ""
|
|
||||||
|
|
||||||
WeatherHelper.removeWeather(
|
WeatherHelper.removeWeather(
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun useOpenWeatherMap(context: Context) {
|
private fun useOpenWeatherMap(context: Context) {
|
||||||
if (Preferences.weatherProviderApiOpen != "") {
|
if (Preferences.weatherProviderApiOpen != "") {
|
||||||
val helper = OpenWeatherMapHelper(Preferences.weatherProviderApiOpen)
|
val helper = OpenWeatherMapHelper(Preferences.weatherProviderApiOpen)
|
||||||
helper.setUnits(if (Preferences.weatherTempUnit == "F") Units.IMPERIAL else Units.METRIC)
|
helper.setUnits(if (Preferences.weatherTempUnit == "F") Units.IMPERIAL else Units.METRIC)
|
||||||
when (val response = suspendCancellableCoroutine<Any?> { continuation ->
|
helper.getCurrentWeatherByGeoCoordinates(Preferences.customLocationLat.toDouble(), Preferences.customLocationLon.toDouble(), object :
|
||||||
helper.getCurrentWeatherByGeoCoordinates(Preferences.customLocationLat.toDouble(), Preferences.customLocationLon.toDouble(), object :
|
CurrentWeatherCallback {
|
||||||
CurrentWeatherCallback {
|
override fun onSuccess(currentWeather: CurrentWeather?) {
|
||||||
override fun onSuccess(currentWeather: CurrentWeather?) {
|
currentWeather?.let {
|
||||||
continuation.resume(currentWeather)
|
Preferences.weatherTemp = currentWeather.main.temp.toFloat()
|
||||||
|
Preferences.weatherIcon = currentWeather.weather[0].icon
|
||||||
|
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(throwable: Throwable?) {
|
|
||||||
continuation.resume(throwable)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}) {
|
|
||||||
is CurrentWeather -> {
|
|
||||||
Preferences.weatherTemp = response.main.temp.toFloat()
|
|
||||||
Preferences.weatherIcon = response.weather[0].icon
|
|
||||||
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
|
||||||
MainWidget.updateWidget(context)
|
|
||||||
|
|
||||||
Preferences.weatherProviderError = ""
|
Preferences.weatherProviderError = ""
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
}
|
}
|
||||||
is Throwable -> {
|
|
||||||
if (response.javaClass == Throwable::class.java) {
|
override fun onFailure(throwable: Throwable?) {
|
||||||
// server error, see [OpenWeatherMapHelper.handleCurrentWeatherResponse]
|
|
||||||
if (response.message?.startsWith("UnAuthorized") == true) {
|
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_invalid_key)
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
}
|
|
||||||
WeatherHelper.removeWeather(
|
|
||||||
context
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_connection)
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
|
||||||
} else {
|
} else {
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
@ -140,34 +114,25 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
val props =
|
val props =
|
||||||
weatherResponse.body["properties"] as LinkedTreeMap<*, *>
|
weatherResponse.body["properties"] as LinkedTreeMap<*, *>
|
||||||
val periods = props["periods"] as List<*>
|
val periods = props["periods"] as List<*>
|
||||||
@android.annotation.SuppressLint("SimpleDateFormat")
|
val now = periods[0] as LinkedTreeMap<*, *>
|
||||||
val format = SimpleDateFormat(
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N)
|
|
||||||
"yyyy-MM-dd'T'HH:mm:ssXXX"
|
|
||||||
else
|
|
||||||
"yyyy-MM-dd'T'HH:mm:ssZ"
|
|
||||||
)
|
|
||||||
for (period in periods) {
|
|
||||||
val now = period as LinkedTreeMap<*, *>
|
|
||||||
val endTime = format.parse(now["endTime"] as String)!!
|
|
||||||
if (endTime.time > System.currentTimeMillis()) {
|
|
||||||
val temp = now["temperature"] as Double
|
|
||||||
val fullIcon = now["icon"] as String
|
|
||||||
val isDaytime = now["isDaytime"] as Boolean
|
|
||||||
|
|
||||||
Preferences.weatherTemp = temp.toFloat()
|
val temp = now["temperature"] as Double
|
||||||
Preferences.weatherIcon = WeatherHelper.getWeatherGovIcon(fullIcon, isDaytime)
|
val fullIcon = now["icon"] as String
|
||||||
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
val isDaytime = now["isDaytime"] as Boolean
|
||||||
MainWidget.updateWidget(context)
|
|
||||||
|
|
||||||
Preferences.weatherProviderError = ""
|
Preferences.weatherTemp = temp.toFloat()
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherIcon = WeatherHelper.getWeatherGovIcon(fullIcon, isDaytime)
|
||||||
break
|
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||||
}
|
|
||||||
}
|
Preferences.weatherProviderError = ""
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
} finally {
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
@ -183,16 +148,14 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is NetworkResponse.ServerError -> {
|
is NetworkResponse.ServerError -> {
|
||||||
when (pointsResponse.code) {
|
if (pointsResponse.body?.containsKey("status") == true && (pointsResponse.body?.get("status") as Double).toInt() == 404) {
|
||||||
404 -> {
|
Preferences.weatherProviderError = ""
|
||||||
Preferences.weatherProviderError = ""
|
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_wrong_location)
|
||||||
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_wrong_location)
|
} else {
|
||||||
}
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
||||||
else -> {
|
Preferences.weatherProviderLocationError = ""
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WeatherHelper.removeWeather(
|
WeatherHelper.removeWeather(
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
@ -213,18 +176,7 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
when (val response = repository.getWeather()) {
|
when (val response = repository.getWeather()) {
|
||||||
is NetworkResponse.Success -> {
|
is NetworkResponse.Success -> {
|
||||||
try {
|
try {
|
||||||
val observations = response.body["observations"] as LinkedTreeMap<*, *>
|
Log.d("ciao - here", response.body.toString())
|
||||||
val location = (observations["location"] as List<*>).first() as LinkedTreeMap<*, *>
|
|
||||||
val observation = (location["observation"] as List<*>).first() as LinkedTreeMap<*, *>
|
|
||||||
val iconName = observation["iconName"] as String
|
|
||||||
val daylight = observation["daylight"] as String
|
|
||||||
val temperature = observation["temperature"] as String
|
|
||||||
|
|
||||||
Preferences.weatherTemp = temperature.toFloat()
|
|
||||||
Preferences.weatherIcon = repository.getWeatherIcon(iconName, daylight != "N")
|
|
||||||
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
|
||||||
MainWidget.updateWidget(context)
|
|
||||||
|
|
||||||
Preferences.weatherProviderError = ""
|
Preferences.weatherProviderError = ""
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
} catch(ex: Exception) {
|
} catch(ex: Exception) {
|
||||||
@ -235,16 +187,8 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is NetworkResponse.ServerError -> {
|
is NetworkResponse.ServerError -> {
|
||||||
when (response.code) {
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
||||||
401 -> {
|
Preferences.weatherProviderLocationError = ""
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_invalid_key)
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WeatherHelper.removeWeather(
|
WeatherHelper.removeWeather(
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
@ -274,10 +218,10 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
when (val response = repository.getWeather()) {
|
when (val response = repository.getWeather()) {
|
||||||
is NetworkResponse.Success -> {
|
is NetworkResponse.Success -> {
|
||||||
try {
|
try {
|
||||||
val data = response.body["data"] as List<*>?
|
val data = response.body["data"] as List<LinkedTreeMap<String, Any>>?
|
||||||
data?.first()?.let { it as LinkedTreeMap<*, *>
|
data?.first()?.let {
|
||||||
val temp = it["temp"] as Double
|
val temp = it["temp"] as Double
|
||||||
val weatherInfo = it["weather"] as LinkedTreeMap<*, *>
|
val weatherInfo = it["weather"] as LinkedTreeMap<String, Any>
|
||||||
val iconCode = weatherInfo["icon"] as String
|
val iconCode = weatherInfo["icon"] as String
|
||||||
|
|
||||||
Preferences.weatherTemp = temp.toFloat()
|
Preferences.weatherTemp = temp.toFloat()
|
||||||
@ -287,6 +231,8 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
|
|
||||||
Preferences.weatherProviderError = ""
|
Preferences.weatherProviderError = ""
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
}
|
}
|
||||||
} catch(ex: Exception) {
|
} catch(ex: Exception) {
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
||||||
@ -335,12 +281,12 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
when (val response = repository.getWeather()) {
|
when (val response = repository.getWeather()) {
|
||||||
is NetworkResponse.Success -> {
|
is NetworkResponse.Success -> {
|
||||||
try {
|
try {
|
||||||
val current = response.body["current"] as LinkedTreeMap<*, *>?
|
val current = response.body["current"] as LinkedTreeMap<String, Any>?
|
||||||
current?.let {
|
current?.let {
|
||||||
val tempC = current["temp_c"] as Double
|
val tempC = current["temp_c"] as Double
|
||||||
val tempF = current["temp_f"] as Double
|
val tempF = current["temp_f"] as Double
|
||||||
val isDay = current["is_day"] as Double
|
val isDay = current["is_day"] as Double
|
||||||
val condition = current["condition"] as LinkedTreeMap<*, *>
|
val condition = current["condition"] as LinkedTreeMap<String, Any>
|
||||||
val iconCode = condition["code"] as Double
|
val iconCode = condition["code"] as Double
|
||||||
|
|
||||||
Preferences.weatherTemp = if (Preferences.weatherTempUnit == "F") tempF.toFloat() else tempC.toFloat()
|
Preferences.weatherTemp = if (Preferences.weatherTempUnit == "F") tempF.toFloat() else tempC.toFloat()
|
||||||
@ -350,6 +296,8 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
|
|
||||||
Preferences.weatherProviderError = ""
|
Preferences.weatherProviderError = ""
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
}
|
}
|
||||||
} catch(ex: Exception) {
|
} catch(ex: Exception) {
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
||||||
@ -398,74 +346,28 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
|
|
||||||
private suspend fun useAccuweatherProvider(context: Context) {
|
private suspend fun useAccuweatherProvider(context: Context) {
|
||||||
if (Preferences.weatherProviderApiAccuweather != "") {
|
if (Preferences.weatherProviderApiAccuweather != "") {
|
||||||
val repository = AccuweatherRepository()
|
// val repository = AccuweatherRepository()
|
||||||
|
|
||||||
when (val locationResponse = repository.getLocation()) {
|
// when (val response = repository.getWeather()) {
|
||||||
is NetworkResponse.Success -> {
|
// is NetworkResponse.Success -> {
|
||||||
try {
|
// try {
|
||||||
val key = locationResponse.body["Key"] as String
|
// Log.d("ciao", response.body.toString())
|
||||||
|
// } catch(ex: Exception) {
|
||||||
|
//
|
||||||
|
// Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
|
||||||
|
// Preferences.weatherProviderLocationError = ""
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// is NetworkResponse.ServerError -> {
|
||||||
|
// WeatherHelper.removeWeather(
|
||||||
|
// context
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
|
||||||
|
// Preferences.weatherProviderLocationError = ""
|
||||||
|
// EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
// }
|
||||||
|
|
||||||
when (val weatherResponse = repository.getWeather(key)) {
|
|
||||||
is NetworkResponse.Success -> {
|
|
||||||
try {
|
|
||||||
weatherResponse.body.first().let {
|
|
||||||
val temp = it["Temperature"] as LinkedTreeMap<*, *>
|
|
||||||
val tempC = (temp["Metric"] as LinkedTreeMap<*, *>)["Value"] as Double
|
|
||||||
val tempF = (temp["Imperial"] as LinkedTreeMap<*, *>)["Value"] as Double
|
|
||||||
val isDay = it["IsDayTime"] as Boolean
|
|
||||||
val icon = it["WeatherIcon"] as Double
|
|
||||||
|
|
||||||
Preferences.weatherTemp = if (Preferences.weatherTempUnit == "F") tempF.toFloat() else tempC.toFloat()
|
|
||||||
Preferences.weatherIcon = repository.getWeatherIcon(icon.toInt(), isDay)
|
|
||||||
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
|
||||||
MainWidget.updateWidget(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
Preferences.weatherProviderError = ""
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_connection)
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(ex: Exception) {
|
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
} finally {
|
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is NetworkResponse.ServerError -> {
|
|
||||||
when (locationResponse.code) {
|
|
||||||
401 -> {
|
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_invalid_key)
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
}
|
|
||||||
503 -> {
|
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_expired_key)
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WeatherHelper.removeWeather(
|
|
||||||
context
|
|
||||||
)
|
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_connection)
|
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
@ -484,27 +386,38 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
is NetworkResponse.Success -> {
|
is NetworkResponse.Success -> {
|
||||||
try {
|
try {
|
||||||
val pp = response.body["properties"] as LinkedTreeMap<*, *>
|
val pp = response.body["properties"] as LinkedTreeMap<*, *>
|
||||||
val data = pp["timeseries"] as List<*>?
|
val data = pp["timeseries"] as List<LinkedTreeMap<String, Any>>?
|
||||||
data?.first()?.let { it as LinkedTreeMap<*, *>
|
data?.let {
|
||||||
val dd = it["data"] as LinkedTreeMap<*, *>
|
val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
|
||||||
val instant = dd["instant"] as LinkedTreeMap<*, *>
|
for (item in data) {
|
||||||
val next = dd["next_1_hours"] as LinkedTreeMap<*, *>
|
val time = Calendar.getInstance().apply { time = format.parse(item["time"] as String)!! }
|
||||||
|
val now = Calendar.getInstance()
|
||||||
|
if (time.timeInMillis >= now.timeInMillis) {
|
||||||
|
val dd = item["data"] as LinkedTreeMap<*, *>
|
||||||
|
val instant = dd["instant"] as LinkedTreeMap<*, *>
|
||||||
|
val next = dd["next_1_hours"] as LinkedTreeMap<*, *>
|
||||||
|
|
||||||
val details = instant["details"] as LinkedTreeMap<*, *>
|
val details = instant["details"] as LinkedTreeMap<*, *>
|
||||||
val temp = details["air_temperature"] as Double
|
val temp = details["air_temperature"] as Double
|
||||||
|
|
||||||
val summary = next["summary"] as LinkedTreeMap<*, *>
|
val summary = next["summary"] as LinkedTreeMap<*, *>
|
||||||
val iconCode = summary["symbol_code"] as String
|
val iconCode = summary["symbol_code"] as String
|
||||||
|
|
||||||
Preferences.weatherTemp = temp.toFloat()
|
Preferences.weatherTemp = temp.toFloat()
|
||||||
Preferences.weatherIcon = WeatherHelper.getYRIcon(iconCode)
|
Preferences.weatherIcon = WeatherHelper.getYRIcon(iconCode, now.get(Calendar.HOUR_OF_DAY) >= 22 || now.get(Calendar.HOUR_OF_DAY) <= 8)
|
||||||
Preferences.weatherTempUnit = "C"
|
Preferences.weatherTempUnit = "C"
|
||||||
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
|
|
||||||
Preferences.weatherProviderError = ""
|
Preferences.weatherProviderError = ""
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} catch(ex: Exception) {
|
} catch(ex: Exception) {
|
||||||
ex.printStackTrace()
|
ex.printStackTrace()
|
||||||
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
||||||
@ -528,4 +441,4 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,7 +13,7 @@ object ApiServices {
|
|||||||
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
||||||
|
|
||||||
@Headers("User-Agent: (Another Widget, tommaso.berlose@gmail.com)")
|
@Headers("User-Agent: (Another Widget, tommaso.berlose@gmail.com)")
|
||||||
@GET("gridpoints/{gridId}/{gridX},{gridY}/forecast/hourly")
|
@GET("gridpoints/{gridId}/{gridX},{gridY}/forecast")
|
||||||
suspend fun getWeather(
|
suspend fun getWeather(
|
||||||
@Path("gridId") gridId: String,
|
@Path("gridId") gridId: String,
|
||||||
@Path("gridX") gridX: Int,
|
@Path("gridX") gridX: Int,
|
||||||
@ -54,17 +54,13 @@ object ApiServices {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface AccuweatherService {
|
interface AccuweatherService {
|
||||||
@GET("locations/v1/cities/geoposition/search")
|
@GET("")
|
||||||
suspend fun getLocation(
|
|
||||||
@Query("apikey") apikey: String,
|
|
||||||
@Query("q") location: String
|
|
||||||
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
|
||||||
|
|
||||||
@GET("currentconditions/v1/{locationKey}")
|
|
||||||
suspend fun getWeather(
|
suspend fun getWeather(
|
||||||
@Path("locationKey") locationKey: String,
|
@Path("gridId") gridId: String,
|
||||||
@Query("apikey") apikey: String
|
@Path("gridX") gridX: Int,
|
||||||
): NetworkResponse<List<HashMap<String, Any>>, HashMap<String, Any>>
|
@Path("gridY") gridY: Int,
|
||||||
|
@Query("units") unit: String
|
||||||
|
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface YrService {
|
interface YrService {
|
||||||
@ -75,13 +71,4 @@ object ApiServices {
|
|||||||
@Query("lon") lon: String,
|
@Query("lon") lon: String,
|
||||||
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
||||||
}
|
}
|
||||||
|
}
|
||||||
interface TimeZonesService {
|
|
||||||
@GET("timezoneJSON")
|
|
||||||
suspend fun getTimeZone(
|
|
||||||
@Query("lat") lat: String,
|
|
||||||
@Query("lng") lon: String,
|
|
||||||
@Query("username") username: String = "tommaso.berlose",
|
|
||||||
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
package com.tommasoberlose.anotherwidget.network.repository
|
package com.tommasoberlose.anotherwidget.network.repository
|
||||||
|
|
||||||
import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory
|
import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
import com.tommasoberlose.anotherwidget.network.api.ApiServices
|
import com.tommasoberlose.anotherwidget.network.api.ApiServices
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
@ -10,11 +9,10 @@ class AccuweatherRepository {
|
|||||||
|
|
||||||
/* ACCUWEATHER */
|
/* ACCUWEATHER */
|
||||||
private val apiServiceAccu: ApiServices.AccuweatherService = getRetrofit().create(ApiServices.AccuweatherService::class.java)
|
private val apiServiceAccu: ApiServices.AccuweatherService = getRetrofit().create(ApiServices.AccuweatherService::class.java)
|
||||||
suspend fun getLocation() = apiServiceAccu.getLocation(Preferences.weatherProviderApiAccuweather, "${Preferences.customLocationLat},${Preferences.customLocationLon}")
|
suspend fun getWeather(): Nothing = TODO()
|
||||||
suspend fun getWeather(locationKey: String) = apiServiceAccu.getWeather(locationKey, Preferences.weatherProviderApiAccuweather)
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val BASE_URL_ACCU = "https://dataservice.accuweather.com/"
|
private const val BASE_URL_ACCU = ""
|
||||||
|
|
||||||
private fun getRetrofit(): Retrofit {
|
private fun getRetrofit(): Retrofit {
|
||||||
return Retrofit.Builder()
|
return Retrofit.Builder()
|
||||||
@ -24,20 +22,4 @@ class AccuweatherRepository {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fun getWeatherIcon(icon: Int, isDaytime: Boolean): String = when(icon) {
|
|
||||||
1, 2, 30, 33, 34 -> "01"
|
|
||||||
3, 4, 35, 36 -> "02"
|
|
||||||
5, 37 -> "50"
|
|
||||||
6, 38 -> "03"
|
|
||||||
7, 8 -> "04"
|
|
||||||
11 -> "82"
|
|
||||||
12, 13, 14, 18, 39, 40 -> "10"
|
|
||||||
15 -> "09"
|
|
||||||
16, 17, 41, 42 -> "11"
|
|
||||||
32 -> "80"
|
|
||||||
19, 20, 21, 22, 23, 24, 31, 43, 44 -> "13"
|
|
||||||
25, 26, 29 -> "81"
|
|
||||||
else -> ""
|
|
||||||
} + if (isDaytime) "d" else "n"
|
|
||||||
}
|
|
@ -23,157 +23,4 @@ class HereRepository {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fun getWeatherIcon(iconName: String, isDaytime: Boolean): String = when(iconName.substringAfter("night_")) {
|
|
||||||
"sunny" -> "01"
|
|
||||||
"clear" -> "01"
|
|
||||||
"mostly_sunny" -> "01"
|
|
||||||
"mostly_clear" -> "01"
|
|
||||||
"passing_clounds" -> "02"
|
|
||||||
"more_sun_than_clouds" -> "02"
|
|
||||||
"scattered_clouds" -> "02"
|
|
||||||
"partly_cloudy" -> "02"
|
|
||||||
"a_mixture_of_sun_and_clouds" -> "03"
|
|
||||||
"increasing_cloudiness" -> "03"
|
|
||||||
"breaks_of_sun_late" -> "03"
|
|
||||||
"afternoon_clouds" -> "03"
|
|
||||||
"morning_clouds" -> "03"
|
|
||||||
"partly_sunny" -> "03"
|
|
||||||
"high_level_clouds" -> "03"
|
|
||||||
"decreasing_cloudiness" -> "03"
|
|
||||||
"clearing_skies" -> "01"
|
|
||||||
"high_clouds" -> "03"
|
|
||||||
"rain_early" -> "10"
|
|
||||||
"heavy_rain_early" -> "10"
|
|
||||||
"strong_thunderstorms" -> "09"
|
|
||||||
"severe_thunderstorms" -> "09"
|
|
||||||
"thundershowers" -> "11"
|
|
||||||
"thunderstorms" -> "11"
|
|
||||||
"tstorms_early" -> "11"
|
|
||||||
"isolated_tstorms_late" -> "11"
|
|
||||||
"scattered_tstorms_late" -> "11"
|
|
||||||
"tstorms_late" -> "11"
|
|
||||||
"tstorms" -> "11"
|
|
||||||
"ice_fog" -> "82"
|
|
||||||
"more_clouds_than_sun" -> "03"
|
|
||||||
"broken_clouds" -> "03"
|
|
||||||
"scattered_showers" -> "10"
|
|
||||||
"a_few_showers" -> "10"
|
|
||||||
"light_showers" -> "10"
|
|
||||||
"passing_showers" -> "10"
|
|
||||||
"rain_showers" -> "10"
|
|
||||||
"showers" -> "10"
|
|
||||||
"widely_scattered_tstorms" -> "11"
|
|
||||||
"isolated_tstorms" -> "11"
|
|
||||||
"a_few_tstorms" -> "11"
|
|
||||||
"scattered_tstorms" -> "11"
|
|
||||||
"hazy_sunshine" -> "50"
|
|
||||||
"haze" -> "50"
|
|
||||||
"smoke" -> "50"
|
|
||||||
"low_level_haze" -> "50"
|
|
||||||
"early_fog_followed_by_sunny_skies" -> "50"
|
|
||||||
"early_fog" -> "82"
|
|
||||||
"light_fog" -> "82"
|
|
||||||
"fog" -> "82"
|
|
||||||
"dense_fog" -> "82"
|
|
||||||
//"night_haze"
|
|
||||||
//"night_smoke"
|
|
||||||
//"night_low_level_haze"
|
|
||||||
//"night_widely_scattered_tstorms"
|
|
||||||
//"night_isolated_tstorms"
|
|
||||||
//"night_a_few_tstorms"
|
|
||||||
//"night_scattered_tstorms"
|
|
||||||
//"night_tstorms"
|
|
||||||
//"night_clear"
|
|
||||||
"mostly_cloudy" -> "03"
|
|
||||||
"cloudy" -> "04"
|
|
||||||
"overcast" -> "04"
|
|
||||||
"low_clouds" -> "03"
|
|
||||||
"hail" -> "10"
|
|
||||||
"sleet" -> "81"
|
|
||||||
"light_mixture_of_precip" -> "81"
|
|
||||||
"icy_mix" -> "81"
|
|
||||||
"mixture_of_precip" -> "81"
|
|
||||||
"heavy_mixture_of_precip" -> "81"
|
|
||||||
"snow_changing_to_rain" -> "81"
|
|
||||||
"snow_changing_to_an_icy_mix" -> "81"
|
|
||||||
"an_icy_mix_changing_to_snow" -> "81"
|
|
||||||
"an_icy_mix_changing_to_rain" -> "81"
|
|
||||||
"rain_changing_to_snow" -> "81"
|
|
||||||
"rain_changing_to_an_icy_mix" -> "81"
|
|
||||||
"light_icy_mix_early" -> "81"
|
|
||||||
"icy_mix_early" -> "81"
|
|
||||||
"light_icy_mix_late" -> "81"
|
|
||||||
"icy_mix_late" -> "81"
|
|
||||||
"snow_rain_mix" -> "81"
|
|
||||||
"scattered_flurries" -> "13"
|
|
||||||
"snow_flurries" -> "13"
|
|
||||||
"light_snow_showers" -> "13"
|
|
||||||
"snow_showers" -> "13"
|
|
||||||
"light_snow" -> "13"
|
|
||||||
"flurries_early" -> "13"
|
|
||||||
"snow_showers_early" -> "13"
|
|
||||||
"light_snow_early" -> "13"
|
|
||||||
"flurries_late" -> "13"
|
|
||||||
"snow_showers_late" -> "13"
|
|
||||||
"light_snow_late" -> "13"
|
|
||||||
//"night_decreasing_cloudiness"
|
|
||||||
//"night_clearing_skies"
|
|
||||||
//"night_high_level_clouds"
|
|
||||||
//"night_high_clouds"
|
|
||||||
//"night_scattered_showers"
|
|
||||||
//"night_a_few_showers"
|
|
||||||
//"night_light_showers"
|
|
||||||
//"night_passing_showers"
|
|
||||||
//"night_rain_showers"
|
|
||||||
//"night_sprinkles"
|
|
||||||
//"night_showers"
|
|
||||||
//"night_mostly_clear"
|
|
||||||
//"night_passing_clouds"
|
|
||||||
//"night_scattered_clouds"
|
|
||||||
//"night_partly_cloudy"
|
|
||||||
//"increasing_cloudiness"
|
|
||||||
//"night_afternoon_clouds"
|
|
||||||
//"night_morning_clouds"
|
|
||||||
//"night_broken_clouds"
|
|
||||||
//"night_mostly_cloudy"
|
|
||||||
"light_freezing_rain" -> "81"
|
|
||||||
"freezing_rain" -> "81"
|
|
||||||
"heavy_rain" -> "10"
|
|
||||||
"lots_of_rain" -> "10"
|
|
||||||
"tons_of_rain" -> "10"
|
|
||||||
//"heavy_rain_early" -> "10"
|
|
||||||
"heavy_rain_late" -> "10"
|
|
||||||
"flash_floods" -> "10"
|
|
||||||
"flood" -> "10"
|
|
||||||
"drizzle" -> "10"
|
|
||||||
"sprinkles" -> "10"
|
|
||||||
"light_rain" -> "10"
|
|
||||||
"sprinkles_early" -> "10"
|
|
||||||
"light_rain_early" -> "10"
|
|
||||||
"sprinkles_late" -> "10"
|
|
||||||
"light_rain_late" -> "10"
|
|
||||||
"rain" -> "10"
|
|
||||||
"numerous_showers" -> "10"
|
|
||||||
"showery" -> "10"
|
|
||||||
"showers_early" -> "10"
|
|
||||||
//"rain_early" -> "10"
|
|
||||||
"showers_late" -> "10"
|
|
||||||
"rain_late" -> "10"
|
|
||||||
"snow" -> "13"
|
|
||||||
"moderate_snow" -> "13"
|
|
||||||
"snow_early" -> "13"
|
|
||||||
"snow_late" -> "13"
|
|
||||||
"heavy_snow" -> "13"
|
|
||||||
"heavy_snow_early" -> "13"
|
|
||||||
"heavy_snow_late" -> "13"
|
|
||||||
"tornado" -> "80"
|
|
||||||
"tropical_storm" -> "09"
|
|
||||||
"hurricane" -> "80"
|
|
||||||
"sandstorm" -> "50"
|
|
||||||
"duststorm" -> "50"
|
|
||||||
"snowstorm" -> "13"
|
|
||||||
"blizzard" -> "13"
|
|
||||||
else -> ""
|
|
||||||
} + if (isDaytime) "d" else "n"
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.network.repository
|
|
||||||
|
|
||||||
import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory
|
|
||||||
import com.tommasoberlose.anotherwidget.network.api.ApiServices
|
|
||||||
import retrofit2.Retrofit
|
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
|
||||||
|
|
||||||
class TimeZonesRepository {
|
|
||||||
|
|
||||||
/* YR */
|
|
||||||
private val apiService: ApiServices.TimeZonesService = getRetrofit().create(ApiServices.TimeZonesService::class.java)
|
|
||||||
suspend fun getTimeZone(lat: String, long: String) = apiService.getTimeZone(lat, long)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val BASE_URL_YR = "http://api.geonames.org/"
|
|
||||||
|
|
||||||
private fun getRetrofit(): Retrofit {
|
|
||||||
return Retrofit.Builder()
|
|
||||||
.baseUrl(BASE_URL_YR)
|
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
|
||||||
.addCallAdapterFactory(NetworkResponseAdapterFactory())
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,181 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.receivers
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.AlarmManager
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.Log
|
||||||
|
import com.chibatching.kotpref.Kotpref
|
||||||
|
import com.chibatching.kotpref.blockingBulk
|
||||||
|
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
||||||
|
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
||||||
|
import com.google.android.gms.fitness.Fitness
|
||||||
|
import com.google.android.gms.fitness.FitnessOptions
|
||||||
|
import com.google.android.gms.fitness.data.DataType
|
||||||
|
import com.google.android.gms.fitness.data.Field.FIELD_STEPS
|
||||||
|
import com.google.android.gms.fitness.request.DataReadRequest
|
||||||
|
import com.google.android.gms.location.*
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
|
||||||
|
class ActivityDetectionReceiver : BroadcastReceiver() {
|
||||||
|
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
if (ActivityTransitionResult.hasResult(intent)) {
|
||||||
|
val result = ActivityTransitionResult.extractResult(intent)!!
|
||||||
|
val lastEvent = result.transitionEvents.last()
|
||||||
|
|
||||||
|
if (lastEvent.activityType == DetectedActivity.WALKING || lastEvent.activityType == DetectedActivity.RUNNING && lastEvent.transitionType == ActivityTransition.ACTIVITY_TRANSITION_EXIT) {
|
||||||
|
requestDailySteps(context)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (intent.action == Intent.ACTION_BOOT_COMPLETED || intent.action == Intent.ACTION_MY_PACKAGE_REPLACED && Preferences.showDailySteps && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || context.checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION)) {
|
||||||
|
resetDailySteps(context)
|
||||||
|
registerFence(context)
|
||||||
|
} else {
|
||||||
|
resetDailySteps(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resetDailySteps(context: Context) {
|
||||||
|
Kotpref.init(context)
|
||||||
|
Preferences.blockingBulk {
|
||||||
|
remove(Preferences::googleFitSteps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val FITNESS_OPTIONS: FitnessOptions = FitnessOptions.builder()
|
||||||
|
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
|
||||||
|
.addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
fun registerFence(context: Context) {
|
||||||
|
Kotpref.init(context)
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || context.checkGrantedPermission(
|
||||||
|
Manifest.permission.ACTIVITY_RECOGNITION)) {
|
||||||
|
val transitions = mutableListOf<ActivityTransition>()
|
||||||
|
|
||||||
|
transitions +=
|
||||||
|
ActivityTransition.Builder()
|
||||||
|
.setActivityType(DetectedActivity.WALKING)
|
||||||
|
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
transitions +=
|
||||||
|
ActivityTransition.Builder()
|
||||||
|
.setActivityType(DetectedActivity.RUNNING)
|
||||||
|
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val request = ActivityTransitionRequest(transitions)
|
||||||
|
|
||||||
|
// myPendingIntent is the instance of PendingIntent where the app receives callbacks.
|
||||||
|
val task = ActivityRecognition.getClient(context)
|
||||||
|
.requestActivityTransitionUpdates(
|
||||||
|
request,
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
2,
|
||||||
|
Intent(context, ActivityDetectionReceiver::class.java),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
task.addOnFailureListener { e: Exception ->
|
||||||
|
e.printStackTrace()
|
||||||
|
Preferences.showDailySteps = false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unregisterFence(context: Context) {
|
||||||
|
val task = ActivityRecognition.getClient(context)
|
||||||
|
.removeActivityTransitionUpdates(
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
2,
|
||||||
|
Intent(context, ActivityDetectionReceiver::class.java),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
task.addOnCompleteListener {
|
||||||
|
if (it.isSuccessful) {
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
2,
|
||||||
|
Intent(context, ActivityDetectionReceiver::class.java),
|
||||||
|
0
|
||||||
|
).cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestDailySteps(context: Context) {
|
||||||
|
Kotpref.init(context)
|
||||||
|
|
||||||
|
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
|
||||||
|
if (account != null && GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
|
||||||
|
|
||||||
|
val cal: Calendar = Calendar.getInstance()
|
||||||
|
cal.set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
cal.set(Calendar.MINUTE, 0)
|
||||||
|
cal.set(Calendar.SECOND, 0)
|
||||||
|
cal.set(Calendar.MILLISECOND, 0)
|
||||||
|
val startTime: Long = cal.timeInMillis
|
||||||
|
|
||||||
|
cal.add(Calendar.DAY_OF_YEAR, 1)
|
||||||
|
val endTime: Long = cal.timeInMillis
|
||||||
|
|
||||||
|
val readRequest = DataReadRequest.Builder()
|
||||||
|
.aggregate(DataType.TYPE_STEP_COUNT_DELTA)
|
||||||
|
.aggregate(DataType.AGGREGATE_STEP_COUNT_DELTA)
|
||||||
|
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
|
||||||
|
.bucketByTime(1, TimeUnit.DAYS)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
Fitness.getHistoryClient(context, account)
|
||||||
|
.readData(readRequest)
|
||||||
|
.addOnSuccessListener { response ->
|
||||||
|
Preferences.googleFitSteps = response.buckets.sumBy {
|
||||||
|
try {
|
||||||
|
it.getDataSet(DataType.AGGREGATE_STEP_COUNT_DELTA)?.dataPoints?.get(
|
||||||
|
0
|
||||||
|
)?.getValue(FIELD_STEPS)?.asInt() ?: 0
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}.toLong()
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
setTimeout(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setTimeout(context: Context) {
|
||||||
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
|
cancel(PendingIntent.getBroadcast(context, 5, Intent(context, ActivityDetectionReceiver::class.java), 0))
|
||||||
|
setExact(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
Calendar.getInstance().timeInMillis + 5 * 60 * 1000,
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
5,
|
||||||
|
Intent(context, ActivityDetectionReceiver::class.java),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.receivers
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.util.Log
|
||||||
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Actions
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
|
class CrashlyticsReceiver : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
if (intent.action == Actions.ACTION_REPORT_CRASH) {
|
||||||
|
val exception: Exception = intent.getSerializableExtra(EXCEPTION) as Exception
|
||||||
|
FirebaseCrashlytics.getInstance().recordException(exception)
|
||||||
|
FirebaseCrashlytics.getInstance().sendUnsentReports()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val EXCEPTION = "EXCEPTION"
|
||||||
|
|
||||||
|
fun sendCrash(context: Context, exception: Exception) {
|
||||||
|
context.sendBroadcast(Intent(context, CrashlyticsReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_REPORT_CRASH
|
||||||
|
putExtra(EXCEPTION, exception)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -13,7 +13,8 @@ class NewCalendarEventReceiver : BroadcastReceiver() {
|
|||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
val eventRepository = EventRepository(context)
|
val eventRepository = EventRepository(context)
|
||||||
when (intent.action) {
|
when (intent.action) {
|
||||||
Intent.ACTION_PROVIDER_CHANGED -> {
|
Intent.ACTION_PROVIDER_CHANGED,
|
||||||
|
Intent.ACTION_TIME_CHANGED -> {
|
||||||
CalendarHelper.updateEventList(context)
|
CalendarHelper.updateEventList(context)
|
||||||
}
|
}
|
||||||
Actions.ACTION_GO_TO_NEXT_EVENT -> {
|
Actions.ACTION_GO_TO_NEXT_EVENT -> {
|
||||||
|
@ -9,14 +9,12 @@ import android.service.notification.NotificationListenerService
|
|||||||
import android.service.notification.StatusBarNotification
|
import android.service.notification.StatusBarNotification
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.google.gson.Gson
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Actions
|
import com.tommasoberlose.anotherwidget.global.Actions
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
|
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import com.tommasoberlose.anotherwidget.utils.setExactIfCanSchedule
|
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -24,26 +22,19 @@ import java.util.*
|
|||||||
class NotificationListener : NotificationListenerService() {
|
class NotificationListener : NotificationListenerService() {
|
||||||
override fun onListenerConnected() {
|
override fun onListenerConnected() {
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
||||||
ActiveNotificationsHelper.clearLastNotification(this)
|
MainWidget.updateWidget(this)
|
||||||
super.onListenerConnected()
|
super.onListenerConnected()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onListenerDisconnected() {
|
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
|
||||||
ActiveNotificationsHelper.clearLastNotification(this)
|
|
||||||
super.onListenerDisconnected()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNotificationPosted(sbn: StatusBarNotification?) {
|
override fun onNotificationPosted(sbn: StatusBarNotification?) {
|
||||||
sbn?.notification?.extras?.let { bundle ->
|
sbn?.notification?.extras?.let { bundle ->
|
||||||
bundle.getParcelable<MediaSession.Token>(Notification.EXTRA_MEDIA_SESSION)?.let {
|
bundle.getParcelable<MediaSession.Token>(Notification.EXTRA_MEDIA_SESSION)?.let {
|
||||||
if (Preferences.showMusic)
|
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
|
||||||
} ?: run {
|
} ?: run {
|
||||||
val isGroupHeader = sbn.notification.flags and Notification.FLAG_GROUP_SUMMARY != 0
|
val isGroupHeader = sbn.notification.flags and Notification.FLAG_GROUP_SUMMARY != 0
|
||||||
val isOngoing = sbn.notification.flags and Notification.FLAG_ONGOING_EVENT != 0
|
val isOngoing = sbn.notification.flags and Notification.FLAG_ONGOING_EVENT != 0
|
||||||
|
|
||||||
if (Preferences.showNotifications && bundle.containsKey(Notification.EXTRA_TITLE) && !isGroupHeader && !isOngoing && ActiveNotificationsHelper.isAppAccepted(sbn.packageName) && !sbn.packageName.contains("com.android.systemui")) {
|
if (bundle.containsKey(Notification.EXTRA_TITLE) && !isGroupHeader && !isOngoing && ActiveNotificationsHelper.isAppAccepted(sbn.packageName) && !sbn.packageName.contains("com.android.systemui")) {
|
||||||
Preferences.lastNotificationId = sbn.id
|
Preferences.lastNotificationId = sbn.id
|
||||||
Preferences.lastNotificationTitle = bundle.getString(Notification.EXTRA_TITLE) ?: ""
|
Preferences.lastNotificationTitle = bundle.getString(Notification.EXTRA_TITLE) ?: ""
|
||||||
try {
|
try {
|
||||||
@ -67,13 +58,15 @@ class NotificationListener : NotificationListenerService() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onNotificationRemoved(sbn: StatusBarNotification?) {
|
override fun onNotificationRemoved(sbn: StatusBarNotification?) {
|
||||||
if (Preferences.showMusic)
|
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
|
||||||
sbn?.let {
|
sbn?.let {
|
||||||
if (Preferences.showNotifications && sbn.id == Preferences.lastNotificationId && sbn.packageName == Preferences.lastNotificationPackage) {
|
if (sbn.id == Preferences.lastNotificationId && sbn.packageName == Preferences.lastNotificationPackage) {
|
||||||
ActiveNotificationsHelper.clearLastNotification(this)
|
ActiveNotificationsHelper.clearLastNotification(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MainWidget.updateWidget(this)
|
||||||
super.onNotificationRemoved(sbn)
|
super.onNotificationRemoved(sbn)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,9 +75,10 @@ class NotificationListener : NotificationListenerService() {
|
|||||||
val intent = Intent(context, UpdatesReceiver::class.java).apply {
|
val intent = Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
action = Actions.ACTION_CLEAR_NOTIFICATION
|
action = Actions.ACTION_CLEAR_NOTIFICATION
|
||||||
}
|
}
|
||||||
|
cancel(PendingIntent.getBroadcast(context, 28943, intent, 0))
|
||||||
val timeoutPref = Constants.GlanceNotificationTimer.fromInt(Preferences.hideNotificationAfter)
|
val timeoutPref = Constants.GlanceNotificationTimer.fromInt(Preferences.hideNotificationAfter)
|
||||||
if (timeoutPref != Constants.GlanceNotificationTimer.WHEN_DISMISSED) {
|
if (timeoutPref != Constants.GlanceNotificationTimer.WHEN_DISMISSED) {
|
||||||
setExactIfCanSchedule(
|
setExact(
|
||||||
AlarmManager.RTC,
|
AlarmManager.RTC,
|
||||||
Calendar.getInstance().timeInMillis + when (timeoutPref) {
|
Calendar.getInstance().timeInMillis + when (timeoutPref) {
|
||||||
Constants.GlanceNotificationTimer.HALF_MINUTE -> 30 * 1000
|
Constants.GlanceNotificationTimer.HALF_MINUTE -> 30 * 1000
|
||||||
@ -92,27 +86,16 @@ class NotificationListener : NotificationListenerService() {
|
|||||||
Constants.GlanceNotificationTimer.FIVE_MINUTES -> 5 * 60 * 1000
|
Constants.GlanceNotificationTimer.FIVE_MINUTES -> 5 * 60 * 1000
|
||||||
Constants.GlanceNotificationTimer.TEN_MINUTES -> 10 * 60 * 1000
|
Constants.GlanceNotificationTimer.TEN_MINUTES -> 10 * 60 * 1000
|
||||||
Constants.GlanceNotificationTimer.FIFTEEN_MINUTES -> 15 * 60 * 1000
|
Constants.GlanceNotificationTimer.FIFTEEN_MINUTES -> 15 * 60 * 1000
|
||||||
else -> 60 * 1000
|
else -> 0
|
||||||
},
|
},
|
||||||
PendingIntent.getBroadcast(
|
PendingIntent.getBroadcast(
|
||||||
context,
|
context,
|
||||||
5,
|
5,
|
||||||
intent,
|
intent,
|
||||||
PendingIntent.FLAG_IMMUTABLE
|
0
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
companion object {
|
|
||||||
fun clearTimeout(context: Context) {
|
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
|
||||||
val intent = Intent(context, UpdatesReceiver::class.java).apply {
|
|
||||||
action = Actions.ACTION_CLEAR_NOTIFICATION
|
|
||||||
}
|
|
||||||
cancel(PendingIntent.getBroadcast(context, 5, intent, PendingIntent.FLAG_IMMUTABLE))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,16 +5,21 @@ import android.app.PendingIntent
|
|||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.core.app.AlarmManagerCompat
|
||||||
|
import androidx.core.content.ContextCompat.getSystemService
|
||||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||||
import com.tommasoberlose.anotherwidget.global.Actions
|
import com.tommasoberlose.anotherwidget.global.Actions
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.helpers.*
|
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.BatteryHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||||
import com.tommasoberlose.anotherwidget.models.Event
|
import com.tommasoberlose.anotherwidget.models.Event
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import com.tommasoberlose.anotherwidget.utils.setExactIfCanSchedule
|
|
||||||
import java.util.*
|
|
||||||
import org.joda.time.Period
|
import org.joda.time.Period
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class UpdatesReceiver : BroadcastReceiver() {
|
class UpdatesReceiver : BroadcastReceiver() {
|
||||||
@ -25,18 +30,17 @@ class UpdatesReceiver : BroadcastReceiver() {
|
|||||||
Intent.ACTION_MY_PACKAGE_REPLACED,
|
Intent.ACTION_MY_PACKAGE_REPLACED,
|
||||||
Intent.ACTION_TIME_CHANGED,
|
Intent.ACTION_TIME_CHANGED,
|
||||||
Intent.ACTION_TIMEZONE_CHANGED,
|
Intent.ACTION_TIMEZONE_CHANGED,
|
||||||
Intent.ACTION_LOCALE_CHANGED -> {
|
Intent.ACTION_LOCALE_CHANGED,
|
||||||
CalendarHelper.updateEventList(context)
|
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(context)
|
|
||||||
ActiveNotificationsHelper.clearLastNotification(context)
|
|
||||||
GreetingsHelper.toggleGreetings(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
Intent.ACTION_DATE_CHANGED,
|
Intent.ACTION_DATE_CHANGED,
|
||||||
Actions.ACTION_CALENDAR_UPDATE -> {
|
Actions.ACTION_CALENDAR_UPDATE -> {
|
||||||
|
ActiveNotificationsHelper.clearLastNotification(context)
|
||||||
|
MediaPlayerHelper.updatePlayingMediaInfo(context)
|
||||||
CalendarHelper.updateEventList(context)
|
CalendarHelper.updateEventList(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
|
||||||
|
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
|
||||||
|
Actions.ACTION_ALARM_UPDATE,
|
||||||
Actions.ACTION_TIME_UPDATE -> {
|
Actions.ACTION_TIME_UPDATE -> {
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
if (intent.hasExtra(EVENT_ID)) {
|
if (intent.hasExtra(EVENT_ID)) {
|
||||||
@ -44,21 +48,12 @@ class UpdatesReceiver : BroadcastReceiver() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
|
|
||||||
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
|
|
||||||
Actions.ACTION_ALARM_UPDATE,
|
|
||||||
Actions.ACTION_UPDATE_GREETINGS -> {
|
|
||||||
MainWidget.updateWidget(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
Actions.ACTION_CLEAR_NOTIFICATION -> {
|
Actions.ACTION_CLEAR_NOTIFICATION -> {
|
||||||
ActiveNotificationsHelper.clearLastNotification(context)
|
ActiveNotificationsHelper.clearLastNotification(context)
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
}
|
}
|
||||||
|
Actions.ACTION_UPDATE_GREETINGS -> {
|
||||||
Actions.ACTION_REFRESH -> {
|
MainWidget.updateWidget(context)
|
||||||
CalendarHelper.updateEventList(context)
|
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(context)
|
|
||||||
WeatherHelper.updateWeather(context)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,37 +62,15 @@ class UpdatesReceiver : BroadcastReceiver() {
|
|||||||
const val EVENT_ID = "EVENT_ID"
|
const val EVENT_ID = "EVENT_ID"
|
||||||
|
|
||||||
fun setUpdates(context: Context, eventId: Long? = null) {
|
fun setUpdates(context: Context, eventId: Long? = null) {
|
||||||
if (!Preferences.showEvents)
|
|
||||||
return
|
|
||||||
val eventRepository = EventRepository(context)
|
val eventRepository = EventRepository(context)
|
||||||
if (eventId == null) {
|
if (eventId == null) {
|
||||||
// schedule ACTION_CALENDAR_UPDATE at midnight (ACTION_DATE_CHANGED no longer works)
|
removeUpdates(context)
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
|
||||||
setExactIfCanSchedule(
|
|
||||||
AlarmManager.RTC,
|
|
||||||
Calendar.getInstance().apply {
|
|
||||||
set(Calendar.MILLISECOND, 0)
|
|
||||||
set(Calendar.SECOND, 0)
|
|
||||||
set(Calendar.MINUTE, 0)
|
|
||||||
set(Calendar.HOUR_OF_DAY, 0)
|
|
||||||
add(Calendar.DATE, 1)
|
|
||||||
}.timeInMillis,
|
|
||||||
PendingIntent.getBroadcast(
|
|
||||||
context,
|
|
||||||
0,
|
|
||||||
Intent(context, UpdatesReceiver::class.java).apply {
|
|
||||||
action = Actions.ACTION_CALENDAR_UPDATE
|
|
||||||
},
|
|
||||||
PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
eventRepository.getFutureEvents().forEach { event ->
|
eventRepository.getFutureEvents().forEach { event ->
|
||||||
setEventUpdate(context, event)
|
setEventUpdate(context, event)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val event = eventRepository.getEventById(eventId)
|
val event = eventRepository.getEventByEventId(eventId)
|
||||||
if (event != null) {
|
if (event != null) {
|
||||||
setEventUpdate(context, event)
|
setEventUpdate(context, event)
|
||||||
}
|
}
|
||||||
@ -106,90 +79,109 @@ class UpdatesReceiver : BroadcastReceiver() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setEventUpdate(context: Context, event: Event) {
|
private fun setEventUpdate(context: Context, event: Event) {
|
||||||
val now = Calendar.getInstance().apply {
|
|
||||||
set(Calendar.SECOND, 0)
|
|
||||||
set(Calendar.MILLISECOND, 0)
|
|
||||||
}
|
|
||||||
val diff = Period(now.timeInMillis, event.startDate, org.joda.time.PeriodType.time())
|
|
||||||
val limit = when (Preferences.showUntil) {
|
|
||||||
0 -> 1000 * 60 * 60 * 3
|
|
||||||
1 -> 1000 * 60 * 60 * 6
|
|
||||||
2 -> 1000 * 60 * 60 * 12
|
|
||||||
3 -> 1000 * 60 * 60 * 24
|
|
||||||
4 -> 1000 * 60 * 60 * 24 * 3
|
|
||||||
5 -> 1000 * 60 * 60 * 24 * 7
|
|
||||||
6 -> 1000 * 60 * 30
|
|
||||||
7 -> 1000 * 60 * 60
|
|
||||||
else -> 1000 * 60 * 60 * 6
|
|
||||||
}
|
|
||||||
val fireTime = when {
|
|
||||||
event.startDate <= now.timeInMillis
|
|
||||||
-> event.endDate
|
|
||||||
event.startDate > now.timeInMillis + limit
|
|
||||||
-> event.startDate - limit
|
|
||||||
!Preferences.showDiffTime
|
|
||||||
-> return
|
|
||||||
event.allDay
|
|
||||||
-> event.startDate
|
|
||||||
diff.hours > 12
|
|
||||||
-> event.startDate - 12 * 1000 * 60 * 60 + 1000 * 60
|
|
||||||
diff.hours > 0
|
|
||||||
-> event.startDate - diff.hours * 1000 * 60 * 60 + 1000 * 60
|
|
||||||
else
|
|
||||||
-> event.startDate - 1000 * 60 * when (Preferences.widgetUpdateFrequency) {
|
|
||||||
Constants.WidgetUpdateFrequency.DEFAULT.rawValue -> {
|
|
||||||
when {
|
|
||||||
diff.minutes >= 45 -> 44
|
|
||||||
diff.minutes >= 30 -> 29
|
|
||||||
diff.minutes >= 15 -> 14
|
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.WidgetUpdateFrequency.HIGH.rawValue -> {
|
|
||||||
when {
|
|
||||||
diff.minutes >= 5 -> diff.minutes - diff.minutes % 5 - 1
|
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// no need to schedule updates after the next ACTION_CALENDAR_UPDATE
|
|
||||||
if (Calendar.getInstance().apply {
|
|
||||||
set(Calendar.MILLISECOND, 0)
|
|
||||||
set(Calendar.SECOND, 0)
|
|
||||||
set(Calendar.MINUTE, 0)
|
|
||||||
set(Calendar.HOUR_OF_DAY, 0)
|
|
||||||
add(Calendar.DATE, 1)
|
|
||||||
}.timeInMillis <= fireTime) return
|
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
setExactIfCanSchedule(
|
val now = Calendar.getInstance().apply {
|
||||||
AlarmManager.RTC,
|
set(Calendar.SECOND, 0)
|
||||||
fireTime.coerceAtLeast(now.timeInMillis + 1000 * 60),
|
set(Calendar.MILLISECOND, 0)
|
||||||
PendingIntent.getBroadcast(
|
}
|
||||||
context,
|
val diff = Period(now.timeInMillis, event.startDate)
|
||||||
event.id.toInt(),
|
val limit = when (Preferences.showUntil) {
|
||||||
Intent(context, UpdatesReceiver::class.java).apply {
|
0 -> 1000 * 60 * 60 * 3
|
||||||
action = Actions.ACTION_TIME_UPDATE
|
1 -> 1000 * 60 * 60 * 6
|
||||||
if (event.startDate > now.timeInMillis)
|
2 -> 1000 * 60 * 60 * 12
|
||||||
putExtra(EVENT_ID, event.id)
|
3 -> 1000 * 60 * 60 * 24
|
||||||
},
|
4 -> 1000 * 60 * 60 * 24 * 3
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
5 -> 1000 * 60 * 60 * 24 * 7
|
||||||
|
6 -> 1000 * 60 * 30
|
||||||
|
7 -> 1000 * 60 * 60
|
||||||
|
else -> 1000 * 60 * 60 * 6
|
||||||
|
}
|
||||||
|
if (event.startDate <= limit) {
|
||||||
|
if (event.startDate > now.timeInMillis) {
|
||||||
|
// Update the widget every hour till the event
|
||||||
|
if (diff.hours == 0) {
|
||||||
|
var minutes = 0
|
||||||
|
when (Preferences.widgetUpdateFrequency) {
|
||||||
|
Constants.WidgetUpdateFrequency.DEFAULT.value -> {
|
||||||
|
minutes = when {
|
||||||
|
diff.minutes > 50 -> 50
|
||||||
|
diff.minutes > 30 -> 30
|
||||||
|
diff.minutes > 15 -> 15
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.WidgetUpdateFrequency.HIGH.value -> {
|
||||||
|
minutes = diff.minutes - (diff.minutes % 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setExact(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
if (event.startDate - minutes * 1000 * 60 > (now.timeInMillis + 120 * 1000)) event.startDate - 60 * 1000 * minutes else now.timeInMillis + 120000,
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
event.eventID.toInt(),
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_TIME_UPDATE
|
||||||
|
putExtra(EVENT_ID, event.eventID)
|
||||||
|
},
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
setExact(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
event.startDate - diff.hours * 1000 * 60 * 60 + if (diff.minutes > 30) (-30) else (+30),
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
event.eventID.toInt(),
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_TIME_UPDATE
|
||||||
|
putExtra(EVENT_ID, event.eventID)
|
||||||
|
},
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Update the widget one second after the event is finished
|
||||||
|
val fireTime =
|
||||||
|
if (event.endDate > now.timeInMillis + 120 * 1000) event.endDate else now.timeInMillis + 120000
|
||||||
|
setExact(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
fireTime,
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
event.eventID.toInt(),
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_TIME_UPDATE
|
||||||
|
},
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setExact(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
if (event.startDate - limit > now.timeInMillis + 120 * 1000) event.startDate - limit else now.timeInMillis + 120000,
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
event.eventID.toInt(),
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_TIME_UPDATE
|
||||||
|
putExtra(EVENT_ID, event.eventID)
|
||||||
|
},
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeUpdates(context: Context) {
|
fun removeUpdates(context: Context) {
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
cancel(PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java).apply {
|
|
||||||
action = Actions.ACTION_CALENDAR_UPDATE
|
|
||||||
}, PendingIntent.FLAG_IMMUTABLE))
|
|
||||||
val eventRepository = EventRepository(context)
|
val eventRepository = EventRepository(context)
|
||||||
eventRepository.getFutureEvents().forEach {
|
eventRepository.getFutureEvents().forEach {
|
||||||
cancel(PendingIntent.getBroadcast(context, it.id.toInt(), Intent(context, UpdatesReceiver::class.java).apply {
|
cancel(PendingIntent.getBroadcast(context, it.eventID.toInt(), Intent(context, UpdatesReceiver::class.java), 0))
|
||||||
action = Actions.ACTION_TIME_UPDATE
|
|
||||||
}, PendingIntent.FLAG_IMMUTABLE))
|
|
||||||
}
|
}
|
||||||
eventRepository.close()
|
eventRepository.close()
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
package com.tommasoberlose.anotherwidget.receivers
|
package com.tommasoberlose.anotherwidget.receivers
|
||||||
|
|
||||||
|
import android.app.AlarmManager
|
||||||
|
import android.app.PendingIntent
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import com.tommasoberlose.anotherwidget.global.Actions
|
import com.tommasoberlose.anotherwidget.global.Actions
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||||
import com.tommasoberlose.anotherwidget.services.WeatherWorker
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class WeatherReceiver : BroadcastReceiver() {
|
class WeatherReceiver : BroadcastReceiver() {
|
||||||
|
|
||||||
@ -16,22 +22,63 @@ class WeatherReceiver : BroadcastReceiver() {
|
|||||||
Intent.ACTION_MY_PACKAGE_REPLACED,
|
Intent.ACTION_MY_PACKAGE_REPLACED,
|
||||||
Intent.ACTION_TIMEZONE_CHANGED,
|
Intent.ACTION_TIMEZONE_CHANGED,
|
||||||
Intent.ACTION_LOCALE_CHANGED,
|
Intent.ACTION_LOCALE_CHANGED,
|
||||||
Intent.ACTION_TIME_CHANGED,
|
Intent.ACTION_TIME_CHANGED -> setUpdates(context)
|
||||||
|
|
||||||
Actions.ACTION_WEATHER_UPDATE -> {
|
Actions.ACTION_WEATHER_UPDATE -> {
|
||||||
WeatherHelper.updateWeather(context)
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
WeatherHelper.updateWeather(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private const val MINUTE = 60 * 1000L
|
||||||
fun setUpdates(context: Context) {
|
fun setUpdates(context: Context) {
|
||||||
|
removeUpdates(context)
|
||||||
|
|
||||||
if (Preferences.showWeather) {
|
if (Preferences.showWeather) {
|
||||||
WeatherWorker.enqueueTrigger(context)
|
val interval = MINUTE * when (Preferences.weatherRefreshPeriod) {
|
||||||
|
0 -> 30
|
||||||
|
1 -> 60
|
||||||
|
2 -> 60L * 3
|
||||||
|
3 -> 60L * 6
|
||||||
|
4 -> 60L * 12
|
||||||
|
5 -> 60L * 24
|
||||||
|
else -> 60
|
||||||
|
}
|
||||||
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
|
setRepeating(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
Calendar.getInstance().timeInMillis,
|
||||||
|
interval,
|
||||||
|
PendingIntent.getBroadcast(context, 0, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setOneTimeUpdate(context: Context) {
|
||||||
|
if (Preferences.showWeather) {
|
||||||
|
listOf(10, 20, 30).forEach {
|
||||||
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
|
setExactAndAllowWhileIdle(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
it * MINUTE,
|
||||||
|
PendingIntent.getBroadcast(context, it, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeUpdates(context: Context) {
|
fun removeUpdates(context: Context) {
|
||||||
WeatherWorker.cancelTrigger(context)
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
|
cancel(PendingIntent.getBroadcast(context, 0, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0))
|
||||||
|
listOf(10, 20, 30).forEach {
|
||||||
|
cancel(PendingIntent.getBroadcast(context, it, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import android.content.Intent
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.global.Actions
|
import com.tommasoberlose.anotherwidget.global.Actions
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
||||||
import com.tommasoberlose.anotherwidget.utils.toast
|
import com.tommasoberlose.anotherwidget.utils.toast
|
||||||
|
|
||||||
@ -16,25 +15,19 @@ class WidgetClickListenerReceiver : BroadcastReceiver() {
|
|||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
if (intent.action == Actions.ACTION_OPEN_WEATHER_INTENT) {
|
if (intent.action == Actions.ACTION_OPEN_WEATHER_INTENT) {
|
||||||
try {
|
try {
|
||||||
IntentHelper.getWeatherIntent(context).run {
|
context.startActivity(IntentHelper.getWeatherIntent(context))
|
||||||
if (flags and Intent.FLAG_ACTIVITY_NEW_TASK == Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
context.startActivity(this)
|
|
||||||
else
|
|
||||||
context.sendBroadcast(this)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
|
||||||
val uri = Uri.parse("https://yandex.ru/pogoda")
|
|
||||||
.buildUpon()
|
|
||||||
.appendQueryParameter("lat", Preferences.customLocationLat)
|
|
||||||
.appendQueryParameter("lon", Preferences.customLocationLon)
|
|
||||||
.build()
|
|
||||||
val i = Intent(Intent.ACTION_VIEW, uri)
|
|
||||||
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
||||||
try {
|
try {
|
||||||
context.startActivity(i)
|
context.applicationContext.startActivity(IntentHelper.getWeatherIntent(context.applicationContext))
|
||||||
} catch (ignored: Exception) {
|
} catch (e: Exception) {
|
||||||
context.toast(context.getString(R.string.error_opening_app))
|
val uri = Uri.parse("http://www.google.com/#q=weather")
|
||||||
|
val i = Intent(Intent.ACTION_VIEW, uri)
|
||||||
|
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
try {
|
||||||
|
context.startActivity(i)
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
context.toast(context.getString(R.string.error_opening_app))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.services
|
||||||
|
|
||||||
|
import android.app.job.JobInfo
|
||||||
|
import android.app.job.JobParameters
|
||||||
|
import android.app.job.JobScheduler
|
||||||
|
import android.app.job.JobService
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.provider.CalendarContract
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
|
||||||
|
class BatteryListenerJob : JobService() {
|
||||||
|
override fun onStartJob(params: JobParameters): Boolean {
|
||||||
|
MainWidget.updateWidget(this)
|
||||||
|
schedule(
|
||||||
|
this
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
override fun onStopJob(params: JobParameters): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val chargingJobId = 1006
|
||||||
|
private const val notChargingJobId = 1007
|
||||||
|
fun schedule(context: Context) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
remove(context)
|
||||||
|
val componentName = ComponentName(
|
||||||
|
context,
|
||||||
|
EventListenerJob::class.java
|
||||||
|
)
|
||||||
|
with(context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler) {
|
||||||
|
schedule(
|
||||||
|
JobInfo.Builder(chargingJobId, componentName)
|
||||||
|
.setRequiresCharging(true)
|
||||||
|
.setPersisted(true)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
schedule(
|
||||||
|
JobInfo.Builder(notChargingJobId, componentName)
|
||||||
|
.setRequiresCharging(false)
|
||||||
|
.setPersisted(true)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun remove(context: Context) {
|
||||||
|
val js = context.getSystemService(JobScheduler::class.java)
|
||||||
|
js?.cancel(chargingJobId)
|
||||||
|
js?.cancel(notChargingJobId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.services
|
||||||
|
|
||||||
|
import android.app.job.JobInfo
|
||||||
|
import android.app.job.JobInfo.TriggerContentUri
|
||||||
|
import android.app.job.JobParameters
|
||||||
|
import android.app.job.JobScheduler
|
||||||
|
import android.app.job.JobService
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.provider.CalendarContract
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||||
|
|
||||||
|
|
||||||
|
class EventListenerJob : JobService() {
|
||||||
|
override fun onStartJob(params: JobParameters): Boolean {
|
||||||
|
CalendarHelper.updateEventList(this)
|
||||||
|
schedule(
|
||||||
|
this
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
override fun onStopJob(params: JobParameters): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val jobId = 1005
|
||||||
|
fun schedule(context: Context) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
val componentName = ComponentName(
|
||||||
|
context,
|
||||||
|
EventListenerJob::class.java
|
||||||
|
)
|
||||||
|
with(context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler) {
|
||||||
|
schedule(
|
||||||
|
JobInfo.Builder(jobId, componentName)
|
||||||
|
.addTriggerContentUri(TriggerContentUri(
|
||||||
|
CalendarContract.CONTENT_URI,
|
||||||
|
TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS
|
||||||
|
))
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun remove(context: Context) {
|
||||||
|
val js = context.getSystemService(JobScheduler::class.java)
|
||||||
|
js?.cancel(jobId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.services
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.*
|
||||||
|
import android.app.job.JobScheduler
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.location.Address
|
||||||
|
import android.location.Geocoder
|
||||||
|
import android.os.IBinder
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.core.app.*
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.google.android.gms.location.LocationServices
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import java.lang.Exception
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
class LocationService : Service() {
|
||||||
|
|
||||||
|
private var job: Job? = null
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
startForeground(LOCATION_ACCESS_NOTIFICATION_ID, getLocationAccessNotification())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
job?.cancel()
|
||||||
|
job = GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
if (ActivityCompat.checkSelfPermission(
|
||||||
|
this@LocationService,
|
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION
|
||||||
|
) == PackageManager.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
|
LocationServices.getFusedLocationProviderClient(this@LocationService).lastLocation.addOnCompleteListener { task ->
|
||||||
|
val networkApi = WeatherNetworkApi(this@LocationService)
|
||||||
|
if (task.isSuccessful) {
|
||||||
|
val location = task.result
|
||||||
|
if (location != null) {
|
||||||
|
Preferences.customLocationLat = location.latitude.toString()
|
||||||
|
Preferences.customLocationLon = location.longitude.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
networkApi.updateWeather()
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
stopSelf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
} else {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
networkApi.updateWeather()
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
stopSelf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stopSelf()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return START_STICKY
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
job?.cancel()
|
||||||
|
job = null
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val LOCATION_ACCESS_NOTIFICATION_ID = 28465
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun requestNewLocation(context: Context) {
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||||
|
context.startForegroundService(Intent(context, LocationService::class.java))
|
||||||
|
} else {
|
||||||
|
context.startService(Intent(context, LocationService::class.java))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBind(intent: Intent?): IBinder? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLocationAccessNotification(): Notification {
|
||||||
|
with(NotificationManagerCompat.from(this)) {
|
||||||
|
// Create channel
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||||
|
createNotificationChannel(
|
||||||
|
NotificationChannel(
|
||||||
|
getString(R.string.location_access_notification_channel_id),
|
||||||
|
getString(R.string.location_access_notification_channel_name),
|
||||||
|
NotificationManager.IMPORTANCE_LOW
|
||||||
|
).apply {
|
||||||
|
description = getString(R.string.location_access_notification_channel_description)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val builder = NotificationCompat.Builder(this@LocationService, getString(R.string.location_access_notification_channel_id))
|
||||||
|
.setSmallIcon(R.drawable.ic_stat_notification)
|
||||||
|
.setContentTitle(getString(R.string.location_access_notification_title))
|
||||||
|
.setOngoing(true)
|
||||||
|
.setColor(ContextCompat.getColor(this@LocationService, R.color.colorAccent))
|
||||||
|
|
||||||
|
// Main intent that open the activity
|
||||||
|
builder.setContentIntent(PendingIntent.getActivity(this@LocationService, 0, Intent(this@LocationService, MainActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT))
|
||||||
|
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,218 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.services
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.*
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.IBinder
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.applyFilters
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.sortEvents
|
||||||
|
import com.tommasoberlose.anotherwidget.models.Event
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import me.everything.providers.android.calendar.CalendarProvider
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
class UpdateCalendarService : Service() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val CALENDAR_SYNC_NOTIFICATION_ID = 28466
|
||||||
|
fun enqueueWork(context: Context) {
|
||||||
|
context.startService(Intent(context, UpdateCalendarService::class.java))
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||||
|
context.startForegroundService(Intent(context, UpdateCalendarService::class.java))
|
||||||
|
} else {
|
||||||
|
context.startService(Intent(context, UpdateCalendarService::class.java))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
startForeground(CALENDAR_SYNC_NOTIFICATION_ID, getCalendarSyncNotification())
|
||||||
|
}
|
||||||
|
|
||||||
|
private var job: Job? = null
|
||||||
|
|
||||||
|
override fun onBind(intent: Intent?): IBinder? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
|
job?.cancel()
|
||||||
|
job = GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
|
||||||
|
val eventRepository = EventRepository(this@UpdateCalendarService)
|
||||||
|
if (Preferences.showEvents) {
|
||||||
|
val eventList = ArrayList<Event>()
|
||||||
|
|
||||||
|
val now = Calendar.getInstance()
|
||||||
|
val begin = Calendar.getInstance().apply {
|
||||||
|
set(Calendar.MILLISECOND, 0)
|
||||||
|
set(Calendar.SECOND, 0)
|
||||||
|
set(Calendar.MINUTE, 0)
|
||||||
|
set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
}
|
||||||
|
val limit = Calendar.getInstance().apply {
|
||||||
|
when (Preferences.showUntil) {
|
||||||
|
0 -> add(Calendar.HOUR, 3)
|
||||||
|
1 -> add(Calendar.HOUR, 6)
|
||||||
|
2 -> add(Calendar.HOUR, 12)
|
||||||
|
3 -> add(Calendar.DAY_OF_MONTH, 1)
|
||||||
|
4 -> add(Calendar.DAY_OF_MONTH, 3)
|
||||||
|
5 -> add(Calendar.DAY_OF_MONTH, 7)
|
||||||
|
6 -> add(Calendar.MINUTE, 30)
|
||||||
|
7 -> add(Calendar.HOUR, 1)
|
||||||
|
else -> add(Calendar.HOUR, 6)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkGrantedPermission(
|
||||||
|
Manifest.permission.READ_CALENDAR
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
eventRepository.resetNextEventData()
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
val provider = CalendarProvider(this@UpdateCalendarService)
|
||||||
|
val data = provider.getInstances(begin.timeInMillis, limit.timeInMillis)
|
||||||
|
if (data != null) {
|
||||||
|
val instances = data.list
|
||||||
|
for (instance in instances) {
|
||||||
|
try {
|
||||||
|
val e = provider.getEvent(instance.eventId)
|
||||||
|
if (e != null && !e.deleted && instance.begin <= limit.timeInMillis && now.timeInMillis < instance.end && !CalendarHelper.getFilteredCalendarIdList()
|
||||||
|
.contains(e.calendarId)
|
||||||
|
) {
|
||||||
|
if (e.allDay) {
|
||||||
|
val start = Calendar.getInstance()
|
||||||
|
start.timeInMillis = instance.begin
|
||||||
|
val end = Calendar.getInstance()
|
||||||
|
end.timeInMillis = instance.end
|
||||||
|
instance.begin =
|
||||||
|
start.timeInMillis - start.timeZone.getOffset(start.timeInMillis)
|
||||||
|
instance.end =
|
||||||
|
end.timeInMillis - end.timeZone.getOffset(end.timeInMillis)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check all day events
|
||||||
|
val startDate = Calendar.getInstance()
|
||||||
|
startDate.timeInMillis = instance.begin
|
||||||
|
val endDate = Calendar.getInstance()
|
||||||
|
endDate.timeInMillis = instance.end
|
||||||
|
|
||||||
|
val isAllDay = e.allDay || (
|
||||||
|
startDate.get(Calendar.MILLISECOND) == 0
|
||||||
|
&& startDate.get(Calendar.SECOND) == 0
|
||||||
|
&& startDate.get(Calendar.MINUTE) == 0
|
||||||
|
&& startDate.get(Calendar.HOUR_OF_DAY) == 0
|
||||||
|
&& endDate.get(Calendar.MILLISECOND) == 0
|
||||||
|
&& endDate.get(Calendar.SECOND) == 0
|
||||||
|
&& endDate.get(Calendar.MINUTE) == 0
|
||||||
|
&& endDate.get(Calendar.HOUR_OF_DAY) == 0
|
||||||
|
)
|
||||||
|
|
||||||
|
eventList.add(
|
||||||
|
Event(
|
||||||
|
id = instance.id,
|
||||||
|
eventID = e.id,
|
||||||
|
title = e.title ?: "",
|
||||||
|
startDate = instance.begin,
|
||||||
|
endDate = instance.end,
|
||||||
|
calendarID = e.calendarId.toInt(),
|
||||||
|
allDay = isAllDay,
|
||||||
|
address = e.eventLocation ?: "",
|
||||||
|
selfAttendeeStatus = e.selfAttendeeStatus.toInt(),
|
||||||
|
availability = e.availability
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val sortedEvents = eventList.sortEvents()
|
||||||
|
val filteredEventList = sortedEvents
|
||||||
|
.applyFilters()
|
||||||
|
|
||||||
|
if (filteredEventList.isEmpty()) {
|
||||||
|
eventRepository.resetNextEventData()
|
||||||
|
eventRepository.clearEvents()
|
||||||
|
} else {
|
||||||
|
eventRepository.saveEvents(
|
||||||
|
sortedEvents
|
||||||
|
)
|
||||||
|
eventRepository.saveNextEventData(filteredEventList.first())
|
||||||
|
}
|
||||||
|
} catch (ignored: java.lang.Exception) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eventRepository.resetNextEventData()
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdatesReceiver.setUpdates(this@UpdateCalendarService)
|
||||||
|
MainWidget.updateWidget(this@UpdateCalendarService)
|
||||||
|
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
eventRepository.close()
|
||||||
|
|
||||||
|
stopSelf()
|
||||||
|
}
|
||||||
|
|
||||||
|
return START_STICKY
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
job?.cancel()
|
||||||
|
job = null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCalendarSyncNotification(): Notification {
|
||||||
|
with(NotificationManagerCompat.from(this)) {
|
||||||
|
// Create channel
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||||
|
createNotificationChannel(
|
||||||
|
NotificationChannel(
|
||||||
|
getString(R.string.calendar_sync_notification_channel_id),
|
||||||
|
getString(R.string.calendar_sync_notification_channel_name),
|
||||||
|
NotificationManager.IMPORTANCE_LOW
|
||||||
|
).apply {
|
||||||
|
description = getString(R.string.calendar_sync_notification_channel_description)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val builder = NotificationCompat.Builder(this@UpdateCalendarService, getString(R.string.calendar_sync_notification_channel_id))
|
||||||
|
.setSmallIcon(R.drawable.ic_stat_notification)
|
||||||
|
.setContentTitle(getString(R.string.calendar_sync_notification_title))
|
||||||
|
.setOngoing(true)
|
||||||
|
.setColor(ContextCompat.getColor(this@UpdateCalendarService, R.color.colorAccent))
|
||||||
|
|
||||||
|
// Main intent that open the activity
|
||||||
|
builder.setContentIntent(PendingIntent.getActivity(this@UpdateCalendarService, 0, Intent(this@UpdateCalendarService, MainActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT))
|
||||||
|
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,199 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.services
|
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.Build
|
|
||||||
import android.provider.CalendarContract
|
|
||||||
import androidx.work.Constraints
|
|
||||||
import androidx.work.ExistingWorkPolicy
|
|
||||||
import androidx.work.OneTimeWorkRequestBuilder
|
|
||||||
import androidx.work.WorkManager
|
|
||||||
import androidx.work.Worker
|
|
||||||
import androidx.work.WorkerParameters
|
|
||||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.applyFilters
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.sortEvents
|
|
||||||
import com.tommasoberlose.anotherwidget.models.Event
|
|
||||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
|
||||||
import java.util.*
|
|
||||||
import me.everything.providers.android.calendar.CalendarProvider
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
|
|
||||||
class UpdateCalendarWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
|
|
||||||
|
|
||||||
override fun doWork(): Result {
|
|
||||||
val context = applicationContext
|
|
||||||
UpdatesReceiver.removeUpdates(context)
|
|
||||||
val eventRepository = EventRepository(context)
|
|
||||||
|
|
||||||
if (Preferences.showEvents) {
|
|
||||||
if (!context.checkGrantedPermission(Manifest.permission.READ_CALENDAR)) {
|
|
||||||
eventRepository.resetNextEventData()
|
|
||||||
eventRepository.clearEvents()
|
|
||||||
} else {
|
|
||||||
// fetch all events from now to next ACTION_CALENDAR_UPDATE + limit
|
|
||||||
val now = Calendar.getInstance()
|
|
||||||
val limit = Calendar.getInstance().apply {
|
|
||||||
set(Calendar.MILLISECOND, 0)
|
|
||||||
set(Calendar.SECOND, 0)
|
|
||||||
set(Calendar.MINUTE, 0)
|
|
||||||
set(Calendar.HOUR_OF_DAY, 0)
|
|
||||||
add(Calendar.DATE, 1)
|
|
||||||
when (Preferences.showUntil) {
|
|
||||||
0 -> add(Calendar.HOUR, 3)
|
|
||||||
1 -> add(Calendar.HOUR, 6)
|
|
||||||
2 -> add(Calendar.HOUR, 12)
|
|
||||||
3 -> add(Calendar.DAY_OF_MONTH, 1)
|
|
||||||
4 -> add(Calendar.DAY_OF_MONTH, 3)
|
|
||||||
5 -> add(Calendar.DAY_OF_MONTH, 7)
|
|
||||||
6 -> add(Calendar.MINUTE, 30)
|
|
||||||
7 -> add(Calendar.HOUR, 1)
|
|
||||||
else -> add(Calendar.HOUR, 6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
val eventList = ArrayList<Event>()
|
|
||||||
val provider = CalendarProvider(context)
|
|
||||||
// apply time zone offset to correctly fetch all-day events
|
|
||||||
val data = provider.getInstances(
|
|
||||||
now.timeInMillis + now.timeZone.getOffset(now.timeInMillis).coerceAtMost(0),
|
|
||||||
limit.timeInMillis + limit.timeZone.getOffset(limit.timeInMillis).coerceAtLeast(0)
|
|
||||||
)
|
|
||||||
if (data != null) {
|
|
||||||
val filteredCalendarIdList = CalendarHelper.getFilteredCalendarIdList()
|
|
||||||
for (instance in data.list) {
|
|
||||||
try {
|
|
||||||
val e = provider.getEvent(instance.eventId)
|
|
||||||
if (e == null || e.deleted || filteredCalendarIdList.contains(e.calendarId))
|
|
||||||
continue
|
|
||||||
if (e.allDay) {
|
|
||||||
val start = Calendar.getInstance()
|
|
||||||
start.timeInMillis = instance.begin
|
|
||||||
val end = Calendar.getInstance()
|
|
||||||
end.timeInMillis = instance.end
|
|
||||||
instance.begin =
|
|
||||||
start.timeInMillis - start.timeZone.getOffset(start.timeInMillis)
|
|
||||||
instance.end =
|
|
||||||
end.timeInMillis - end.timeZone.getOffset(end.timeInMillis)
|
|
||||||
}
|
|
||||||
if (instance.begin <= limit.timeInMillis && now.timeInMillis < instance.end) {
|
|
||||||
/* Following check may result in "fake" all-day events with
|
|
||||||
* non-UTC start/end time, and therefore cannot be found by
|
|
||||||
* Calendar when tapped to open details.
|
|
||||||
// Check all day events
|
|
||||||
val startDate = Calendar.getInstance()
|
|
||||||
startDate.timeInMillis = instance.begin
|
|
||||||
val endDate = Calendar.getInstance()
|
|
||||||
endDate.timeInMillis = instance.end
|
|
||||||
|
|
||||||
val isAllDay = e.allDay || (
|
|
||||||
startDate.get(Calendar.MILLISECOND) == 0
|
|
||||||
&& startDate.get(Calendar.SECOND) == 0
|
|
||||||
&& startDate.get(Calendar.MINUTE) == 0
|
|
||||||
&& startDate.get(Calendar.HOUR_OF_DAY) == 0
|
|
||||||
&& endDate.get(Calendar.MILLISECOND) == 0
|
|
||||||
&& endDate.get(Calendar.SECOND) == 0
|
|
||||||
&& endDate.get(Calendar.MINUTE) == 0
|
|
||||||
&& endDate.get(Calendar.HOUR_OF_DAY) == 0
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
|
|
||||||
eventList.add(
|
|
||||||
Event(
|
|
||||||
id = instance.id,
|
|
||||||
eventID = e.id,
|
|
||||||
title = e.title ?: "",
|
|
||||||
startDate = instance.begin,
|
|
||||||
endDate = instance.end,
|
|
||||||
calendarID = e.calendarId,
|
|
||||||
allDay = e.allDay,
|
|
||||||
address = e.eventLocation ?: "",
|
|
||||||
selfAttendeeStatus = e.selfAttendeeStatus.toInt(),
|
|
||||||
availability = e.availability
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val sortedEvents = eventList.sortEvents()
|
|
||||||
val filteredEventList = sortedEvents.applyFilters()
|
|
||||||
|
|
||||||
if (filteredEventList.isEmpty()) {
|
|
||||||
eventRepository.resetNextEventData()
|
|
||||||
eventRepository.clearEvents()
|
|
||||||
} else {
|
|
||||||
val first = filteredEventList.first()
|
|
||||||
if (Preferences.nextEventId != first.id && (
|
|
||||||
//Preferences.showWeatherAsGlanceProvider || !Preferences.showNextEvent ||
|
|
||||||
eventRepository.getEventById(first.id)?.startDate != first.startDate))
|
|
||||||
eventRepository.saveNextEventData(first)
|
|
||||||
eventRepository.saveEvents(filteredEventList)
|
|
||||||
}
|
|
||||||
} catch (ignored: java.lang.Exception) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
eventRepository.resetNextEventData()
|
|
||||||
eventRepository.clearEvents()
|
|
||||||
}
|
|
||||||
eventRepository.close()
|
|
||||||
UpdatesReceiver.setUpdates(context)
|
|
||||||
|
|
||||||
MainWidget.updateWidget(context)
|
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
|
||||||
|
|
||||||
if (Preferences.showEvents)
|
|
||||||
enqueueTrigger(context)
|
|
||||||
return Result.success()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun enqueue(context: Context) {
|
|
||||||
WorkManager.getInstance(context).enqueueUniqueWork(
|
|
||||||
"updateEventList",
|
|
||||||
ExistingWorkPolicy.KEEP,
|
|
||||||
OneTimeWorkRequestBuilder<UpdateCalendarWorker>().build()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun enqueueTrigger(context: Context) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
||||||
WorkManager.getInstance(context).enqueueUniqueWork(
|
|
||||||
"updateEventListTrigger",
|
|
||||||
ExistingWorkPolicy.KEEP,
|
|
||||||
OneTimeWorkRequestBuilder<Trigger>().setConstraints(
|
|
||||||
Constraints.Builder().addContentUriTrigger(
|
|
||||||
CalendarContract.CONTENT_URI,
|
|
||||||
true
|
|
||||||
).build()
|
|
||||||
).build()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun cancelTrigger(context: Context) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
||||||
WorkManager.getInstance(context).cancelUniqueWork(
|
|
||||||
"updateEventListTrigger"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Trigger(context: Context, params: WorkerParameters) : Worker(context, params) {
|
|
||||||
override fun doWork(): Result {
|
|
||||||
if (Preferences.showEvents && !isStopped)
|
|
||||||
enqueue(applicationContext)
|
|
||||||
return Result.success()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.services
|
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.content.Context
|
|
||||||
import android.location.Location
|
|
||||||
import android.location.LocationManager
|
|
||||||
import androidx.work.CoroutineWorker
|
|
||||||
import androidx.work.ExistingWorkPolicy
|
|
||||||
import androidx.work.OneTimeWorkRequestBuilder
|
|
||||||
import androidx.work.WorkManager
|
|
||||||
import androidx.work.Worker
|
|
||||||
import androidx.work.WorkerParameters
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
class WeatherWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
|
|
||||||
|
|
||||||
override suspend fun doWork(): Result {
|
|
||||||
val context = applicationContext
|
|
||||||
if (Preferences.customLocationAdd == "" &&
|
|
||||||
context.checkGrantedPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
|
|
||||||
) {
|
|
||||||
val lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
|
||||||
var location: Location? = null
|
|
||||||
for (provider in lm.getProviders(true)) {
|
|
||||||
lm.getLastKnownLocation(provider)?.let {
|
|
||||||
if (location == null ||
|
|
||||||
it.time - location!!.time > 2 * 60 * 1000 ||
|
|
||||||
(it.time - location!!.time > -2 * 60 * 1000 && it.accuracy < location!!.accuracy))
|
|
||||||
location = it
|
|
||||||
}
|
|
||||||
}
|
|
||||||
location?.let { location ->
|
|
||||||
Preferences.customLocationLat = location.latitude.toString()
|
|
||||||
Preferences.customLocationLon = location.longitude.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
WeatherNetworkApi(context).updateWeather()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Preferences.showWeather)
|
|
||||||
enqueueTrigger(context)
|
|
||||||
return Result.success()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun enqueue(context: Context, replace: Boolean = false) {
|
|
||||||
WorkManager.getInstance(context).enqueueUniqueWork(
|
|
||||||
"updateWeather",
|
|
||||||
if (replace) ExistingWorkPolicy.REPLACE else ExistingWorkPolicy.KEEP,
|
|
||||||
OneTimeWorkRequestBuilder<WeatherWorker>().build()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun enqueueTrigger(context: Context) {
|
|
||||||
val interval = when (Preferences.weatherRefreshPeriod) {
|
|
||||||
0 -> 30
|
|
||||||
1 -> 60
|
|
||||||
2 -> 60L * 3
|
|
||||||
3 -> 60L * 6
|
|
||||||
4 -> 60L * 12
|
|
||||||
5 -> 60L * 24
|
|
||||||
else -> 60
|
|
||||||
}
|
|
||||||
WorkManager.getInstance(context).enqueueUniqueWork(
|
|
||||||
"updateWeatherTrigger",
|
|
||||||
ExistingWorkPolicy.REPLACE,
|
|
||||||
OneTimeWorkRequestBuilder<Trigger>().setInitialDelay(
|
|
||||||
interval, TimeUnit.MINUTES
|
|
||||||
).build()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun cancelTrigger(context: Context) {
|
|
||||||
WorkManager.getInstance(context).cancelUniqueWork(
|
|
||||||
"updateWeatherTrigger"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Trigger(context: Context, params: WorkerParameters) : Worker(context, params) {
|
|
||||||
override fun doWork(): Result {
|
|
||||||
if (Preferences.showWeather && !isStopped)
|
|
||||||
enqueue(applicationContext)
|
|
||||||
return Result.success()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -46,7 +46,6 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
overridePendingTransition(R.anim.nav_default_enter_anim, R.anim.nav_default_exit_anim)
|
|
||||||
|
|
||||||
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
|
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
|
||||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
binding = ActivityMainBinding.inflate(layoutInflater)
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.activities
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import com.tommasoberlose.anotherwidget.R
|
|
||||||
import com.tommasoberlose.anotherwidget.databinding.ActivityMainBinding
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
|
|
||||||
class SplashActivity: AppCompatActivity() {
|
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
lifecycleScope.launchWhenResumed {
|
|
||||||
delay(1000)
|
|
||||||
|
|
||||||
if (!this@SplashActivity.isDestroyed) {
|
|
||||||
startActivity(Intent(this@SplashActivity, MainActivity::class.java))
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,96 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.activities.settings
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.android.billingclient.api.*
|
||||||
|
import com.android.billingclient.api.BillingClient.BillingResponseCode.OK
|
||||||
|
import com.android.billingclient.api.BillingClient.BillingResponseCode.USER_CANCELED
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.databinding.ActivitySupportDevBinding
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.settings.SupportDevViewModel
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.toast
|
||||||
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
|
|
||||||
|
class SupportDevActivity : AppCompatActivity(), PurchasesUpdatedListener {
|
||||||
|
|
||||||
|
private lateinit var viewModel: SupportDevViewModel
|
||||||
|
private lateinit var adapter: SlimAdapter
|
||||||
|
private lateinit var binding: ActivitySupportDevBinding
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
viewModel = ViewModelProvider(this).get(SupportDevViewModel::class.java)
|
||||||
|
viewModel.billingClient = BillingClient.newBuilder(this).enablePendingPurchases().setListener(this).build()
|
||||||
|
binding = ActivitySupportDevBinding.inflate(layoutInflater)
|
||||||
|
|
||||||
|
|
||||||
|
binding.listView.setHasFixedSize(true)
|
||||||
|
val mLayoutManager = LinearLayoutManager(this)
|
||||||
|
binding.listView.layoutManager = mLayoutManager
|
||||||
|
|
||||||
|
adapter = SlimAdapter.create()
|
||||||
|
adapter
|
||||||
|
.register<SkuDetails>(R.layout.inapp_product_layout) { item, injector ->
|
||||||
|
item.sku
|
||||||
|
injector
|
||||||
|
.with<TextView>(R.id.product_title) {
|
||||||
|
it.text = when (item.sku) {
|
||||||
|
"donation_coffee" -> getString(R.string.donation_coffee)
|
||||||
|
"donation_donuts" -> getString(R.string.donation_donuts)
|
||||||
|
"donation_breakfast" -> getString(R.string.donation_breakfast)
|
||||||
|
"donation_lunch" -> getString(R.string.donation_lunch)
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.text(R.id.product_price, item.price)
|
||||||
|
.clicked(R.id.item) {
|
||||||
|
viewModel.purchase(this, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.attachTo(binding.listView)
|
||||||
|
|
||||||
|
viewModel.openConnection()
|
||||||
|
subscribeUi(viewModel)
|
||||||
|
|
||||||
|
binding.actionBack.setOnClickListener {
|
||||||
|
onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
setContentView(binding.root)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun subscribeUi(viewModel: SupportDevViewModel) {
|
||||||
|
viewModel.products.observe(this, Observer {
|
||||||
|
if (it.isNotEmpty()) {
|
||||||
|
binding.loader.isVisible = false
|
||||||
|
}
|
||||||
|
adapter.updateData(it.sortedWith(compareBy(SkuDetails::getPriceAmountMicros)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
|
||||||
|
if (billingResult.responseCode == OK && purchases != null) {
|
||||||
|
for (purchase in purchases) {
|
||||||
|
if (purchase.purchaseState == Purchase.PurchaseState.PURCHASED) {
|
||||||
|
viewModel.handlePurchase(purchase)
|
||||||
|
toast(getString(R.string.thanks))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (billingResult.responseCode == USER_CANCELED) {
|
||||||
|
// DO nothing
|
||||||
|
} else {
|
||||||
|
toast(getString(R.string.error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun onDestroy() {
|
||||||
|
viewModel.closeConnection()
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,6 @@ import com.google.android.material.card.MaterialCardView
|
|||||||
import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding
|
import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.tabs.ChooseApplicationViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.tabs.ChooseApplicationViewModel
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import net.idik.lib.slimadapter.SlimAdapter
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
@ -172,18 +171,6 @@ class ChooseApplicationActivity : AppCompatActivity() {
|
|||||||
list.filter {
|
list.filter {
|
||||||
it.loadLabel(viewModel.pm).contains(search, true)
|
it.loadLabel(viewModel.pm).contains(search, true)
|
||||||
}
|
}
|
||||||
}.sortedWith { app1, app2 ->
|
|
||||||
when (selectedPackage) {
|
|
||||||
app1.activityInfo.packageName -> {
|
|
||||||
-1
|
|
||||||
}
|
|
||||||
app2.activityInfo.packageName -> {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
app1.loadLabel(viewModel.pm).toString().compareTo(app2.loadLabel(viewModel.pm).toString(), ignoreCase = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
adapter.updateData(listOf(IntentHelper.DO_NOTHING_OPTION, IntentHelper.DEFAULT_OPTION, IntentHelper.REFRESH_WIDGET_OPTION) + filteredList)
|
adapter.updateData(listOf(IntentHelper.DO_NOTHING_OPTION, IntentHelper.DEFAULT_OPTION, IntentHelper.REFRESH_WIDGET_OPTION) + filteredList)
|
||||||
|
@ -169,7 +169,6 @@ class CustomDateActivity : AppCompatActivity() {
|
|||||||
isDateCapitalize = viewModel.isDateCapitalize.value ?: true
|
isDateCapitalize = viewModel.isDateCapitalize.value ?: true
|
||||||
isDateUppercase = viewModel.isDateUppercase.value ?: false
|
isDateUppercase = viewModel.isDateUppercase.value ?: false
|
||||||
}
|
}
|
||||||
com.tommasoberlose.anotherwidget.ui.widgets.MainWidget.updateWidget(this)
|
|
||||||
super.onBackPressed()
|
super.onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,15 +38,12 @@ class CustomFontActivity : AppCompatActivity() {
|
|||||||
private lateinit var adapter: SlimAdapter
|
private lateinit var adapter: SlimAdapter
|
||||||
private lateinit var viewModel: CustomFontViewModel
|
private lateinit var viewModel: CustomFontViewModel
|
||||||
private lateinit var binding: ActivityCustomFontBinding
|
private lateinit var binding: ActivityCustomFontBinding
|
||||||
private lateinit var handlerThread: HandlerThread
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
viewModel = ViewModelProvider(this).get(CustomFontViewModel::class.java)
|
viewModel = ViewModelProvider(this).get(CustomFontViewModel::class.java)
|
||||||
binding = ActivityCustomFontBinding.inflate(layoutInflater)
|
binding = ActivityCustomFontBinding.inflate(layoutInflater)
|
||||||
handlerThread = HandlerThread("listCustomFonts")
|
|
||||||
handlerThread.start()
|
|
||||||
|
|
||||||
binding.listView.setHasFixedSize(true)
|
binding.listView.setHasFixedSize(true)
|
||||||
val mLayoutManager = LinearLayoutManager(this)
|
val mLayoutManager = LinearLayoutManager(this)
|
||||||
@ -67,17 +64,14 @@ class CustomFontActivity : AppCompatActivity() {
|
|||||||
injector
|
injector
|
||||||
.text(R.id.text, item)
|
.text(R.id.text, item)
|
||||||
.with<TextView>(R.id.text) {
|
.with<TextView>(R.id.text) {
|
||||||
val googleSans: Typeface? = androidx.core.content.res.ResourcesCompat.getFont(
|
val googleSans: Typeface = when (Preferences.customFontVariant) {
|
||||||
this,
|
"100" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_thin.ttf")
|
||||||
when (Preferences.customFontVariant) {
|
"200" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_light.ttf")
|
||||||
"100" -> R.font.google_sans_thin
|
"500" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_medium.ttf")
|
||||||
"200" -> R.font.google_sans_light
|
"700" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_bold.ttf")
|
||||||
"500" -> R.font.google_sans_medium
|
"800" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_black.ttf")
|
||||||
"700" -> R.font.google_sans_bold
|
else -> Typeface.createFromAsset(this.assets, "fonts/google_sans_regular.ttf")
|
||||||
"800" -> R.font.google_sans_black
|
}
|
||||||
else -> R.font.google_sans_regular
|
|
||||||
}
|
|
||||||
)
|
|
||||||
it.typeface = googleSans
|
it.typeface = googleSans
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,49 +97,32 @@ class CustomFontActivity : AppCompatActivity() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Callback : FontsContractCompat.FontRequestCallback() {
|
val callback = object : FontsContractCompat.FontRequestCallback() {
|
||||||
var handler: Handler? = Handler(handlerThread.looper)
|
|
||||||
|
|
||||||
fun cancel() {
|
|
||||||
if (handler != null) {
|
|
||||||
handler!!.removeCallbacksAndMessages(null)
|
|
||||||
handler = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun finalize() {
|
|
||||||
cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTypefaceRetrieved(typeface: Typeface) {
|
override fun onTypefaceRetrieved(typeface: Typeface) {
|
||||||
if (it.tag == this) {
|
it.typeface = typeface
|
||||||
it.tag = null
|
it.isVisible = true
|
||||||
it.typeface = typeface
|
|
||||||
it.setTextColor(getColor(R.color.colorPrimaryText))
|
it.measure(
|
||||||
}
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTypefaceRequestFailed(reason: Int) {
|
override fun onTypefaceRequestFailed(reason: Int) {
|
||||||
if (it.tag == this) {
|
it.isVisible = false
|
||||||
it.tag = null
|
it.layoutParams = it.layoutParams.apply {
|
||||||
//it.text = item.fontFamily + " ($reason)"
|
height = 0
|
||||||
it.setTextColor(getColor(R.color.errorColorText))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(it.tag as Callback?)?.cancel()
|
val handlerThread = HandlerThread(item.fontFamily)
|
||||||
val callback = Callback()
|
handlerThread.start()
|
||||||
it.tag = callback
|
val mHandler = Handler(handlerThread.looper)
|
||||||
it.typeface = null
|
|
||||||
it.setTextColor(getColor(R.color.colorSecondaryText))
|
|
||||||
|
|
||||||
val mHandler = callback.handler!!
|
|
||||||
FontsContractCompat.requestFont(this, request, callback, mHandler)
|
FontsContractCompat.requestFont(this, request, callback, mHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
injector.clicked(R.id.text) {
|
injector.clicked(R.id.text) {
|
||||||
if ((it as TextView).typeface == null) return@clicked
|
|
||||||
val dialog = BottomSheetMenu<Int>(this, header = item.fontFamily)
|
val dialog = BottomSheetMenu<Int>(this, header = item.fontFamily)
|
||||||
if (item.fontVariants.isEmpty()) {
|
if (item.fontVariants.isEmpty()) {
|
||||||
dialog.addItem(SettingsStringHelper.getVariantLabel(this, "regular"), -1)
|
dialog.addItem(SettingsStringHelper.getVariantLabel(this, "regular"), -1)
|
||||||
@ -170,12 +147,6 @@ class CustomFontActivity : AppCompatActivity() {
|
|||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
handlerThread.quit()
|
|
||||||
filterJob?.cancel()
|
|
||||||
super.onDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
private var filterJob: Job? = null
|
private var filterJob: Job? = null
|
||||||
|
|
||||||
private fun subscribeUi(binding: ActivityCustomFontBinding, viewModel: CustomFontViewModel) {
|
private fun subscribeUi(binding: ActivityCustomFontBinding, viewModel: CustomFontViewModel) {
|
||||||
@ -233,13 +204,6 @@ class CustomFontActivity : AppCompatActivity() {
|
|||||||
adapter.updateData(filteredList)
|
adapter.updateData(filteredList)
|
||||||
binding.loader.visibility = View.INVISIBLE
|
binding.loader.visibility = View.INVISIBLE
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
delay(200)
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
adapter.updateData(listOf(getString(R.string.custom_font_subtitle_1)).filter {
|
|
||||||
it.contains(search ?: "", ignoreCase = true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import android.app.Activity
|
|||||||
import android.location.Address
|
import android.location.Address
|
||||||
import android.location.Geocoder
|
import android.location.Geocoder
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
@ -46,27 +45,22 @@ class CustomLocationActivity : AppCompatActivity() {
|
|||||||
adapter = SlimAdapter.create()
|
adapter = SlimAdapter.create()
|
||||||
adapter
|
adapter
|
||||||
.register<String>(R.layout.custom_location_item) { _, injector ->
|
.register<String>(R.layout.custom_location_item) { _, injector ->
|
||||||
injector.text(R.id.text, getString(R.string.custom_location_gps))
|
injector
|
||||||
injector.clicked(R.id.text) {
|
.text(R.id.text, getString(R.string.custom_location_gps))
|
||||||
Preferences.bulk {
|
.clicked(R.id.text) {
|
||||||
remove(Preferences::customLocationLat)
|
requirePermission()
|
||||||
remove(Preferences::customLocationLon)
|
|
||||||
remove(Preferences::customLocationAdd)
|
|
||||||
}
|
}
|
||||||
setResult(Activity.RESULT_OK)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.register<Address>(R.layout.custom_location_item) { item, injector ->
|
.register<Address>(R.layout.custom_location_item) { item, injector ->
|
||||||
injector.text(R.id.text, item.getAddressLine(0) ?: "")
|
injector.text(R.id.text, item.getAddressLine(0))
|
||||||
injector.clicked(R.id.item) {
|
injector.clicked(R.id.item) {
|
||||||
Preferences.bulk {
|
Preferences.bulk {
|
||||||
customLocationLat = item.latitude.toString()
|
customLocationLat = item.latitude.toString()
|
||||||
customLocationLon = item.longitude.toString()
|
customLocationLon = item.longitude.toString()
|
||||||
customLocationAdd = item.getAddressLine(0) ?: ""
|
customLocationAdd = item.getAddressLine(0)
|
||||||
|
setResult(Activity.RESULT_OK)
|
||||||
|
finish()
|
||||||
}
|
}
|
||||||
setResult(Activity.RESULT_OK)
|
|
||||||
finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.attachTo(binding.listView)
|
.attachTo(binding.listView)
|
||||||
@ -120,6 +114,36 @@ class CustomLocationActivity : AppCompatActivity() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun requirePermission() {
|
||||||
|
Dexter.withContext(this)
|
||||||
|
.withPermissions(
|
||||||
|
Manifest.permission.ACCESS_FINE_LOCATION
|
||||||
|
).withListener(object: MultiplePermissionsListener {
|
||||||
|
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
||||||
|
report?.let {
|
||||||
|
if (report.areAllPermissionsGranted()){
|
||||||
|
Preferences.bulk {
|
||||||
|
remove(Preferences::customLocationLat)
|
||||||
|
remove(Preferences::customLocationLon)
|
||||||
|
remove(Preferences::customLocationAdd)
|
||||||
|
}
|
||||||
|
setResult(Activity.RESULT_OK)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override fun onPermissionRationaleShouldBeShown(
|
||||||
|
permissions: MutableList<PermissionRequest>?,
|
||||||
|
token: PermissionToken?
|
||||||
|
) {
|
||||||
|
// Remember to invoke this method when the custom rationale is closed
|
||||||
|
// or just by default if you don't want to use any custom rationale.
|
||||||
|
token?.continuePermissionRequest()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.check()
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
binding.actionBack.setOnClickListener {
|
binding.actionBack.setOnClickListener {
|
||||||
onBackPressed()
|
onBackPressed()
|
||||||
|
@ -1,155 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.activities.tabs
|
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.app.Activity
|
|
||||||
import android.location.Address
|
|
||||||
import android.location.Geocoder
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.text.method.LinkMovementMethod
|
|
||||||
import android.view.View
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import com.chibatching.kotpref.bulk
|
|
||||||
import com.karumi.dexter.Dexter
|
|
||||||
import com.karumi.dexter.MultiplePermissionsReport
|
|
||||||
import com.karumi.dexter.PermissionToken
|
|
||||||
import com.karumi.dexter.listener.PermissionRequest
|
|
||||||
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
|
|
||||||
import com.tommasoberlose.anotherwidget.R
|
|
||||||
import com.tommasoberlose.anotherwidget.databinding.ActivityTimeZoneSelectorBinding
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
import com.tommasoberlose.anotherwidget.network.TimeZonesApi
|
|
||||||
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.tabs.TimeZoneSelectorViewModel
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.toast
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import net.idik.lib.slimadapter.SlimAdapter
|
|
||||||
|
|
||||||
class TimeZoneSelectorActivity : AppCompatActivity() {
|
|
||||||
|
|
||||||
private lateinit var adapter: SlimAdapter
|
|
||||||
private lateinit var viewModel: TimeZoneSelectorViewModel
|
|
||||||
private lateinit var binding: ActivityTimeZoneSelectorBinding
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
viewModel = ViewModelProvider(this).get(TimeZoneSelectorViewModel::class.java)
|
|
||||||
binding = ActivityTimeZoneSelectorBinding.inflate(layoutInflater)
|
|
||||||
|
|
||||||
binding.geonameCredits.movementMethod = LinkMovementMethod.getInstance()
|
|
||||||
|
|
||||||
binding.listView.setHasFixedSize(true)
|
|
||||||
val mLayoutManager = LinearLayoutManager(this)
|
|
||||||
binding.listView.layoutManager = mLayoutManager
|
|
||||||
|
|
||||||
adapter = SlimAdapter.create()
|
|
||||||
adapter
|
|
||||||
.register<String>(R.layout.custom_location_item) { _, injector ->
|
|
||||||
injector
|
|
||||||
.text(R.id.text, getString(R.string.no_time_zone_label))
|
|
||||||
.clicked(R.id.text) {
|
|
||||||
Preferences.bulk {
|
|
||||||
altTimezoneId = ""
|
|
||||||
altTimezoneLabel = ""
|
|
||||||
}
|
|
||||||
MainWidget.updateWidget(this@TimeZoneSelectorActivity)
|
|
||||||
setResult(Activity.RESULT_OK)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.register<Address>(R.layout.custom_location_item) { item, injector ->
|
|
||||||
injector.text(R.id.text, item.getAddressLine(0))
|
|
||||||
injector.clicked(R.id.item) {
|
|
||||||
binding.loader.visibility = View.VISIBLE
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
|
||||||
val networkApi = TimeZonesApi(this@TimeZoneSelectorActivity)
|
|
||||||
val id = networkApi.getTimeZone(item.latitude.toString(), item.longitude.toString())
|
|
||||||
|
|
||||||
if (id != null) {
|
|
||||||
Preferences.bulk {
|
|
||||||
altTimezoneId = id
|
|
||||||
altTimezoneLabel = try {
|
|
||||||
item.locality
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
item.getAddressLine(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MainWidget.updateWidget(this@TimeZoneSelectorActivity)
|
|
||||||
setResult(Activity.RESULT_OK)
|
|
||||||
finish()
|
|
||||||
} else {
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
binding.loader.visibility = View.INVISIBLE
|
|
||||||
toast(getString(R.string.time_zone_search_error_message))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.attachTo(binding.listView)
|
|
||||||
|
|
||||||
|
|
||||||
viewModel.addresses.observe(this, Observer {
|
|
||||||
adapter.updateData(listOf("Default") + it)
|
|
||||||
})
|
|
||||||
|
|
||||||
setupListener()
|
|
||||||
subscribeUi(binding, viewModel)
|
|
||||||
|
|
||||||
binding.location.requestFocus()
|
|
||||||
|
|
||||||
setContentView(binding.root)
|
|
||||||
}
|
|
||||||
|
|
||||||
private var searchJob: Job? = null
|
|
||||||
|
|
||||||
private fun subscribeUi(binding: ActivityTimeZoneSelectorBinding, viewModel: TimeZoneSelectorViewModel) {
|
|
||||||
binding.viewModel = viewModel
|
|
||||||
binding.lifecycleOwner = this
|
|
||||||
|
|
||||||
viewModel.addresses.observe(this, Observer {
|
|
||||||
adapter.updateData(listOf("Default") + it)
|
|
||||||
binding.loader.visibility = View.INVISIBLE
|
|
||||||
})
|
|
||||||
|
|
||||||
viewModel.locationInput.observe(this, Observer { location ->
|
|
||||||
binding.loader.visibility = View.VISIBLE
|
|
||||||
searchJob?.cancel()
|
|
||||||
searchJob = lifecycleScope.launch(Dispatchers.IO) {
|
|
||||||
delay(200)
|
|
||||||
val list = if (location == null || location == "") {
|
|
||||||
viewModel.addresses.value!!
|
|
||||||
} else {
|
|
||||||
val coder = Geocoder(this@TimeZoneSelectorActivity)
|
|
||||||
try {
|
|
||||||
coder.getFromLocationName(location, 10) as ArrayList<Address>
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
emptyList<Address>()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
viewModel.addresses.value = list
|
|
||||||
binding.loader.visibility = View.INVISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
binding.clearSearch.isVisible = location.isNotBlank()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupListener() {
|
|
||||||
binding.actionBack.setOnClickListener {
|
|
||||||
onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.clearSearch.setOnClickListener {
|
|
||||||
viewModel.locationInput.value = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -47,32 +47,36 @@ class WeatherProviderActivity : AppCompatActivity() {
|
|||||||
injector
|
injector
|
||||||
.text(R.id.text, WeatherHelper.getProviderName(this, provider))
|
.text(R.id.text, WeatherHelper.getProviderName(this, provider))
|
||||||
.clicked(R.id.item) {
|
.clicked(R.id.item) {
|
||||||
if (Preferences.weatherProvider != provider.rawValue) {
|
if (Preferences.weatherProvider != provider.value) {
|
||||||
Preferences.weatherProviderError = "-"
|
Preferences.weatherProviderError = "-"
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
}
|
}
|
||||||
val oldValue = Preferences.weatherProvider
|
val oldValue = Preferences.weatherProvider
|
||||||
Preferences.weatherProvider = provider.rawValue
|
Preferences.weatherProvider = provider.value
|
||||||
updateListItem(oldValue)
|
updateListItem(oldValue)
|
||||||
updateListItem()
|
updateListItem()
|
||||||
binding.loader.isVisible = true
|
binding.loader.isVisible = true
|
||||||
|
|
||||||
WeatherHelper.updateWeather(this@WeatherProviderActivity, true)
|
lifecycleScope.launch {
|
||||||
|
WeatherHelper.updateWeather(this@WeatherProviderActivity)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.clicked(R.id.radioButton) {
|
.clicked(R.id.radioButton) {
|
||||||
if (Preferences.weatherProvider != provider.rawValue) {
|
if (Preferences.weatherProvider != provider.value) {
|
||||||
Preferences.weatherProviderError = "-"
|
Preferences.weatherProviderError = "-"
|
||||||
Preferences.weatherProviderLocationError = ""
|
Preferences.weatherProviderLocationError = ""
|
||||||
}
|
}
|
||||||
val oldValue = Preferences.weatherProvider
|
val oldValue = Preferences.weatherProvider
|
||||||
Preferences.weatherProvider = provider.rawValue
|
Preferences.weatherProvider = provider.value
|
||||||
updateListItem(oldValue)
|
updateListItem(oldValue)
|
||||||
updateListItem()
|
updateListItem()
|
||||||
binding.loader.isVisible = true
|
binding.loader.isVisible = true
|
||||||
|
|
||||||
WeatherHelper.updateWeather(this@WeatherProviderActivity, true)
|
lifecycleScope.launch {
|
||||||
|
WeatherHelper.updateWeather(this@WeatherProviderActivity)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.checked(R.id.radioButton, provider.rawValue == Preferences.weatherProvider)
|
.checked(R.id.radioButton, provider.value == Preferences.weatherProvider)
|
||||||
.with<TextView>(R.id.text2) {
|
.with<TextView>(R.id.text2) {
|
||||||
if (WeatherHelper.isKeyRequired(provider)) {
|
if (WeatherHelper.isKeyRequired(provider)) {
|
||||||
it.text = getString(R.string.api_key_required_message)
|
it.text = getString(R.string.api_key_required_message)
|
||||||
@ -88,18 +92,20 @@ class WeatherProviderActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
.clicked(R.id.action_configure) {
|
.clicked(R.id.action_configure) {
|
||||||
BottomSheetWeatherProviderSettings(this) {
|
BottomSheetWeatherProviderSettings(this) {
|
||||||
binding.loader.isVisible = true
|
lifecycleScope.launch {
|
||||||
WeatherHelper.updateWeather(this@WeatherProviderActivity, true)
|
binding.loader.isVisible = true
|
||||||
|
WeatherHelper.updateWeather(this@WeatherProviderActivity)
|
||||||
|
}
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
.visibility(R.id.action_configure, if (/*WeatherHelper.isKeyRequired(provider) && */provider.rawValue == Preferences.weatherProvider) View.VISIBLE else View.GONE)
|
.visibility(R.id.action_configure, if (/*WeatherHelper.isKeyRequired(provider) && */provider.value == Preferences.weatherProvider) View.VISIBLE else View.GONE)
|
||||||
.with<TextView>(R.id.provider_error) {
|
.with<TextView>(R.id.provider_error) {
|
||||||
if (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-") {
|
if (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-") {
|
||||||
it.text = Preferences.weatherProviderError
|
it.text = Preferences.weatherProviderError
|
||||||
it.isVisible = provider.rawValue == Preferences.weatherProvider
|
it.isVisible = provider.value == Preferences.weatherProvider
|
||||||
} else if (Preferences.weatherProviderLocationError != "") {
|
} else if (Preferences.weatherProviderLocationError != "") {
|
||||||
it.text = Preferences.weatherProviderLocationError
|
it.text = Preferences.weatherProviderLocationError
|
||||||
it.isVisible = provider.rawValue == Preferences.weatherProvider
|
it.isVisible = provider.value == Preferences.weatherProvider
|
||||||
} else {
|
} else {
|
||||||
it.isVisible = false
|
it.isVisible = false
|
||||||
}
|
}
|
||||||
@ -109,6 +115,8 @@ class WeatherProviderActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
adapter.updateData(
|
adapter.updateData(
|
||||||
Constants.WeatherProvider.values().asList()
|
Constants.WeatherProvider.values().asList()
|
||||||
|
.filter { it != Constants.WeatherProvider.HERE }
|
||||||
|
.filter { it != Constants.WeatherProvider.ACCUWEATHER }
|
||||||
)
|
)
|
||||||
|
|
||||||
setupListener()
|
setupListener()
|
||||||
@ -119,17 +127,17 @@ class WeatherProviderActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun subscribeUi(viewModel: WeatherProviderViewModel) {
|
private fun subscribeUi(viewModel: WeatherProviderViewModel) {
|
||||||
viewModel.weatherProviderError.observe(this) {
|
viewModel.weatherProviderError.observe(this) {
|
||||||
binding.listView.postDelayed({ updateListItem() }, 300)
|
updateListItem()
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.weatherProviderLocationError.observe(this) {
|
viewModel.weatherProviderLocationError.observe(this) {
|
||||||
binding.listView.postDelayed({ updateListItem() }, 300)
|
updateListItem()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateListItem(provider: Int = Preferences.weatherProvider) {
|
private fun updateListItem(provider: Int = Preferences.weatherProvider) {
|
||||||
(adapter.data).forEachIndexed { index, item ->
|
(adapter.data).forEachIndexed { index, item ->
|
||||||
if (item is Constants.WeatherProvider && item.rawValue == provider) {
|
if (item is Constants.WeatherProvider && item.value == provider) {
|
||||||
adapter.notifyItemChanged(index)
|
adapter.notifyItemChanged(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,7 +165,7 @@ class WeatherProviderActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onMessageEvent(@Suppress("UNUSED_PARAMETER") ignore: MainFragment.UpdateUiMessageEvent?) {
|
fun onMessageEvent(ignore: MainFragment.UpdateUiMessageEvent?) {
|
||||||
binding.loader.isVisible = Preferences.weatherProviderError == "-"
|
binding.loader.isVisible = Preferences.weatherProviderError == "-"
|
||||||
if (Preferences.weatherProviderError == "" && Preferences.weatherProviderLocationError == "") {
|
if (Preferences.weatherProviderError == "" && Preferences.weatherProviderLocationError == "") {
|
||||||
Snackbar.make(binding.listView, getString(R.string.settings_weather_provider_api_key_subtitle_all_set), Snackbar.LENGTH_LONG).show()
|
Snackbar.make(binding.listView, getString(R.string.settings_weather_provider_api_key_subtitle_all_set), Snackbar.LENGTH_LONG).show()
|
||||||
|
@ -1,23 +1,36 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.fragments
|
package com.tommasoberlose.anotherwidget.ui.fragments
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.SharedPreferences
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.util.TypedValue
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.RemoteViews
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.RelativeLayout
|
||||||
|
import androidx.core.animation.addListener
|
||||||
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.navigation.NavController
|
||||||
import androidx.navigation.Navigation
|
import androidx.navigation.Navigation
|
||||||
|
import androidx.navigation.fragment.FragmentNavigatorExtras
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
|
import com.google.android.material.badge.BadgeDrawable
|
||||||
|
import com.google.android.material.card.MaterialCardView
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
|
import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
|
||||||
@ -25,7 +38,10 @@ import com.tommasoberlose.anotherwidget.databinding.FragmentAppMainBinding
|
|||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.helpers.*
|
import com.tommasoberlose.anotherwidget.helpers.*
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import com.tommasoberlose.anotherwidget.utils.*
|
import com.tommasoberlose.anotherwidget.utils.*
|
||||||
@ -34,11 +50,11 @@ import org.greenrobot.eventbus.EventBus
|
|||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
|
|
||||||
|
|
||||||
class MainFragment : Fragment() {
|
class MainFragment : Fragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance() = MainFragment()
|
fun newInstance() = MainFragment()
|
||||||
|
private const val PREVIEW_BASE_HEIGHT = 120
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var viewModel: MainViewModel
|
private lateinit var viewModel: MainViewModel
|
||||||
@ -78,20 +94,21 @@ class MainFragment : Fragment() {
|
|||||||
navHost?.navController?.addOnDestinationChangedListener { controller, destination, _ ->
|
navHost?.navController?.addOnDestinationChangedListener { controller, destination, _ ->
|
||||||
val show = destination.id != R.id.tabSelectorFragment
|
val show = destination.id != R.id.tabSelectorFragment
|
||||||
binding.actionBack.animate().alpha(if (show) 1f else 0f).setDuration(200).translationX((if (show) 0f else 4f).convertDpToPixel(requireContext())).start()
|
binding.actionBack.animate().alpha(if (show) 1f else 0f).setDuration(200).translationX((if (show) 0f else 4f).convertDpToPixel(requireContext())).start()
|
||||||
binding.actionBack.setOnSingleClickListener {
|
binding.actionBack.setOnClickListener {
|
||||||
controller.navigateUp()
|
controller.navigateUp()
|
||||||
}
|
}
|
||||||
binding.actionBack.isClickable = show
|
|
||||||
binding.actionBack.isFocusable = show
|
|
||||||
binding.actionSettings.animate().alpha(if (!show) 1f else 0f).setDuration(200).translationX((if (!show) 0f else -4f).convertDpToPixel(requireContext())).start()
|
binding.actionSettings.animate().alpha(if (!show) 1f else 0f).setDuration(200).translationX((if (!show) 0f else -4f).convertDpToPixel(requireContext())).start()
|
||||||
binding.actionSettings.isClickable = !show
|
|
||||||
binding.actionSettings.isFocusable = !show
|
|
||||||
binding.fragmentTitle.text = if (show) destination.label.toString() else getString(R.string.app_name)
|
binding.fragmentTitle.text = if (show) destination.label.toString() else getString(R.string.app_name)
|
||||||
binding.toolbar.cardElevation = 0f
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionSettings.setOnSingleClickListener {
|
binding.actionSettings.setOnClickListener {
|
||||||
Navigation.findNavController(it).navigate(R.id.action_appMainFragment_to_appSettingsFragment)
|
Navigation.findNavController(it).navigate(R.id.action_appMainFragment_to_appSettingsFragment,)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.preview.layoutParams = binding.preview.layoutParams.apply {
|
||||||
|
height = PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||||
|
requireContext()
|
||||||
|
) else 0
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribeUi(viewModel)
|
subscribeUi(viewModel)
|
||||||
@ -140,76 +157,165 @@ class MainFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.fragmentScrollY.observe(viewLifecycleOwner) {
|
viewModel.fragmentScrollY.observe(viewLifecycleOwner) {
|
||||||
binding.toolbar.cardElevation = if (it > 0) 32f else 0f
|
binding.toolbar.cardElevation = if (it > 0) 24f else 0f
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.showPreview.observe(viewLifecycleOwner) {
|
viewModel.showPreview.observe(viewLifecycleOwner) {
|
||||||
binding.preview.isVisible = it
|
updatePreviewVisibility()
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.clockPreferencesUpdate.observe(viewLifecycleOwner) {
|
||||||
|
updateClock()
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.widgetPreferencesUpdate.observe(viewLifecycleOwner) {
|
viewModel.widgetPreferencesUpdate.observe(viewLifecycleOwner) {
|
||||||
onUpdateUiEvent(null)
|
onUpdateUiEvent(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel.showClock.observe(viewLifecycleOwner) {
|
||||||
|
updateClockVisibility(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var uiJob: Job? = null
|
private var uiJob: Job? = null
|
||||||
|
|
||||||
private fun updateUI() {
|
private fun updateUI() {
|
||||||
|
uiJob?.cancel()
|
||||||
|
|
||||||
if (Preferences.showPreview) {
|
if (Preferences.showPreview) {
|
||||||
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
val bgColor: Int = ContextCompat.getColor(
|
||||||
|
requireContext(),
|
||||||
|
if (ColorHelper.getFontColor(requireActivity().isDarkTheme())
|
||||||
|
.isColorDark()
|
||||||
|
) android.R.color.white else R.color.colorAccent
|
||||||
|
)
|
||||||
|
|
||||||
|
val wallpaperDrawable = BitmapHelper.getTintedDrawable(
|
||||||
|
requireContext(),
|
||||||
|
R.drawable.card_background,
|
||||||
|
ColorHelper.getBackgroundColor(requireActivity().isDarkTheme())
|
||||||
|
)
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
binding.preview.setCardBackgroundColor(bgColor)
|
||||||
|
binding.widgetDetail.widgetShapeBackground.setImageDrawable(wallpaperDrawable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WidgetHelper.runWithCustomTypeface(requireContext()) { typeface ->
|
WidgetHelper.runWithCustomTypeface(requireContext()) { typeface ->
|
||||||
uiJob?.cancel()
|
|
||||||
uiJob = lifecycleScope.launch(Dispatchers.IO) {
|
uiJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||||
val generatedView = MainWidget.getWidgetView(
|
val generatedView = MainWidget.generateWidgetView(requireContext(), typeface).root
|
||||||
requireContext(),
|
|
||||||
binding.widget.width - binding.widget.paddingStart - binding.widget.paddingEnd,
|
withContext(Dispatchers.Main) {
|
||||||
typeface
|
generatedView.measure(0, 0)
|
||||||
|
binding.preview.measure(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
val bitmap = BitmapHelper.getBitmapFromView(
|
||||||
|
generatedView,
|
||||||
|
if (binding.preview.width > 0) binding.preview.width else generatedView.measuredWidth,
|
||||||
|
generatedView.measuredHeight
|
||||||
)
|
)
|
||||||
|
|
||||||
if (generatedView != null) {
|
withContext(Dispatchers.Main) {
|
||||||
withContext(Dispatchers.Main) {
|
binding.widgetDetail.bitmapContainer.apply {
|
||||||
val view: View = generatedView.apply(requireActivity().applicationContext, binding.widget)
|
setImageBitmap(bitmap)
|
||||||
view.measure(0, 0)
|
|
||||||
|
|
||||||
binding.widgetLoader.animate().alpha(0f).setDuration(200L).start()
|
|
||||||
binding.widget.animate().alpha(0f).setDuration(200L).withEndAction {
|
|
||||||
updatePreviewVisibility(view.measuredHeight)
|
|
||||||
binding.widget.removeAllViews()
|
|
||||||
binding.widget.addView(view)
|
|
||||||
|
|
||||||
binding.widget.animate().setStartDelay(300L).alpha(1f).start()
|
|
||||||
}.start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.widgetLoader.animate().scaleX(0f).scaleY(0f).alpha(0f)
|
||||||
|
.setDuration(200L).start()
|
||||||
|
binding.widget.animate().alpha(1f).start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePreviewVisibility(widgetHeight: Int) {
|
private fun updateClock() {
|
||||||
if (isAdded) {
|
// Clock
|
||||||
val newHeight = widgetHeight + 32f.convertDpToPixel(requireContext()).toInt()
|
binding.widgetDetail.time.setTextColor(ColorHelper.getClockFontColor(requireActivity().isDarkTheme()))
|
||||||
if (binding.preview.layoutParams.height != newHeight) {
|
binding.widgetDetail.timeAmPm.setTextColor(ColorHelper.getClockFontColor(requireActivity().isDarkTheme()))
|
||||||
binding.preview.clearAnimation()
|
binding.widgetDetail.time.setTextSize(
|
||||||
ValueAnimator.ofInt(
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
binding.preview.height,
|
Preferences.clockTextSize.toPixel(requireContext())
|
||||||
newHeight
|
)
|
||||||
).apply {
|
binding.widgetDetail.timeAmPm.setTextSize(
|
||||||
duration = 300L
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
addUpdateListener {
|
Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2
|
||||||
val animatedValue = animatedValue as Int
|
)
|
||||||
val layoutParams = binding.preview.layoutParams
|
binding.widgetDetail.timeAmPm.isVisible = Preferences.showAMPMIndicator
|
||||||
layoutParams.height = animatedValue
|
|
||||||
binding.preview.layoutParams = layoutParams
|
// Clock bottom margin
|
||||||
}
|
binding.widgetDetail.clockBottomMarginNone.isVisible =
|
||||||
}.start()
|
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value
|
||||||
|
binding.widgetDetail.clockBottomMarginSmall.isVisible =
|
||||||
|
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value
|
||||||
|
binding.widgetDetail.clockBottomMarginMedium.isVisible =
|
||||||
|
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value
|
||||||
|
binding.widgetDetail.clockBottomMarginLarge.isVisible =
|
||||||
|
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateClockVisibility(showClock: Boolean) {
|
||||||
|
binding.widgetDetail.timeContainer.clearAnimation()
|
||||||
|
binding.widgetDetail.time.clearAnimation()
|
||||||
|
|
||||||
|
updatePreviewVisibility()
|
||||||
|
|
||||||
|
if (showClock) {
|
||||||
|
binding.widgetDetail.timeContainer.layoutParams = binding.widgetDetail.timeContainer.layoutParams.apply {
|
||||||
|
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||||
}
|
}
|
||||||
|
binding.widgetDetail.timeContainer.measure(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Preferences.showClock && binding.widgetDetail.time.alpha != 1f) || (!Preferences.showClock && binding.widgetDetail.time.alpha != 0f)) {
|
||||||
|
val initialHeight = binding.widgetDetail.timeContainer.measuredHeight
|
||||||
|
ValueAnimator.ofFloat(
|
||||||
|
if (showClock) 0f else 1f,
|
||||||
|
if (showClock) 1f else 0f
|
||||||
|
).apply {
|
||||||
|
duration = 300L
|
||||||
|
addUpdateListener {
|
||||||
|
val animatedValue = animatedValue as Float
|
||||||
|
binding.widgetDetail.timeContainer.layoutParams =
|
||||||
|
binding.widgetDetail.timeContainer.layoutParams.apply {
|
||||||
|
height = (initialHeight * animatedValue).toInt()
|
||||||
|
}
|
||||||
|
binding.widgetDetail.time.alpha = animatedValue
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updatePreviewVisibility() {
|
||||||
|
binding.preview.clearAnimation()
|
||||||
|
if (binding.preview.layoutParams.height != (if (Preferences.showPreview) PREVIEW_BASE_HEIGHT.toPixel(requireContext()) else 0) + (if (Preferences.showClock) 100.toPixel(
|
||||||
|
requireContext()
|
||||||
|
) else 0)) {
|
||||||
|
ValueAnimator.ofInt(
|
||||||
|
binding.preview.height,
|
||||||
|
(if (Preferences.showPreview) PREVIEW_BASE_HEIGHT.toPixel(requireContext()) else 0) + (if (Preferences.showClock) 100.toPixel(
|
||||||
|
requireContext()
|
||||||
|
) else 0)
|
||||||
|
).apply {
|
||||||
|
duration = 300L
|
||||||
|
addUpdateListener {
|
||||||
|
val animatedValue = animatedValue as Int
|
||||||
|
val layoutParams = binding.preview.layoutParams
|
||||||
|
layoutParams.height = animatedValue
|
||||||
|
binding.preview.layoutParams = layoutParams
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
EventBus.getDefault().register(this)
|
EventBus.getDefault().register(this)
|
||||||
// updateUI()
|
updateUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
@ -223,7 +329,7 @@ class MainFragment : Fragment() {
|
|||||||
class ChangeTabEvent(val page: Int)
|
class ChangeTabEvent(val page: Int)
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onUpdateUiEvent(@Suppress("UNUSED_PARAMETER") ignore: UpdateUiMessageEvent?) {
|
fun onUpdateUiEvent(ignore: UpdateUiMessageEvent?) {
|
||||||
delayJob?.cancel()
|
delayJob?.cancel()
|
||||||
delayJob = lifecycleScope.launch(Dispatchers.IO) {
|
delayJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||||
delay(300)
|
delay(300)
|
||||||
@ -234,7 +340,7 @@ class MainFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
fun onChangeTabEvent(@Suppress("UNUSED_PARAMETER") ignore: ChangeTabEvent) {
|
fun onChangeTabEvent(ignore: ChangeTabEvent) {
|
||||||
val navHost = childFragmentManager.findFragmentById(R.id.settings_fragment) as? NavHostFragment?
|
val navHost = childFragmentManager.findFragmentById(R.id.settings_fragment) as? NavHostFragment?
|
||||||
navHost?.navController?.navigateUp()
|
navHost?.navController?.navigateUp()
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,13 @@ import android.view.LayoutInflater
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.Navigation
|
import androidx.navigation.Navigation
|
||||||
|
import androidx.transition.TransitionInflater
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import com.karumi.dexter.Dexter
|
import com.karumi.dexter.Dexter
|
||||||
import com.karumi.dexter.MultiplePermissionsReport
|
import com.karumi.dexter.MultiplePermissionsReport
|
||||||
@ -29,10 +32,11 @@ import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
|||||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.settings.IntegrationsActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.settings.IntegrationsActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.settings.SupportDevActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
import com.tommasoberlose.anotherwidget.utils.openURI
|
import com.tommasoberlose.anotherwidget.utils.openURI
|
||||||
import com.tommasoberlose.anotherwidget.utils.setOnSingleClickListener
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@ -72,7 +76,7 @@ class SettingsFragment : Fragment() {
|
|||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
super.onActivityCreated(savedInstanceState)
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
binding.actionBack.setOnSingleClickListener {
|
binding.actionBack.setOnClickListener {
|
||||||
Navigation.findNavController(it).popBackStack()
|
Navigation.findNavController(it).popBackStack()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,18 +195,20 @@ class SettingsFragment : Fragment() {
|
|||||||
requireActivity().openURI("https://github.com/tommasoberlose/another-widget/blob/master/privacy-policy.md")
|
requireActivity().openURI("https://github.com/tommasoberlose/another-widget/blob/master/privacy-policy.md")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.actionHelpDev.setOnClickListener {
|
||||||
|
startActivity(Intent(requireContext(), SupportDevActivity::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
binding.actionRefreshWidget.setOnClickListener {
|
binding.actionRefreshWidget.setOnClickListener {
|
||||||
binding.actionRefreshIcon
|
binding.actionRefreshIcon
|
||||||
.animate()
|
.animate()
|
||||||
.rotation((binding.actionRefreshIcon.rotation - binding.actionRefreshIcon.rotation % 360f) + 360f)
|
.rotation((binding.actionRefreshIcon.rotation - binding.actionRefreshIcon.rotation % 360f) + 360f)
|
||||||
.withEndAction {
|
.withEndAction {
|
||||||
try {
|
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
WeatherHelper.updateWeather(requireContext())
|
WeatherHelper.updateWeather(requireContext())
|
||||||
CalendarHelper.updateEventList(requireContext())
|
CalendarHelper.updateEventList(requireContext())
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
|
MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
|
||||||
ActiveNotificationsHelper.clearLastNotification(requireContext())
|
ActiveNotificationsHelper.clearLastNotification(requireContext())
|
||||||
} catch (ex: Exception) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.start()
|
.start()
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.fragments.tabs
|
package com.tommasoberlose.anotherwidget.ui.fragments.tabs
|
||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.CalendarContract
|
import android.provider.CalendarContract
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.chibatching.kotpref.bulk
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||||
@ -16,15 +21,20 @@ import com.tommasoberlose.anotherwidget.models.CalendarSelector
|
|||||||
import com.tommasoberlose.anotherwidget.databinding.FragmentTabCalendarBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentTabCalendarBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.tabs.ChooseApplicationActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.isDefaultSet
|
||||||
import com.tommasoberlose.anotherwidget.utils.toast
|
import com.tommasoberlose.anotherwidget.utils.toast
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlin.Comparator
|
||||||
|
|
||||||
class CalendarFragment : Fragment() {
|
class CalendarFragment : Fragment() {
|
||||||
|
|
||||||
@ -63,7 +73,6 @@ class CalendarFragment : Fragment() {
|
|||||||
binding.showAllDayToggle.setCheckedImmediatelyNoEvent(Preferences.calendarAllDay)
|
binding.showAllDayToggle.setCheckedImmediatelyNoEvent(Preferences.calendarAllDay)
|
||||||
binding.showOnlyBusyEventsToggle.setCheckedImmediatelyNoEvent(Preferences.showOnlyBusyEvents)
|
binding.showOnlyBusyEventsToggle.setCheckedImmediatelyNoEvent(Preferences.showOnlyBusyEvents)
|
||||||
binding.showDiffTimeToggle.setCheckedImmediatelyNoEvent(Preferences.showDiffTime)
|
binding.showDiffTimeToggle.setCheckedImmediatelyNoEvent(Preferences.showDiffTime)
|
||||||
binding.showNextEventOnMultipleLinesToggle.setCheckedImmediatelyNoEvent(Preferences.showNextEventOnMultipleLines)
|
|
||||||
|
|
||||||
setupListener()
|
setupListener()
|
||||||
|
|
||||||
@ -91,12 +100,6 @@ class CalendarFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.showNextEventOnMultipleLines.observe(viewLifecycleOwner) {
|
|
||||||
maintainScrollPosition {
|
|
||||||
binding.showNextEventOnMultipleLinesLabel.text = if (it) getString(R.string.settings_enabled) else getString(R.string.settings_disabled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.showDiffTime.observe(viewLifecycleOwner) {
|
viewModel.showDiffTime.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.showDiffTimeLabel.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
binding.showDiffTimeLabel.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||||
@ -107,9 +110,9 @@ class CalendarFragment : Fragment() {
|
|||||||
viewModel.widgetUpdateFrequency.observe(viewLifecycleOwner) {
|
viewModel.widgetUpdateFrequency.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.widgetUpdateFrequencyLabel.text = when (it) {
|
binding.widgetUpdateFrequencyLabel.text = when (it) {
|
||||||
Constants.WidgetUpdateFrequency.HIGH.rawValue -> getString(R.string.settings_widget_update_frequency_high)
|
Constants.WidgetUpdateFrequency.HIGH.value -> getString(R.string.settings_widget_update_frequency_high)
|
||||||
Constants.WidgetUpdateFrequency.DEFAULT.rawValue -> getString(R.string.settings_widget_update_frequency_default)
|
Constants.WidgetUpdateFrequency.DEFAULT.value -> getString(R.string.settings_widget_update_frequency_default)
|
||||||
Constants.WidgetUpdateFrequency.LOW.rawValue -> getString(R.string.settings_widget_update_frequency_low)
|
Constants.WidgetUpdateFrequency.LOW.value -> getString(R.string.settings_widget_update_frequency_low)
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,7 +185,7 @@ class CalendarFragment : Fragment() {
|
|||||||
|
|
||||||
binding.showAllDayToggle.setOnCheckedChangeListener { _, isChecked ->
|
binding.showAllDayToggle.setOnCheckedChangeListener { _, isChecked ->
|
||||||
Preferences.calendarAllDay = isChecked
|
Preferences.calendarAllDay = isChecked
|
||||||
updateCalendar()
|
MainWidget.updateWidget(requireContext())
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionChangeAttendeeFilter.setOnClickListener {
|
binding.actionChangeAttendeeFilter.setOnClickListener {
|
||||||
@ -227,7 +230,7 @@ class CalendarFragment : Fragment() {
|
|||||||
|
|
||||||
binding.showOnlyBusyEventsToggle.setOnCheckedChangeListener { _, isChecked ->
|
binding.showOnlyBusyEventsToggle.setOnCheckedChangeListener { _, isChecked ->
|
||||||
Preferences.showOnlyBusyEvents = isChecked
|
Preferences.showOnlyBusyEvents = isChecked
|
||||||
updateCalendar()
|
MainWidget.updateWidget(requireContext())
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionShowDiffTime.setOnClickListener {
|
binding.actionShowDiffTime.setOnClickListener {
|
||||||
@ -236,26 +239,16 @@ class CalendarFragment : Fragment() {
|
|||||||
|
|
||||||
binding.showDiffTimeToggle.setOnCheckedChangeListener { _, isChecked ->
|
binding.showDiffTimeToggle.setOnCheckedChangeListener { _, isChecked ->
|
||||||
Preferences.showDiffTime = isChecked
|
Preferences.showDiffTime = isChecked
|
||||||
updateCalendar()
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.actionShowNextEventOnMultipleLines.setOnClickListener {
|
|
||||||
binding.showNextEventOnMultipleLinesToggle.isChecked = !binding.showNextEventOnMultipleLinesToggle.isChecked
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.showNextEventOnMultipleLinesToggle.setOnCheckedChangeListener { _, isChecked ->
|
|
||||||
Preferences.showNextEventOnMultipleLines = isChecked
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionWidgetUpdateFrequency.setOnClickListener {
|
binding.actionWidgetUpdateFrequency.setOnClickListener {
|
||||||
if (Preferences.showEvents && Preferences.showDiffTime) {
|
if (Preferences.showEvents && Preferences.showDiffTime) {
|
||||||
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_widget_update_frequency_title), message = getString(R.string.settings_widget_update_frequency_subtitle)).setSelectedValue(Preferences.widgetUpdateFrequency)
|
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_widget_update_frequency_title), message = getString(R.string.settings_widget_update_frequency_subtitle)).setSelectedValue(Preferences.widgetUpdateFrequency)
|
||||||
.addItem(getString(R.string.settings_widget_update_frequency_high), Constants.WidgetUpdateFrequency.HIGH.rawValue)
|
.addItem(getString(R.string.settings_widget_update_frequency_high), Constants.WidgetUpdateFrequency.HIGH.value)
|
||||||
.addItem(getString(R.string.settings_widget_update_frequency_default), Constants.WidgetUpdateFrequency.DEFAULT.rawValue)
|
.addItem(getString(R.string.settings_widget_update_frequency_default), Constants.WidgetUpdateFrequency.DEFAULT.value)
|
||||||
.addItem(getString(R.string.settings_widget_update_frequency_low), Constants.WidgetUpdateFrequency.LOW.rawValue)
|
.addItem(getString(R.string.settings_widget_update_frequency_low), Constants.WidgetUpdateFrequency.LOW.value)
|
||||||
.addOnSelectItemListener { value ->
|
.addOnSelectItemListener { value ->
|
||||||
Preferences.widgetUpdateFrequency = value
|
Preferences.widgetUpdateFrequency = value
|
||||||
updateCalendar()
|
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import com.chibatching.kotpref.bulk
|
|||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetPicker
|
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||||
import com.tommasoberlose.anotherwidget.databinding.FragmentTabClockBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentTabClockBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
@ -28,7 +28,6 @@ import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
|||||||
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.tabs.ChooseApplicationActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.tabs.ChooseApplicationActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.tabs.TimeZoneSelectorActivity
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDefaultSet
|
import com.tommasoberlose.anotherwidget.utils.isDefaultSet
|
||||||
@ -101,17 +100,6 @@ class ClockFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.altTimezoneLabel.observe(viewLifecycleOwner) {
|
|
||||||
maintainScrollPosition {
|
|
||||||
if (it != "") {
|
|
||||||
binding.altTimezoneClockLabel.text =
|
|
||||||
String.format("%s (%s)", it, Preferences.altTimezoneId)
|
|
||||||
} else {
|
|
||||||
binding.altTimezoneClockLabel.text = getString(R.string.no_time_zone_label)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.showAMPMIndicator.observe(viewLifecycleOwner) {
|
viewModel.showAMPMIndicator.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.ampmIndicatorLabel.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
binding.ampmIndicatorLabel.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||||
@ -144,19 +132,16 @@ class ClockFragment : Fragment() {
|
|||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
|
|
||||||
binding.actionClockTextSize.setOnClickListener {
|
binding.actionClockTextSize.setOnClickListener {
|
||||||
BottomSheetPicker(
|
val dialog = BottomSheetMenu<Float>(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
items = (120 downTo 30).filter { it % 2 == 0 }.map { BottomSheetPicker.MenuItem("${it}sp", it.toFloat()) },
|
header = getString(R.string.settings_clock_text_size_title)
|
||||||
getSelected = { Preferences.clockTextSize },
|
).setSelectedValue(Preferences.clockTextSize)
|
||||||
header = getString(R.string.settings_clock_text_size_title),
|
(46 downTo 12).filter { it % 2 == 0 }.forEach {
|
||||||
onItemSelected = {value ->
|
dialog.addItem("${it}sp", it.toFloat())
|
||||||
if (value != null) Preferences.clockTextSize = value
|
}
|
||||||
}
|
dialog.addOnSelectItemListener { value ->
|
||||||
).show()
|
Preferences.clockTextSize = value
|
||||||
}
|
}.show()
|
||||||
|
|
||||||
binding.actionAltTimezoneClock.setOnClickListener {
|
|
||||||
startActivity(Intent(requireContext(), TimeZoneSelectorActivity::class.java))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionAmpmIndicatorSize.setOnClickListener {
|
binding.actionAmpmIndicatorSize.setOnClickListener {
|
||||||
|
@ -100,9 +100,17 @@ class GesturesFragment : Fragment() {
|
|||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.calendarAppLabel.text = when {
|
binding.calendarAppLabel.text = when {
|
||||||
it == IntentHelper.DO_NOTHING_OPTION -> getString(R.string.gestures_do_nothing)
|
it == IntentHelper.DO_NOTHING_OPTION -> getString(R.string.gestures_do_nothing)
|
||||||
it == IntentHelper.REFRESH_WIDGET_OPTION -> getString(R.string.gestures_refresh_widget)
|
it == IntentHelper.REFRESH_WIDGET_OPTION -> "None, the widget will be refreshed"
|
||||||
it != IntentHelper.DEFAULT_OPTION -> it
|
it != IntentHelper.DEFAULT_OPTION -> it
|
||||||
else -> getString(R.string.default_calendar_app)
|
else -> {
|
||||||
|
if (IntentHelper.getCalendarIntent(requireContext()).isDefaultSet(requireContext())) {
|
||||||
|
getString(
|
||||||
|
R.string.default_calendar_app
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
getString(R.string.gestures_do_nothing)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,9 +125,17 @@ class GesturesFragment : Fragment() {
|
|||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.clockAppLabel.text = when {
|
binding.clockAppLabel.text = when {
|
||||||
it == IntentHelper.DO_NOTHING_OPTION -> getString(R.string.gestures_do_nothing)
|
it == IntentHelper.DO_NOTHING_OPTION -> getString(R.string.gestures_do_nothing)
|
||||||
it == IntentHelper.REFRESH_WIDGET_OPTION -> getString(R.string.gestures_refresh_widget)
|
it == IntentHelper.REFRESH_WIDGET_OPTION -> "None, the widget will be refreshed"
|
||||||
it != IntentHelper.DEFAULT_OPTION -> it
|
it != IntentHelper.DEFAULT_OPTION -> it
|
||||||
else -> getString(R.string.default_clock_app)
|
else -> {
|
||||||
|
if (IntentHelper.getClockIntent(requireContext()).isDefaultSet(requireContext())) {
|
||||||
|
getString(
|
||||||
|
R.string.default_clock_app
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
getString(R.string.gestures_do_nothing)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,7 +144,7 @@ class GesturesFragment : Fragment() {
|
|||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.weatherAppLabel.text = when {
|
binding.weatherAppLabel.text = when {
|
||||||
it == IntentHelper.DO_NOTHING_OPTION -> getString(R.string.gestures_do_nothing)
|
it == IntentHelper.DO_NOTHING_OPTION -> getString(R.string.gestures_do_nothing)
|
||||||
it == IntentHelper.REFRESH_WIDGET_OPTION -> getString(R.string.gestures_refresh_widget)
|
it == IntentHelper.REFRESH_WIDGET_OPTION -> "None, the widget will be refreshed"
|
||||||
it != IntentHelper.DEFAULT_OPTION -> it
|
it != IntentHelper.DEFAULT_OPTION -> it
|
||||||
else -> getString(R.string.default_weather_app)
|
else -> getString(R.string.default_weather_app)
|
||||||
}
|
}
|
||||||
@ -144,12 +160,6 @@ class GesturesFragment : Fragment() {
|
|||||||
|
|
||||||
binding.showMultipleEventsToggle.setOnCheckedChangeListener { _, isChecked ->
|
binding.showMultipleEventsToggle.setOnCheckedChangeListener { _, isChecked ->
|
||||||
Preferences.showNextEvent = isChecked
|
Preferences.showNextEvent = isChecked
|
||||||
if (!isChecked) {
|
|
||||||
com.tommasoberlose.anotherwidget.db.EventRepository(requireContext()).run {
|
|
||||||
resetNextEventData()
|
|
||||||
close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionOpenEventDetails.setOnClickListener {
|
binding.actionOpenEventDetails.setOnClickListener {
|
||||||
@ -163,12 +173,9 @@ class GesturesFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.actionCalendarApp.setOnClickListener {
|
binding.actionCalendarApp.setOnClickListener {
|
||||||
startActivityForResult(
|
startActivityForResult(Intent(requireContext(), ChooseApplicationActivity::class.java).apply {
|
||||||
Intent(requireContext(), ChooseApplicationActivity::class.java).apply {
|
putExtra(Constants.RESULT_APP_PACKAGE, Preferences.calendarAppPackage)
|
||||||
putExtra(Constants.RESULT_APP_PACKAGE, Preferences.calendarAppPackage)
|
}, RequestCode.CALENDAR_APP_REQUEST_CODE.code)
|
||||||
},
|
|
||||||
RequestCode.CALENDAR_APP_REQUEST_CODE.code
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionClockApp.setOnClickListener {
|
binding.actionClockApp.setOnClickListener {
|
||||||
|
@ -8,20 +8,26 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.animation.AnimationUtils
|
import android.view.animation.AnimationUtils
|
||||||
|
import android.view.animation.LayoutAnimationController
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
||||||
|
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
||||||
|
import com.google.android.gms.common.api.ApiException
|
||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
@ -35,6 +41,8 @@ import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
|
|||||||
import com.tommasoberlose.anotherwidget.helpers.GlanceProviderHelper
|
import com.tommasoberlose.anotherwidget.helpers.GlanceProviderHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||||
import com.tommasoberlose.anotherwidget.models.GlanceProvider
|
import com.tommasoberlose.anotherwidget.models.GlanceProvider
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver.Companion.FITNESS_OPTIONS
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
import com.tommasoberlose.anotherwidget.utils.*
|
import com.tommasoberlose.anotherwidget.utils.*
|
||||||
@ -230,6 +238,40 @@ class GlanceTabFragment : Fragment() {
|
|||||||
injector.visibility(R.id.info_icon, View.VISIBLE)
|
injector.visibility(R.id.info_icon, View.VISIBLE)
|
||||||
isVisible = Preferences.customNotes != ""
|
isVisible = Preferences.customNotes != ""
|
||||||
}
|
}
|
||||||
|
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||||
|
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(
|
||||||
|
context
|
||||||
|
)
|
||||||
|
if (GoogleSignIn.hasPermissions(
|
||||||
|
account,
|
||||||
|
FITNESS_OPTIONS
|
||||||
|
) && (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || requireActivity().checkGrantedPermission(
|
||||||
|
Manifest.permission.ACTIVITY_RECOGNITION
|
||||||
|
))
|
||||||
|
) {
|
||||||
|
injector.text(
|
||||||
|
R.id.label,
|
||||||
|
if (Preferences.showDailySteps) getString(R.string.settings_visible) else getString(
|
||||||
|
R.string.settings_not_visible
|
||||||
|
)
|
||||||
|
)
|
||||||
|
injector.visibility(R.id.error_icon, View.GONE)
|
||||||
|
injector.visibility(R.id.info_icon, View.VISIBLE)
|
||||||
|
isVisible = Preferences.showDailySteps
|
||||||
|
} else if (Preferences.showDailySteps) {
|
||||||
|
ActivityDetectionReceiver.unregisterFence(requireContext())
|
||||||
|
injector.visibility(R.id.error_icon, View.VISIBLE)
|
||||||
|
injector.visibility(R.id.info_icon, View.GONE)
|
||||||
|
injector.text(R.id.label, getString(R.string.settings_not_visible))
|
||||||
|
isVisible = false
|
||||||
|
} else {
|
||||||
|
ActivityDetectionReceiver.unregisterFence(requireContext())
|
||||||
|
injector.text(R.id.label, getString(R.string.settings_not_visible))
|
||||||
|
injector.visibility(R.id.error_icon, View.GONE)
|
||||||
|
injector.visibility(R.id.info_icon, View.VISIBLE)
|
||||||
|
isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
Constants.GlanceProviderId.EVENTS -> {
|
Constants.GlanceProviderId.EVENTS -> {
|
||||||
isVisible =
|
isVisible =
|
||||||
Preferences.showEventsAsGlanceProvider
|
Preferences.showEventsAsGlanceProvider
|
||||||
@ -251,25 +293,6 @@ class GlanceTabFragment : Fragment() {
|
|||||||
if (!(isVisible && hasError)) View.VISIBLE else View.GONE
|
if (!(isVisible && hasError)) View.VISIBLE else View.GONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Constants.GlanceProviderId.WEATHER -> {
|
|
||||||
isVisible =
|
|
||||||
Preferences.showWeatherAsGlanceProvider
|
|
||||||
val hasError = !Preferences.showWeather || (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-") || Preferences.weatherProviderLocationError != ""
|
|
||||||
injector.text(
|
|
||||||
R.id.label,
|
|
||||||
if (isVisible && !hasError) getString(R.string.settings_visible) else getString(
|
|
||||||
R.string.settings_not_visible
|
|
||||||
)
|
|
||||||
)
|
|
||||||
injector.visibility(
|
|
||||||
R.id.error_icon,
|
|
||||||
if (isVisible && hasError) View.VISIBLE else View.GONE
|
|
||||||
)
|
|
||||||
injector.visibility(
|
|
||||||
R.id.info_icon,
|
|
||||||
if (!(isVisible && hasError)) View.VISIBLE else View.GONE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
injector.alpha(R.id.title, if (isVisible) 1f else .25f)
|
injector.alpha(R.id.title, if (isVisible) 1f else .25f)
|
||||||
@ -449,6 +472,30 @@ class GlanceTabFragment : Fragment() {
|
|||||||
Preferences.showDailySteps = false
|
Preferences.showDailySteps = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dialog != null) {
|
||||||
|
dialog?.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 -> {
|
||||||
|
try {
|
||||||
|
val account: GoogleSignInAccount? = GoogleSignIn.getSignedInAccountFromIntent(
|
||||||
|
data
|
||||||
|
).getResult(ApiException::class.java)
|
||||||
|
if (!GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
|
||||||
|
GoogleSignIn.requestPermissions(
|
||||||
|
requireActivity(),
|
||||||
|
1,
|
||||||
|
account,
|
||||||
|
FITNESS_OPTIONS
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
adapter.notifyItemRangeChanged(0, adapter.data.size)
|
||||||
|
}
|
||||||
|
} catch (e: ApiException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
Preferences.showDailySteps = false
|
||||||
|
}
|
||||||
|
|
||||||
if (dialog != null) {
|
if (dialog != null) {
|
||||||
dialog?.show()
|
dialog?.show()
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.fragments.tabs
|
package com.tommasoberlose.anotherwidget.ui.fragments.tabs
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.chibatching.kotpref.blockingBulk
|
||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
||||||
@ -20,6 +22,8 @@ import com.tommasoberlose.anotherwidget.global.Preferences
|
|||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toHexValue
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toHexValue
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.DateHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.tabs.CustomDateActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||||
@ -27,6 +31,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class LayoutFragment : Fragment() {
|
class LayoutFragment : Fragment() {
|
||||||
@ -86,63 +91,23 @@ class LayoutFragment : Fragment() {
|
|||||||
viewModel: MainViewModel
|
viewModel: MainViewModel
|
||||||
) {
|
) {
|
||||||
|
|
||||||
viewModel.widgetMargin.observe(viewLifecycleOwner) {
|
|
||||||
maintainScrollPosition {
|
|
||||||
binding.widgetMarginLabel.text = when (it) {
|
|
||||||
Constants.Dimension.NONE.rawValue -> getString(R.string.settings_widget_dim_none)
|
|
||||||
Constants.Dimension.SMALL.rawValue -> getString(R.string.settings_widget_dim_small)
|
|
||||||
Constants.Dimension.LARGE.rawValue -> getString(R.string.settings_widget_dim_large)
|
|
||||||
else -> getString(R.string.settings_widget_dim_medium)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.widgetPadding.observe(viewLifecycleOwner) {
|
|
||||||
maintainScrollPosition {
|
|
||||||
binding.widgetPaddingLabel.text = when (it) {
|
|
||||||
Constants.Dimension.NONE.rawValue -> getString(R.string.settings_widget_dim_none)
|
|
||||||
Constants.Dimension.SMALL.rawValue -> getString(R.string.settings_widget_dim_small)
|
|
||||||
Constants.Dimension.LARGE.rawValue -> getString(R.string.settings_widget_dim_large)
|
|
||||||
else -> getString(R.string.settings_widget_dim_medium)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.secondRowTopMargin.observe(viewLifecycleOwner) {
|
viewModel.secondRowTopMargin.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.secondRowTopMarginLabel.text = when (it) {
|
binding.secondRowTopMarginLabel.text = when (it) {
|
||||||
Constants.SecondRowTopMargin.NONE.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_none)
|
Constants.SecondRowTopMargin.NONE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_none)
|
||||||
Constants.SecondRowTopMargin.SMALL.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_small)
|
Constants.SecondRowTopMargin.SMALL.value -> getString(R.string.settings_clock_bottom_margin_subtitle_small)
|
||||||
Constants.SecondRowTopMargin.LARGE.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_large)
|
Constants.SecondRowTopMargin.LARGE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_large)
|
||||||
else -> getString(R.string.settings_clock_bottom_margin_subtitle_medium)
|
else -> getString(R.string.settings_clock_bottom_margin_subtitle_medium)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.widgetAlign.observe(viewLifecycleOwner) {
|
|
||||||
maintainScrollPosition {
|
|
||||||
binding.widgetAlignIcon.setImageDrawable(when (it) {
|
|
||||||
Constants.WidgetAlign.LEFT.rawValue -> ContextCompat.getDrawable(requireContext(), R.drawable.round_align_horizontal_left_24)
|
|
||||||
Constants.WidgetAlign.RIGHT.rawValue -> ContextCompat.getDrawable(requireContext(), R.drawable.round_align_horizontal_right_24)
|
|
||||||
Constants.WidgetAlign.CENTER.rawValue -> ContextCompat.getDrawable(requireContext(), R.drawable.round_align_horizontal_center_24)
|
|
||||||
else -> ContextCompat.getDrawable(requireContext(), R.drawable.round_align_horizontal_center_24)
|
|
||||||
})
|
|
||||||
|
|
||||||
binding.widgetAlignLabel.text = when (it) {
|
|
||||||
Constants.WidgetAlign.LEFT.rawValue -> getString(R.string.settings_widget_align_left_subtitle)
|
|
||||||
Constants.WidgetAlign.RIGHT.rawValue -> getString(R.string.settings_widget_align_right_subtitle)
|
|
||||||
Constants.WidgetAlign.CENTER.rawValue -> getString(R.string.settings_widget_align_center_subtitle)
|
|
||||||
else -> getString(R.string.settings_widget_align_center_subtitle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.clockBottomMargin.observe(viewLifecycleOwner) {
|
viewModel.clockBottomMargin.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.clockBottomMarginLabel.text = when (it) {
|
binding.clockBottomMarginLabel.text = when (it) {
|
||||||
Constants.ClockBottomMargin.NONE.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_none)
|
Constants.ClockBottomMargin.NONE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_none)
|
||||||
Constants.ClockBottomMargin.SMALL.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_small)
|
Constants.ClockBottomMargin.SMALL.value -> getString(R.string.settings_clock_bottom_margin_subtitle_small)
|
||||||
Constants.ClockBottomMargin.LARGE.rawValue -> getString(R.string.settings_clock_bottom_margin_subtitle_large)
|
Constants.ClockBottomMargin.LARGE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_large)
|
||||||
else -> getString(R.string.settings_clock_bottom_margin_subtitle_medium)
|
else -> getString(R.string.settings_clock_bottom_margin_subtitle_medium)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,7 +115,7 @@ class LayoutFragment : Fragment() {
|
|||||||
|
|
||||||
viewModel.backgroundCardColor.observe(viewLifecycleOwner) {
|
viewModel.backgroundCardColor.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
if (ColorHelper.getBackgroundAlpha(requireActivity().isDarkTheme()) == 0) {
|
if (Preferences.backgroundCardAlpha == "00") {
|
||||||
binding.backgroundColorLabel.text = getString(R.string.transparent)
|
binding.backgroundColorLabel.text = getString(R.string.transparent)
|
||||||
} else {
|
} else {
|
||||||
binding.backgroundColorLabel.text =
|
binding.backgroundColorLabel.text =
|
||||||
@ -169,58 +134,6 @@ class LayoutFragment : Fragment() {
|
|||||||
|
|
||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
|
|
||||||
binding.actionWidgetMargin.setOnClickListener {
|
|
||||||
BottomSheetMenu<Float>(
|
|
||||||
requireContext(),
|
|
||||||
header = getString(R.string.settings_widget_margin_title)
|
|
||||||
).setSelectedValue(Preferences.widgetMargin)
|
|
||||||
.addItem(
|
|
||||||
getString(R.string.settings_widget_dim_none),
|
|
||||||
Constants.Dimension.NONE.rawValue
|
|
||||||
)
|
|
||||||
.addItem(
|
|
||||||
getString(R.string.settings_widget_dim_small),
|
|
||||||
Constants.Dimension.SMALL.rawValue
|
|
||||||
)
|
|
||||||
.addItem(
|
|
||||||
getString(R.string.settings_widget_dim_medium),
|
|
||||||
Constants.Dimension.MEDIUM.rawValue
|
|
||||||
)
|
|
||||||
.addItem(
|
|
||||||
getString(R.string.settings_widget_dim_large),
|
|
||||||
Constants.Dimension.LARGE.rawValue
|
|
||||||
)
|
|
||||||
.addOnSelectItemListener { value ->
|
|
||||||
Preferences.widgetMargin = value
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.actionWidgetPadding.setOnClickListener {
|
|
||||||
BottomSheetMenu<Float>(
|
|
||||||
requireContext(),
|
|
||||||
header = getString(R.string.settings_widget_padding_title)
|
|
||||||
).setSelectedValue(Preferences.widgetPadding)
|
|
||||||
.addItem(
|
|
||||||
getString(R.string.settings_widget_dim_none),
|
|
||||||
Constants.Dimension.NONE.rawValue
|
|
||||||
)
|
|
||||||
.addItem(
|
|
||||||
getString(R.string.settings_widget_dim_small),
|
|
||||||
Constants.Dimension.SMALL.rawValue
|
|
||||||
)
|
|
||||||
.addItem(
|
|
||||||
getString(R.string.settings_widget_dim_medium),
|
|
||||||
Constants.Dimension.MEDIUM.rawValue
|
|
||||||
)
|
|
||||||
.addItem(
|
|
||||||
getString(R.string.settings_widget_dim_large),
|
|
||||||
Constants.Dimension.LARGE.rawValue
|
|
||||||
)
|
|
||||||
.addOnSelectItemListener { value ->
|
|
||||||
Preferences.widgetPadding = value
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.actionSecondRowTopMarginSize.setOnClickListener {
|
binding.actionSecondRowTopMarginSize.setOnClickListener {
|
||||||
BottomSheetMenu<Int>(
|
BottomSheetMenu<Int>(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
@ -228,19 +141,19 @@ class LayoutFragment : Fragment() {
|
|||||||
).setSelectedValue(Preferences.secondRowTopMargin)
|
).setSelectedValue(Preferences.secondRowTopMargin)
|
||||||
.addItem(
|
.addItem(
|
||||||
getString(R.string.settings_clock_bottom_margin_subtitle_none),
|
getString(R.string.settings_clock_bottom_margin_subtitle_none),
|
||||||
Constants.SecondRowTopMargin.NONE.rawValue
|
Constants.SecondRowTopMargin.NONE.value
|
||||||
)
|
)
|
||||||
.addItem(
|
.addItem(
|
||||||
getString(R.string.settings_clock_bottom_margin_subtitle_small),
|
getString(R.string.settings_clock_bottom_margin_subtitle_small),
|
||||||
Constants.SecondRowTopMargin.SMALL.rawValue
|
Constants.SecondRowTopMargin.SMALL.value
|
||||||
)
|
)
|
||||||
.addItem(
|
.addItem(
|
||||||
getString(R.string.settings_clock_bottom_margin_subtitle_medium),
|
getString(R.string.settings_clock_bottom_margin_subtitle_medium),
|
||||||
Constants.SecondRowTopMargin.MEDIUM.rawValue
|
Constants.SecondRowTopMargin.MEDIUM.value
|
||||||
)
|
)
|
||||||
.addItem(
|
.addItem(
|
||||||
getString(R.string.settings_clock_bottom_margin_subtitle_large),
|
getString(R.string.settings_clock_bottom_margin_subtitle_large),
|
||||||
Constants.SecondRowTopMargin.LARGE.rawValue
|
Constants.SecondRowTopMargin.LARGE.value
|
||||||
)
|
)
|
||||||
.addOnSelectItemListener { value ->
|
.addOnSelectItemListener { value ->
|
||||||
Preferences.secondRowTopMargin = value
|
Preferences.secondRowTopMargin = value
|
||||||
@ -254,47 +167,25 @@ class LayoutFragment : Fragment() {
|
|||||||
).setSelectedValue(Preferences.clockBottomMargin)
|
).setSelectedValue(Preferences.clockBottomMargin)
|
||||||
.addItem(
|
.addItem(
|
||||||
getString(R.string.settings_clock_bottom_margin_subtitle_none),
|
getString(R.string.settings_clock_bottom_margin_subtitle_none),
|
||||||
Constants.ClockBottomMargin.NONE.rawValue
|
Constants.ClockBottomMargin.NONE.value
|
||||||
)
|
)
|
||||||
.addItem(
|
.addItem(
|
||||||
getString(R.string.settings_clock_bottom_margin_subtitle_small),
|
getString(R.string.settings_clock_bottom_margin_subtitle_small),
|
||||||
Constants.ClockBottomMargin.SMALL.rawValue
|
Constants.ClockBottomMargin.SMALL.value
|
||||||
)
|
)
|
||||||
.addItem(
|
.addItem(
|
||||||
getString(R.string.settings_clock_bottom_margin_subtitle_medium),
|
getString(R.string.settings_clock_bottom_margin_subtitle_medium),
|
||||||
Constants.ClockBottomMargin.MEDIUM.rawValue
|
Constants.ClockBottomMargin.MEDIUM.value
|
||||||
)
|
)
|
||||||
.addItem(
|
.addItem(
|
||||||
getString(R.string.settings_clock_bottom_margin_subtitle_large),
|
getString(R.string.settings_clock_bottom_margin_subtitle_large),
|
||||||
Constants.ClockBottomMargin.LARGE.rawValue
|
Constants.ClockBottomMargin.LARGE.value
|
||||||
)
|
)
|
||||||
.addOnSelectItemListener { value ->
|
.addOnSelectItemListener { value ->
|
||||||
Preferences.clockBottomMargin = value
|
Preferences.clockBottomMargin = value
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionWidgetAlign.setOnClickListener {
|
|
||||||
BottomSheetMenu<Int>(
|
|
||||||
requireContext(),
|
|
||||||
header = getString(R.string.settings_widget_align_title)
|
|
||||||
).setSelectedValue(Preferences.widgetAlign)
|
|
||||||
.addItem(
|
|
||||||
getString(R.string.settings_widget_align_center_subtitle),
|
|
||||||
Constants.WidgetAlign.CENTER.rawValue
|
|
||||||
)
|
|
||||||
.addItem(
|
|
||||||
getString(R.string.settings_widget_align_left_subtitle),
|
|
||||||
Constants.WidgetAlign.LEFT.rawValue
|
|
||||||
)
|
|
||||||
.addItem(
|
|
||||||
getString(R.string.settings_widget_align_right_subtitle),
|
|
||||||
Constants.WidgetAlign.RIGHT.rawValue
|
|
||||||
)
|
|
||||||
.addOnSelectItemListener { value ->
|
|
||||||
Preferences.widgetAlign = value
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.actionBackgroundColor.setOnClickListener {
|
binding.actionBackgroundColor.setOnClickListener {
|
||||||
BottomSheetColorPicker(requireContext(),
|
BottomSheetColorPicker(requireContext(),
|
||||||
colors = colors,
|
colors = colors,
|
||||||
|
@ -23,8 +23,6 @@ import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
|
|||||||
import com.tommasoberlose.anotherwidget.databinding.FragmentPreferencesBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentPreferencesBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
|
||||||
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
|
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
@ -89,7 +87,6 @@ class PreferencesFragment : Fragment() {
|
|||||||
CalendarHelper.setEventUpdatesAndroidN(requireContext())
|
CalendarHelper.setEventUpdatesAndroidN(requireContext())
|
||||||
} else {
|
} else {
|
||||||
CalendarHelper.removeEventUpdatesAndroidN(requireContext())
|
CalendarHelper.removeEventUpdatesAndroidN(requireContext())
|
||||||
UpdatesReceiver.removeUpdates(requireContext())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,15 +106,15 @@ class PreferencesFragment : Fragment() {
|
|||||||
|
|
||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
|
|
||||||
binding.actionTypography.setOnSingleClickListener {
|
binding.actionTypography.setOnClickListener {
|
||||||
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_typographyTabFragment)
|
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_typographyTabFragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionGeneralSettings.setOnSingleClickListener {
|
binding.actionGeneralSettings.setOnClickListener {
|
||||||
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_generalTabFragment)
|
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_generalTabFragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionShowEvents.setOnSingleClickListener {
|
binding.actionShowEvents.setOnClickListener {
|
||||||
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_calendarTabFragment)
|
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_calendarTabFragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,22 +126,20 @@ class PreferencesFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionShowWeather.setOnSingleClickListener {
|
binding.actionShowWeather.setOnClickListener {
|
||||||
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_weatherTabFragment)
|
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_weatherTabFragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.showWeatherSwitch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
binding.showWeatherSwitch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
||||||
Preferences.showWeather = enabled
|
Preferences.showWeather = enabled
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
Preferences.weatherProviderError = ""
|
WeatherReceiver.setUpdates(requireContext())
|
||||||
Preferences.weatherProviderLocationError = ""
|
|
||||||
WeatherHelper.updateWeather(requireContext())
|
|
||||||
} else {
|
} else {
|
||||||
WeatherReceiver.removeUpdates(requireContext())
|
WeatherReceiver.removeUpdates(requireContext())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionShowClock.setOnSingleClickListener {
|
binding.actionShowClock.setOnClickListener {
|
||||||
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_clockTabFragment)
|
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_clockTabFragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,11 +147,11 @@ class PreferencesFragment : Fragment() {
|
|||||||
Preferences.showClock = enabled
|
Preferences.showClock = enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionShowGlance.setOnSingleClickListener {
|
binding.actionShowGlance.setOnClickListener {
|
||||||
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_glanceTabFragment)
|
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_glanceTabFragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionTabDefaultApp.setOnSingleClickListener {
|
binding.actionTabDefaultApp.setOnClickListener {
|
||||||
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_gesturesFragment)
|
Navigation.findNavController(it).navigate(R.id.action_tabSelectorFragment_to_gesturesFragment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,7 +161,6 @@ class PreferencesFragment : Fragment() {
|
|||||||
.withPermissions(
|
.withPermissions(
|
||||||
Manifest.permission.READ_CALENDAR
|
Manifest.permission.READ_CALENDAR
|
||||||
).withListener(object: MultiplePermissionsListener {
|
).withListener(object: MultiplePermissionsListener {
|
||||||
private var shouldShowRationale = false
|
|
||||||
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
||||||
report?.let {
|
report?.let {
|
||||||
val granted = report.areAllPermissionsGranted()
|
val granted = report.areAllPermissionsGranted()
|
||||||
@ -174,33 +168,12 @@ class PreferencesFragment : Fragment() {
|
|||||||
if (granted) {
|
if (granted) {
|
||||||
CalendarHelper.updateEventList(requireContext())
|
CalendarHelper.updateEventList(requireContext())
|
||||||
}
|
}
|
||||||
else if (!shouldShowRationale && report.isAnyPermissionPermanentlyDenied) {
|
|
||||||
MaterialBottomSheetDialog(
|
|
||||||
requireContext(),
|
|
||||||
getString(R.string.title_permission_calendar),
|
|
||||||
getString(R.string.description_permission_calendar)
|
|
||||||
).setNegativeButton(getString(R.string.action_ignore))
|
|
||||||
.setPositiveButton(getString(R.string.action_grant_permission)) {
|
|
||||||
startActivity(
|
|
||||||
android.content.Intent(
|
|
||||||
android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
|
||||||
).apply {
|
|
||||||
data = android.net.Uri.fromParts(
|
|
||||||
"package",
|
|
||||||
requireContext().packageName,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override fun onPermissionRationaleShouldBeShown(
|
override fun onPermissionRationaleShouldBeShown(
|
||||||
permissions: MutableList<PermissionRequest>?,
|
permissions: MutableList<PermissionRequest>?,
|
||||||
token: PermissionToken?
|
token: PermissionToken?
|
||||||
) {
|
) {
|
||||||
shouldShowRationale = true
|
|
||||||
// Remember to invoke this method when the custom rationale is closed
|
// Remember to invoke this method when the custom rationale is closed
|
||||||
// or just by default if you don't want to use any custom rationale.
|
// or just by default if you don't want to use any custom rationale.
|
||||||
token?.continuePermissionRequest()
|
token?.continuePermissionRequest()
|
||||||
|
@ -15,7 +15,6 @@ import com.google.android.material.transition.MaterialSharedAxis
|
|||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetPicker
|
|
||||||
import com.tommasoberlose.anotherwidget.databinding.FragmentTabTypographyBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentTabTypographyBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
@ -168,27 +167,25 @@ class TypographyFragment : Fragment() {
|
|||||||
|
|
||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
binding.actionMainTextSize.setOnClickListener {
|
binding.actionMainTextSize.setOnClickListener {
|
||||||
BottomSheetPicker(
|
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.title_main_text_size)).setSelectedValue(
|
||||||
requireContext(),
|
Preferences.textMainSize)
|
||||||
items = (40 downTo 10).map { BottomSheetPicker.MenuItem("${it}sp", it.toFloat()) },
|
(40 downTo 10).filter { it % 2 == 0 }.forEach {
|
||||||
getSelected = { Preferences.textMainSize },
|
dialog.addItem("${it}sp", it.toFloat())
|
||||||
header = getString(R.string.title_main_text_size),
|
}
|
||||||
onItemSelected = {value ->
|
dialog.addOnSelectItemListener { value ->
|
||||||
if (value != null) Preferences.textMainSize = value
|
Preferences.textMainSize = value
|
||||||
}
|
}.show()
|
||||||
).show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionSecondTextSize.setOnClickListener {
|
binding.actionSecondTextSize.setOnClickListener {
|
||||||
BottomSheetPicker(
|
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.title_second_text_size)).setSelectedValue(
|
||||||
requireContext(),
|
Preferences.textSecondSize)
|
||||||
items = (40 downTo 10).map { BottomSheetPicker.MenuItem("${it}sp", it.toFloat()) },
|
(40 downTo 10).filter { it % 2 == 0 }.forEach {
|
||||||
getSelected = { Preferences.textSecondSize },
|
dialog.addItem("${it}sp", it.toFloat())
|
||||||
header = getString(R.string.title_second_text_size),
|
}
|
||||||
onItemSelected = {value ->
|
dialog.addOnSelectItemListener { value ->
|
||||||
if (value != null) Preferences.textSecondSize = value
|
Preferences.textSecondSize = value
|
||||||
}
|
}.show()
|
||||||
).show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionFontColor.setOnClickListener {
|
binding.actionFontColor.setOnClickListener {
|
||||||
@ -212,7 +209,7 @@ class TypographyFragment : Fragment() {
|
|||||||
} else {
|
} else {
|
||||||
Preferences.textGlobalAlpha = alpha.toHexValue()
|
Preferences.textGlobalAlpha = alpha.toHexValue()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +236,7 @@ class TypographyFragment : Fragment() {
|
|||||||
} else {
|
} else {
|
||||||
Preferences.textSecondaryAlpha = alpha.toHexValue()
|
Preferences.textSecondaryAlpha = alpha.toHexValue()
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +273,7 @@ class TypographyFragment : Fragment() {
|
|||||||
Intent(requireContext(), CustomFontActivity::class.java),
|
Intent(requireContext(), CustomFontActivity::class.java),
|
||||||
RequestCode.CUSTOM_FONT_CHOOSER_REQUEST_CODE.code
|
RequestCode.CUSTOM_FONT_CHOOSER_REQUEST_CODE.code
|
||||||
)
|
)
|
||||||
} else if (value != Preferences.customFont) {
|
} else if (value != Constants.CUSTOM_FONT_DOWNLOADED) {
|
||||||
Preferences.bulk {
|
Preferences.bulk {
|
||||||
customFont = value
|
customFont = value
|
||||||
customFontFile = ""
|
customFontFile = ""
|
||||||
@ -317,17 +314,6 @@ class TypographyFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
|
||||||
if (resultCode == android.app.Activity.RESULT_OK) {
|
|
||||||
when (requestCode) {
|
|
||||||
RequestCode.CUSTOM_FONT_CHOOSER_REQUEST_CODE.code -> {
|
|
||||||
com.tommasoberlose.anotherwidget.ui.widgets.MainWidget.updateWidget(requireContext())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun maintainScrollPosition(callback: () -> Unit) {
|
private fun maintainScrollPosition(callback: () -> Unit) {
|
||||||
binding.scrollView.isScrollable = false
|
binding.scrollView.isScrollable = false
|
||||||
callback.invoke()
|
callback.invoke()
|
||||||
|
@ -91,17 +91,16 @@ class WeatherFragment : Fragment() {
|
|||||||
viewModel.weatherProvider.observe(viewLifecycleOwner) {
|
viewModel.weatherProvider.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.labelWeatherProvider.text = WeatherHelper.getProviderName(requireContext(), Constants.WeatherProvider.fromInt(it)!!)
|
binding.labelWeatherProvider.text = WeatherHelper.getProviderName(requireContext(), Constants.WeatherProvider.fromInt(it)!!)
|
||||||
|
checkWeatherProviderConfig()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.weatherProviderError.observe(viewLifecycleOwner) {
|
viewModel.weatherProviderError.observe(viewLifecycleOwner) {
|
||||||
checkWeatherProviderConfig()
|
checkWeatherProviderConfig()
|
||||||
checkLocationPermission()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.weatherProviderLocationError.observe(viewLifecycleOwner) {
|
viewModel.weatherProviderLocationError.observe(viewLifecycleOwner) {
|
||||||
checkWeatherProviderConfig()
|
checkWeatherProviderConfig()
|
||||||
checkLocationPermission()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.customLocationAdd.observe(viewLifecycleOwner) {
|
viewModel.customLocationAdd.observe(viewLifecycleOwner) {
|
||||||
@ -109,7 +108,6 @@ class WeatherFragment : Fragment() {
|
|||||||
binding.labelCustomLocation.text =
|
binding.labelCustomLocation.text =
|
||||||
if (it == "") getString(R.string.custom_location_gps) else it
|
if (it == "") getString(R.string.custom_location_gps) else it
|
||||||
}
|
}
|
||||||
checkWeatherProviderConfig()
|
|
||||||
checkLocationPermission()
|
checkLocationPermission()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,40 +116,43 @@ class WeatherFragment : Fragment() {
|
|||||||
binding.tempUnit.text =
|
binding.tempUnit.text =
|
||||||
if (it == "F") getString(R.string.fahrenheit) else getString(R.string.celsius)
|
if (it == "F") getString(R.string.fahrenheit) else getString(R.string.celsius)
|
||||||
}
|
}
|
||||||
|
checkLocationPermission()
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.weatherRefreshPeriod.observe(viewLifecycleOwner) {
|
viewModel.weatherRefreshPeriod.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.labelWeatherRefreshPeriod.text = getString(SettingsStringHelper.getRefreshPeriodString(it))
|
binding.labelWeatherRefreshPeriod.text = getString(SettingsStringHelper.getRefreshPeriodString(it))
|
||||||
}
|
}
|
||||||
|
checkLocationPermission()
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.weatherIconPack.observe(viewLifecycleOwner) {
|
viewModel.weatherIconPack.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.labelWeatherIconPack.text = getString(R.string.settings_weather_icon_pack_default).format((it + 1))
|
binding.labelWeatherIconPack.text = getString(R.string.settings_weather_icon_pack_default).format((it + 1))
|
||||||
}
|
}
|
||||||
|
checkLocationPermission()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkLocationPermission() {
|
private fun checkLocationPermission() {
|
||||||
if (requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_COARSE_LOCATION)) {
|
if (requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
|
||||||
binding.locationPermissionAlert.isVisible = false
|
binding.locationPermissionAlert.isVisible = false
|
||||||
} else if (Preferences.customLocationAdd == "") {
|
WeatherReceiver.setUpdates(requireContext())
|
||||||
|
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
|
||||||
binding.locationPermissionAlert.isVisible = true
|
binding.locationPermissionAlert.isVisible = true
|
||||||
binding.locationPermissionAlert.setOnClickListener {
|
binding.locationPermissionAlert.setOnClickListener {
|
||||||
requirePermission()
|
requirePermission()
|
||||||
}
|
}
|
||||||
binding.weatherProviderLocationError.isVisible = false
|
|
||||||
} else {
|
} else {
|
||||||
binding.locationPermissionAlert.isVisible = false
|
binding.locationPermissionAlert.isVisible = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkWeatherProviderConfig() {
|
private fun checkWeatherProviderConfig() {
|
||||||
binding.weatherProviderError.isVisible = Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-"
|
binding.weatherProviderError.isVisible = Preferences.showWeather && Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-"
|
||||||
binding.weatherProviderError.text = Preferences.weatherProviderError
|
binding.weatherProviderError.text = Preferences.weatherProviderError
|
||||||
|
|
||||||
binding.weatherProviderLocationError.isVisible = Preferences.weatherProviderLocationError != ""
|
binding.weatherProviderLocationError.isVisible = Preferences.showWeather && Preferences.weatherProviderLocationError != ""
|
||||||
binding.weatherProviderLocationError.text = Preferences.weatherProviderLocationError
|
binding.weatherProviderLocationError.text = Preferences.weatherProviderLocationError
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,9 +177,11 @@ class WeatherFragment : Fragment() {
|
|||||||
.addItem(getString(R.string.celsius), "C")
|
.addItem(getString(R.string.celsius), "C")
|
||||||
.addOnSelectItemListener { value ->
|
.addOnSelectItemListener { value ->
|
||||||
if (value != Preferences.weatherTempUnit) {
|
if (value != Preferences.weatherTempUnit) {
|
||||||
Preferences.weatherTempUnit = value
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
WeatherHelper.updateWeather(requireContext())
|
WeatherHelper.updateWeather(requireContext())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Preferences.weatherTempUnit = value
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,10 +193,7 @@ class WeatherFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
dialog
|
dialog
|
||||||
.addOnSelectItemListener { value ->
|
.addOnSelectItemListener { value ->
|
||||||
if (value != Preferences.weatherRefreshPeriod) {
|
Preferences.weatherRefreshPeriod = value
|
||||||
Preferences.weatherRefreshPeriod = value
|
|
||||||
WeatherReceiver.setUpdates(requireContext())
|
|
||||||
}
|
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,10 +206,12 @@ class WeatherFragment : Fragment() {
|
|||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
when (requestCode) {
|
when (requestCode) {
|
||||||
Constants.RESULT_CODE_CUSTOM_LOCATION -> {
|
Constants.RESULT_CODE_CUSTOM_LOCATION -> {
|
||||||
WeatherHelper.updateWeather(requireContext())
|
WeatherReceiver.setUpdates(requireContext())
|
||||||
|
checkLocationPermission()
|
||||||
|
}
|
||||||
|
RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> {
|
||||||
|
checkLocationPermission()
|
||||||
}
|
}
|
||||||
//RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> {
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
@ -218,35 +220,12 @@ class WeatherFragment : Fragment() {
|
|||||||
private fun requirePermission() {
|
private fun requirePermission() {
|
||||||
Dexter.withContext(requireContext())
|
Dexter.withContext(requireContext())
|
||||||
.withPermissions(
|
.withPermissions(
|
||||||
Manifest.permission.ACCESS_FINE_LOCATION,
|
Manifest.permission.ACCESS_FINE_LOCATION
|
||||||
Manifest.permission.ACCESS_COARSE_LOCATION
|
|
||||||
).withListener(object: MultiplePermissionsListener {
|
).withListener(object: MultiplePermissionsListener {
|
||||||
private var shouldShowRationale = false
|
|
||||||
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
||||||
report?.let {
|
report?.let {
|
||||||
if (report.grantedPermissionResponses.isNotEmpty()) {
|
if (report.areAllPermissionsGranted()){
|
||||||
checkLocationPermission()
|
checkLocationPermission()
|
||||||
WeatherHelper.updateWeather(requireContext())
|
|
||||||
}
|
|
||||||
else if (!shouldShowRationale && report.isAnyPermissionPermanentlyDenied) {
|
|
||||||
MaterialBottomSheetDialog(
|
|
||||||
requireContext(),
|
|
||||||
getString(R.string.title_permission_location),
|
|
||||||
getString(R.string.description_permission_location)
|
|
||||||
).setNegativeButton(getString(R.string.action_ignore))
|
|
||||||
.setPositiveButton(getString(R.string.action_grant_permission)) {
|
|
||||||
startActivity(
|
|
||||||
Intent(
|
|
||||||
android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
|
||||||
).apply {
|
|
||||||
data = android.net.Uri.fromParts(
|
|
||||||
"package",
|
|
||||||
requireContext().packageName,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}.show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,7 +233,6 @@ class WeatherFragment : Fragment() {
|
|||||||
permissions: MutableList<PermissionRequest>?,
|
permissions: MutableList<PermissionRequest>?,
|
||||||
token: PermissionToken?
|
token: PermissionToken?
|
||||||
) {
|
) {
|
||||||
shouldShowRationale = true
|
|
||||||
// Remember to invoke this method when the custom rationale is closed
|
// Remember to invoke this method when the custom rationale is closed
|
||||||
// or just by default if you don't want to use any custom rationale.
|
// or just by default if you don't want to use any custom rationale.
|
||||||
token?.continuePermissionRequest()
|
token?.continuePermissionRequest()
|
||||||
@ -263,12 +241,6 @@ class WeatherFragment : Fragment() {
|
|||||||
.check()
|
.check()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
checkWeatherProviderConfig()
|
|
||||||
checkLocationPermission()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun maintainScrollPosition(callback: () -> Unit) {
|
private fun maintainScrollPosition(callback: () -> Unit) {
|
||||||
binding.scrollView.isScrollable = false
|
binding.scrollView.isScrollable = false
|
||||||
callback.invoke()
|
callback.invoke()
|
||||||
|
@ -49,9 +49,6 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
val secondRowInformation = Preferences.asLiveData(Preferences::secondRowInformation)
|
val secondRowInformation = Preferences.asLiveData(Preferences::secondRowInformation)
|
||||||
val showDividers = Preferences.asLiveData(Preferences::showDividers)
|
val showDividers = Preferences.asLiveData(Preferences::showDividers)
|
||||||
val secondRowTopMargin = Preferences.asLiveData(Preferences::secondRowTopMargin)
|
val secondRowTopMargin = Preferences.asLiveData(Preferences::secondRowTopMargin)
|
||||||
val widgetAlign = Preferences.asLiveData(Preferences::widgetAlign)
|
|
||||||
val widgetMargin = Preferences.asLiveData(Preferences::widgetMargin)
|
|
||||||
val widgetPadding = Preferences.asLiveData(Preferences::widgetPadding)
|
|
||||||
|
|
||||||
// Calendar Settings
|
// Calendar Settings
|
||||||
val showEvents = Preferences.asLiveData(Preferences::showEvents)
|
val showEvents = Preferences.asLiveData(Preferences::showEvents)
|
||||||
@ -59,7 +56,6 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
val showUntil = Preferences.asLiveData(Preferences::showUntil)
|
val showUntil = Preferences.asLiveData(Preferences::showUntil)
|
||||||
val showDiffTime = Preferences.asLiveData(Preferences::showDiffTime)
|
val showDiffTime = Preferences.asLiveData(Preferences::showDiffTime)
|
||||||
val showNextEvent = Preferences.asLiveData(Preferences::showNextEvent)
|
val showNextEvent = Preferences.asLiveData(Preferences::showNextEvent)
|
||||||
val showNextEventOnMultipleLines = Preferences.asLiveData(Preferences::showNextEventOnMultipleLines)
|
|
||||||
val openEventDetails = Preferences.asLiveData(Preferences::openEventDetails)
|
val openEventDetails = Preferences.asLiveData(Preferences::openEventDetails)
|
||||||
val calendarAppName = Preferences.asLiveData(Preferences::calendarAppName)
|
val calendarAppName = Preferences.asLiveData(Preferences::calendarAppName)
|
||||||
val widgetUpdateFrequency = Preferences.asLiveData(Preferences::widgetUpdateFrequency)
|
val widgetUpdateFrequency = Preferences.asLiveData(Preferences::widgetUpdateFrequency)
|
||||||
@ -68,7 +64,6 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
// Clock Settings
|
// Clock Settings
|
||||||
val showClock = Preferences.asLiveData(Preferences::showClock)
|
val showClock = Preferences.asLiveData(Preferences::showClock)
|
||||||
val clockTextSize = Preferences.asLiveData(Preferences::clockTextSize)
|
val clockTextSize = Preferences.asLiveData(Preferences::clockTextSize)
|
||||||
val altTimezoneLabel = Preferences.asLiveData(Preferences::altTimezoneLabel)
|
|
||||||
val clockTextColor = MediatorLiveData<Boolean>().apply {
|
val clockTextColor = MediatorLiveData<Boolean>().apply {
|
||||||
addSource(Preferences.asLiveData(Preferences::clockTextColor)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::clockTextColor)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::clockTextAlpha)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::clockTextAlpha)) { value = true }
|
||||||
@ -104,8 +99,7 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
|
|
||||||
// UI
|
// UI
|
||||||
val fragmentScrollY = MutableLiveData<Int>()
|
val fragmentScrollY = MutableLiveData<Int>()
|
||||||
val widgetPreferencesUpdate = MediatorLiveData<Boolean>().apply {
|
val clockPreferencesUpdate = MediatorLiveData<Boolean>().apply {
|
||||||
addSource(Preferences.asLiveData(Preferences::showClock)) { value = true }
|
|
||||||
addSource(Preferences.asLiveData(Preferences::clockTextSize)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::clockTextSize)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::clockTextColor)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::clockTextColor)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::clockTextAlpha)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::clockTextAlpha)) { value = true }
|
||||||
@ -113,7 +107,8 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
addSource(Preferences.asLiveData(Preferences::clockTextAlphaDark)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::clockTextAlphaDark)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showAMPMIndicator)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showAMPMIndicator)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::clockBottomMargin)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::clockBottomMargin)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::altTimezoneLabel)) { value = true }
|
}
|
||||||
|
val widgetPreferencesUpdate = MediatorLiveData<Boolean>().apply {
|
||||||
addSource(Preferences.asLiveData(Preferences::textGlobalColor)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::textGlobalColor)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::textGlobalAlpha)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::textGlobalAlpha)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::textSecondaryColor)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::textSecondaryColor)) { value = true }
|
||||||
@ -135,9 +130,7 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
addSource(Preferences.asLiveData(Preferences::customFontFile)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::customFontFile)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::customFontName)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::customFontName)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::customFontVariant)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::customFontVariant)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::widgetAlign)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::secondRowInformation)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::widgetMargin)) { value = true }
|
|
||||||
addSource(Preferences.asLiveData(Preferences::widgetPadding)) { value = true }
|
|
||||||
addSource(Preferences.asLiveData(Preferences::showDividers)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showDividers)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::secondRowTopMargin)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::secondRowTopMargin)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::isDateCapitalize)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::isDateCapitalize)) { value = true }
|
||||||
@ -147,7 +140,6 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
addSource(Preferences.asLiveData(Preferences::calendarAllDay)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::calendarAllDay)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showDiffTime)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showDiffTime)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showNextEvent)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showNextEvent)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showNextEventOnMultipleLines)) { value = true }
|
|
||||||
addSource(Preferences.asLiveData(Preferences::showDeclinedEvents)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showDeclinedEvents)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showInvitedEvents)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showInvitedEvents)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showAcceptedEvents)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showAcceptedEvents)) { value = true }
|
||||||
@ -155,7 +147,7 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
addSource(Preferences.asLiveData(Preferences::secondRowInformation)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::secondRowInformation)) { value = true }
|
||||||
|
|
||||||
addSource(Preferences.asLiveData(Preferences::showWeather)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showWeather)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::weatherProvider)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::weatherTempUnit)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::weatherIconPack)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::weatherIconPack)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::customLocationLat)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::customLocationLat)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::customLocationLon)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::customLocationLon)) { value = true }
|
||||||
@ -173,7 +165,6 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
addSource(Preferences.asLiveData(Preferences::musicPlayersFilter)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::musicPlayersFilter)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::appNotificationsFilter)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::appNotificationsFilter)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showEventsAsGlanceProvider)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showEventsAsGlanceProvider)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showWeatherAsGlanceProvider)) { value = true }
|
|
||||||
|
|
||||||
addSource(Preferences.asLiveData(Preferences::installedIntegrations)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::installedIntegrations)) { value = true }
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.viewmodels.settings
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.android.billingclient.api.*
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class SupportDevViewModel : ViewModel() {
|
||||||
|
|
||||||
|
lateinit var billingClient: BillingClient
|
||||||
|
val products: MutableLiveData<List<SkuDetails>> = MutableLiveData(emptyList())
|
||||||
|
|
||||||
|
fun openConnection() {
|
||||||
|
|
||||||
|
billingClient.startConnection(object : BillingClientStateListener {
|
||||||
|
override fun onBillingSetupFinished(billingResult: BillingResult) {
|
||||||
|
if (billingResult.responseCode == BillingClient.BillingResponseCode.OK) {
|
||||||
|
val params = SkuDetailsParams.newBuilder()
|
||||||
|
params.setSkusList(listOf("donation_coffee", "donation_donuts", "donation_breakfast", "donation_lunch", "donation_dinner")).setType(BillingClient.SkuType.INAPP)
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
val skuDetailsList = billingClient.querySkuDetails(params.build()).skuDetailsList
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
products.value = skuDetailsList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override fun onBillingServiceDisconnected() {
|
||||||
|
// Try to restart the connection on the next request to
|
||||||
|
// Google Play by calling the startConnection() method.
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun purchase(activity: Activity, product: SkuDetails) {
|
||||||
|
val flowParams = BillingFlowParams.newBuilder()
|
||||||
|
.setSkuDetails(product)
|
||||||
|
.build()
|
||||||
|
billingClient.launchBillingFlow(activity, flowParams)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handlePurchase(purchase: Purchase) {
|
||||||
|
if (!purchase.isAcknowledged) {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
val token = purchase.purchaseToken
|
||||||
|
val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
|
||||||
|
.setPurchaseToken(token)
|
||||||
|
billingClient.acknowledgePurchase(acknowledgePurchaseParams.build())
|
||||||
|
|
||||||
|
val consumeParams =
|
||||||
|
ConsumeParams.newBuilder()
|
||||||
|
.setPurchaseToken(token)
|
||||||
|
.build()
|
||||||
|
billingClient.consumePurchase(consumeParams)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun closeConnection() {
|
||||||
|
billingClient.endConnection()
|
||||||
|
}
|
||||||
|
}
|
@ -9,9 +9,10 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import com.koolio.library.DownloadableFontList
|
import com.koolio.library.DownloadableFontList
|
||||||
import com.koolio.library.Font
|
import com.koolio.library.Font
|
||||||
import com.koolio.library.FontList
|
import com.koolio.library.FontList
|
||||||
//import com.tommasoberlose.anotherwidget.BuildConfig
|
import com.tommasoberlose.anotherwidget.BuildConfig
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
class CustomFontViewModel(application: Application) : AndroidViewModel(application) {
|
class CustomFontViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ class CustomFontViewModel(application: Application) : AndroidViewModel(applicati
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DownloadableFontList.requestDownloadableFontList(fontListCallback, BuildConfig.GOOGLE_API_KEY)
|
DownloadableFontList.requestDownloadableFontList(fontListCallback, BuildConfig.GOOGLE_API_KEY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,13 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.viewmodels.tabs
|
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import android.location.Address
|
|
||||||
import androidx.lifecycle.AndroidViewModel
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
|
|
||||||
class TimeZoneSelectorViewModel(application: Application) : AndroidViewModel(application) {
|
|
||||||
|
|
||||||
val addresses: MutableLiveData<List<Address>> = MutableLiveData(emptyList())
|
|
||||||
val locationInput: MutableLiveData<String> = MutableLiveData(Preferences.altTimezoneLabel)
|
|
||||||
}
|
|
@ -1,999 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.widgets
|
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.Gravity
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.*
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import com.tommasoberlose.anotherwidget.R
|
|
||||||
import com.tommasoberlose.anotherwidget.databinding.LeftAlignedWidgetBinding
|
|
||||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Actions
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.*
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ImageHelper.applyShadow
|
|
||||||
import com.tommasoberlose.anotherwidget.receivers.NewCalendarEventReceiver
|
|
||||||
import com.tommasoberlose.anotherwidget.receivers.WidgetClickListenerReceiver
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.convertDpToPixel
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
|
||||||
import java.text.DateFormat
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
class AlignedWidget(val context: Context, val rightAligned: Boolean = false) {
|
|
||||||
fun generateWidget(appWidgetId: Int, w: Int, typeface: Typeface? = null): RemoteViews? {
|
|
||||||
|
|
||||||
var views = RemoteViews(context.packageName, if (!rightAligned) R.layout.left_aligned_widget_sans else R.layout.right_aligned_widget_sans)
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Background
|
|
||||||
views.setInt(
|
|
||||||
R.id.widget_shape_background,
|
|
||||||
"setColorFilter",
|
|
||||||
ColorHelper.getBackgroundColorRgb(context.isDarkTheme())
|
|
||||||
)
|
|
||||||
views.setInt(
|
|
||||||
R.id.widget_shape_background,
|
|
||||||
"setImageAlpha",
|
|
||||||
ColorHelper.getBackgroundAlpha(context.isDarkTheme())
|
|
||||||
)
|
|
||||||
val margin = Preferences.widgetMargin.convertDpToPixel(context).toInt()
|
|
||||||
views.setViewPadding(R.id.widget_shape_background, margin, margin, margin, margin)
|
|
||||||
val refreshIntent = IntentHelper.getPendingIntent(
|
|
||||||
context,
|
|
||||||
appWidgetId,
|
|
||||||
IntentHelper.getWidgetUpdateIntent(context),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.widget_shape_background, refreshIntent)
|
|
||||||
|
|
||||||
// Padding
|
|
||||||
val padding = (Preferences.widgetPadding.convertDpToPixel(context) + Preferences.widgetMargin.convertDpToPixel(context)).toInt()
|
|
||||||
views.setViewPadding(R.id.main_layout, padding, padding, padding, padding)
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clock
|
|
||||||
views = ClockWidget(context).updateClockView(views, appWidgetId)
|
|
||||||
|
|
||||||
// Setup listener
|
|
||||||
try {
|
|
||||||
val generatedBinding = generateWidgetView(typeface) ?: return null
|
|
||||||
|
|
||||||
val width = w - (Preferences.widgetPadding.convertDpToPixel(context) + Preferences.widgetMargin.convertDpToPixel(context)).toInt() * 2
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.bitmap_container,
|
|
||||||
BitmapHelper.getBitmapFromView(generatedBinding.root, width)
|
|
||||||
)
|
|
||||||
views = updateGridView(generatedBinding, views, appWidgetId)
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
return views
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateGridView(bindingView: LeftAlignedWidgetBinding, views: RemoteViews, widgetID: Int): RemoteViews {
|
|
||||||
try {
|
|
||||||
val eventRepository = EventRepository(context)
|
|
||||||
val nextEvent = eventRepository.getNextEvent()
|
|
||||||
val eventsCount = eventRepository.getEventsCount()
|
|
||||||
eventRepository.close()
|
|
||||||
|
|
||||||
// Weather
|
|
||||||
if (Preferences.showWeather && Preferences.weatherIcon != "") {
|
|
||||||
views.setViewVisibility(R.id.weather_rect, View.VISIBLE)
|
|
||||||
views.setViewVisibility(R.id.weather_sub_line_rect, View.GONE)
|
|
||||||
|
|
||||||
val i = Intent(context, WidgetClickListenerReceiver::class.java)
|
|
||||||
i.action = Actions.ACTION_OPEN_WEATHER_INTENT
|
|
||||||
val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, PendingIntent.FLAG_IMMUTABLE)
|
|
||||||
|
|
||||||
views.setOnClickPendingIntent(R.id.weather_rect, weatherPIntent)
|
|
||||||
views.setOnClickPendingIntent(R.id.weather_sub_line_rect, weatherPIntent)
|
|
||||||
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.weather_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(bindingView.weatherDateLine, draw = false, width = bindingView.weatherDateLine.width, height = bindingView.weatherDateLine.height)
|
|
||||||
)
|
|
||||||
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.weather_sub_line_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(bindingView.weatherSubLine, draw = false, width = bindingView.weatherSubLine.width, height = bindingView.weatherSubLine.height)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
views.setViewVisibility(R.id.weather_rect, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.weather_sub_line_rect, View.GONE)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Calendar
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.date_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(bindingView.date, draw = false, width = bindingView.date.width, height = bindingView.date.height)
|
|
||||||
)
|
|
||||||
|
|
||||||
val calPIntent = IntentHelper.getPendingIntent(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getCalendarIntent(context),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.date_rect, calPIntent)
|
|
||||||
views.setViewVisibility(R.id.first_line_rect, View.VISIBLE)
|
|
||||||
|
|
||||||
// Spacing
|
|
||||||
views.setViewVisibility(
|
|
||||||
R.id.sub_line_top_margin_small_sans,
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.rawValue) View.VISIBLE else View.GONE
|
|
||||||
)
|
|
||||||
views.setViewVisibility(
|
|
||||||
R.id.sub_line_top_margin_medium_sans,
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.rawValue) View.VISIBLE else View.GONE
|
|
||||||
)
|
|
||||||
views.setViewVisibility(
|
|
||||||
R.id.sub_line_top_margin_large_sans,
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.rawValue) View.VISIBLE else View.GONE
|
|
||||||
)
|
|
||||||
|
|
||||||
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null && !Preferences.showEventsAsGlanceProvider) {
|
|
||||||
if (Preferences.showNextEvent && eventsCount > 1) {
|
|
||||||
|
|
||||||
// Action next event
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.action_next_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(bindingView.actionNext, draw = false, width = bindingView.actionNext.width, height = bindingView.actionNext.height)
|
|
||||||
)
|
|
||||||
views.setViewVisibility(R.id.action_next_rect, View.VISIBLE)
|
|
||||||
views.setOnClickPendingIntent(
|
|
||||||
R.id.action_next_rect,
|
|
||||||
PendingIntent.getBroadcast(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
Intent(
|
|
||||||
context,
|
|
||||||
NewCalendarEventReceiver::class.java
|
|
||||||
).apply { action = Actions.ACTION_GO_TO_NEXT_EVENT },
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
views.setViewVisibility(R.id.action_next_rect, View.VISIBLE)
|
|
||||||
} else {
|
|
||||||
views.setViewVisibility(R.id.action_next_rect, View.GONE)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Event intent
|
|
||||||
val eventIntent = IntentHelper.getPendingIntent(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getEventIntent(context, nextEvent),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.next_event_rect, eventIntent)
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.next_event_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(bindingView.nextEvent, draw = false, width = bindingView.nextEvent.width, height = bindingView.nextEvent.height)
|
|
||||||
)
|
|
||||||
views.setViewVisibility(R.id.next_event_rect, View.VISIBLE)
|
|
||||||
|
|
||||||
// Event time difference
|
|
||||||
if (Preferences.showDiffTime && Calendar.getInstance().timeInMillis < nextEvent.startDate) {
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.next_event_difference_time_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(
|
|
||||||
bindingView.nextEventDifferenceTime,
|
|
||||||
draw = false,
|
|
||||||
width = bindingView.nextEventDifferenceTime.width,
|
|
||||||
height = bindingView.nextEventDifferenceTime.height
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
views.setOnClickPendingIntent(R.id.next_event_difference_time_rect, eventIntent)
|
|
||||||
if (!Preferences.showNextEventOnMultipleLines) {
|
|
||||||
views.setViewVisibility(R.id.next_event_difference_time_rect, View.VISIBLE)
|
|
||||||
} else {
|
|
||||||
views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Event information
|
|
||||||
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
|
|
||||||
val mapIntent = IntentHelper.getPendingIntent(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getGoogleMapsIntentFromAddress(context, nextEvent.address),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.sub_line_rect, mapIntent)
|
|
||||||
} else {
|
|
||||||
val pIntentDetail = IntentHelper.getPendingIntent(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getCalendarIntent(context, nextEvent.startDate),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.sub_line_rect, pIntentDetail)
|
|
||||||
}
|
|
||||||
|
|
||||||
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
|
||||||
views.setViewVisibility(R.id.sub_line_rect, View.VISIBLE)
|
|
||||||
views.setViewVisibility(R.id.weather_sub_line_rect, if (Preferences.showWeather && Preferences.weatherIcon != "") View.VISIBLE else View.GONE)
|
|
||||||
views.setViewVisibility(R.id.first_line_rect, View.GONE)
|
|
||||||
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
|
|
||||||
var showSomething = false
|
|
||||||
var isWeatherShown = false
|
|
||||||
loop@ for (provider: Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(context)) {
|
|
||||||
when (provider) {
|
|
||||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
|
||||||
if (MediaPlayerHelper.isSomeonePlaying(context)) {
|
|
||||||
val musicIntent = IntentHelper.getPendingIntent(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getMusicIntent(context),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.sub_line_rect, musicIntent)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
|
||||||
if (Preferences.showNextAlarm) {
|
|
||||||
val nextAlarm = AlarmHelper.getNextAlarm(context)
|
|
||||||
if (nextAlarm != "") {
|
|
||||||
val alarmIntent = IntentHelper.getPendingIntent(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getClockIntent(context),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.sub_line_rect, alarmIntent)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
|
||||||
if (Preferences.showBatteryCharging) {
|
|
||||||
BatteryHelper.updateBatteryInfo(context)
|
|
||||||
if (Preferences.isCharging || Preferences.isBatteryLevelLow) {
|
|
||||||
val batteryIntent = IntentHelper.getPendingIntent(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getBatteryIntent(),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.sub_line_rect, batteryIntent)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
|
||||||
if (Preferences.customNotes.isNotEmpty()) {
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
|
||||||
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
|
|
||||||
val fitIntent = IntentHelper.getPendingIntent(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getFitIntent(context),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.sub_line_rect, fitIntent)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.NOTIFICATIONS -> {
|
|
||||||
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
|
|
||||||
try {
|
|
||||||
if (Preferences.lastNotificationIcon != 0) {
|
|
||||||
val remotePackageContext = context.createPackageContext(
|
|
||||||
Preferences.lastNotificationPackage, 0)
|
|
||||||
ContextCompat.getDrawable(
|
|
||||||
remotePackageContext,
|
|
||||||
Preferences.lastNotificationIcon)
|
|
||||||
}
|
|
||||||
val notificationIntent = IntentHelper.getPendingIntent(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getNotificationIntent(context),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(
|
|
||||||
R.id.sub_line_rect,
|
|
||||||
notificationIntent
|
|
||||||
)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
} catch (ex: Exception) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.GREETINGS -> {
|
|
||||||
if (Preferences.showGreetings && GreetingsHelper.showGreetings() && GreetingsHelper.getRandomString(context).isNotBlank()) {
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.EVENTS -> {
|
|
||||||
if (Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(
|
|
||||||
Manifest.permission.READ_CALENDAR) && nextEvent != null) {
|
|
||||||
val pIntentDetail = IntentHelper.getPendingIntent(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getEventIntent(
|
|
||||||
context,
|
|
||||||
nextEvent,
|
|
||||||
forceEventDetails = true
|
|
||||||
),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(
|
|
||||||
R.id.sub_line_rect,
|
|
||||||
pIntentDetail
|
|
||||||
)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.WEATHER -> {
|
|
||||||
if (Preferences.showWeatherAsGlanceProvider && Preferences.showWeather && Preferences.weatherIcon != "") {
|
|
||||||
val i = Intent(context, WidgetClickListenerReceiver::class.java)
|
|
||||||
i.action = Actions.ACTION_OPEN_WEATHER_INTENT
|
|
||||||
val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, PendingIntent.FLAG_IMMUTABLE)
|
|
||||||
|
|
||||||
views.setOnClickPendingIntent(
|
|
||||||
R.id.sub_line_rect,
|
|
||||||
weatherPIntent
|
|
||||||
)
|
|
||||||
|
|
||||||
showSomething = true
|
|
||||||
isWeatherShown = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (showSomething) {
|
|
||||||
views.setViewVisibility(R.id.first_line_rect, View.VISIBLE)
|
|
||||||
views.setViewVisibility(R.id.weather_rect, if (isWeatherShown) View.GONE else View.VISIBLE)
|
|
||||||
views.setViewVisibility(R.id.sub_line_rect, View.VISIBLE)
|
|
||||||
|
|
||||||
views.setViewVisibility(R.id.calendar_layout_rect, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.weather_sub_line_rect, View.GONE)
|
|
||||||
} else {
|
|
||||||
// Spacing
|
|
||||||
views.setViewVisibility(R.id.sub_line_top_margin_small_sans, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.sub_line_top_margin_medium_sans, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.sub_line_top_margin_large_sans, View.GONE)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
views.setViewVisibility(R.id.first_line_rect, View.VISIBLE)
|
|
||||||
views.setViewVisibility(R.id.weather_rect, View.VISIBLE)
|
|
||||||
|
|
||||||
views.setViewVisibility(R.id.calendar_layout_rect, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.sub_line_rect, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.weather_sub_line_rect, View.GONE)
|
|
||||||
// Spacing
|
|
||||||
views.setViewVisibility(R.id.sub_line_top_margin_small_sans, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.sub_line_top_margin_medium_sans, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.sub_line_top_margin_large_sans, View.GONE)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second row
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.sub_line_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(bindingView.subLine, draw = false, width = bindingView.subLine.width, height = bindingView.subLine.height)
|
|
||||||
)
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
return views
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Generates the widget bitmap from the view
|
|
||||||
private fun generateWidgetView(typeface: Typeface? = null): LeftAlignedWidgetBinding? {
|
|
||||||
try {
|
|
||||||
var isWeatherShownAsGlanceProvider = false
|
|
||||||
val eventRepository = EventRepository(context)
|
|
||||||
val nextEvent = eventRepository.getNextEvent()
|
|
||||||
val eventsCount = eventRepository.getEventsCount()
|
|
||||||
eventRepository.close()
|
|
||||||
|
|
||||||
val bindingView = LeftAlignedWidgetBinding.inflate(LayoutInflater.from(context))
|
|
||||||
|
|
||||||
bindingView.loader.isVisible = false
|
|
||||||
|
|
||||||
// Weather
|
|
||||||
if (Preferences.showWeather && Preferences.weatherIcon != "") {
|
|
||||||
bindingView.weatherDateLine.isVisible = true
|
|
||||||
val currentTemp = String.format(
|
|
||||||
Locale.getDefault(),
|
|
||||||
"%d°%s",
|
|
||||||
Preferences.weatherTemp.roundToInt(),
|
|
||||||
Preferences.weatherRealTempUnit
|
|
||||||
)
|
|
||||||
|
|
||||||
val icon: String = Preferences.weatherIcon
|
|
||||||
if (icon == "") {
|
|
||||||
bindingView.weatherSubLineWeatherIcon.isVisible = false
|
|
||||||
bindingView.weatherDateLineWeatherIcon.isVisible = false
|
|
||||||
} else {
|
|
||||||
bindingView.weatherSubLineWeatherIcon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon))
|
|
||||||
bindingView.weatherDateLineWeatherIcon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon))
|
|
||||||
bindingView.weatherSubLineWeatherIcon.isVisible = true
|
|
||||||
bindingView.weatherDateLineWeatherIcon.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
bindingView.weatherDateLineTemperature.text = currentTemp
|
|
||||||
bindingView.weatherSubLineTemperature.text = currentTemp
|
|
||||||
|
|
||||||
if (GlanceProviderHelper.showGlanceProviders(context)) {
|
|
||||||
bindingView.weatherSubLine.isVisible = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bindingView.weatherDateLine.isVisible = false
|
|
||||||
bindingView.weatherSubLine.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
val now = Calendar.getInstance().apply {
|
|
||||||
set(Calendar.SECOND, 0)
|
|
||||||
set(Calendar.MILLISECOND, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
bindingView.dateLayout.isVisible = true
|
|
||||||
bindingView.calendarLayout.isVisible = false
|
|
||||||
bindingView.nextEventDifferenceTime.isVisible = false
|
|
||||||
bindingView.actionNext.isVisible = false
|
|
||||||
|
|
||||||
bindingView.date.text = DateHelper.getDateText(context, now)
|
|
||||||
|
|
||||||
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null && !Preferences.showEventsAsGlanceProvider) {
|
|
||||||
// Multiple counter
|
|
||||||
bindingView.actionNext.isVisible =
|
|
||||||
Preferences.showNextEvent && eventsCount > 1
|
|
||||||
|
|
||||||
bindingView.nextEvent.text = nextEvent.title
|
|
||||||
|
|
||||||
if (Preferences.showNextEventOnMultipleLines) {
|
|
||||||
bindingView.nextEvent.apply {
|
|
||||||
isSingleLine = false
|
|
||||||
maxLines = 3
|
|
||||||
gravity = if (rightAligned) Gravity.END else Gravity.START
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Preferences.showDiffTime && now.timeInMillis < nextEvent.startDate) {
|
|
||||||
val diffTime = if (!nextEvent.allDay) {
|
|
||||||
SettingsStringHelper.getDifferenceText(
|
|
||||||
context,
|
|
||||||
now.timeInMillis,
|
|
||||||
nextEvent.startDate
|
|
||||||
).toLowerCase(Locale.getDefault())
|
|
||||||
} else {
|
|
||||||
SettingsStringHelper.getAllDayEventDifferenceText(
|
|
||||||
context,
|
|
||||||
now.timeInMillis,
|
|
||||||
nextEvent.startDate
|
|
||||||
).toLowerCase(Locale.getDefault())
|
|
||||||
}
|
|
||||||
bindingView.nextEventDifferenceTime.text = diffTime
|
|
||||||
|
|
||||||
if (!Preferences.showNextEventOnMultipleLines) {
|
|
||||||
bindingView.nextEventDifferenceTime.isVisible = true
|
|
||||||
} else {
|
|
||||||
val text = context.getString(R.string.events_glance_provider_format).format(nextEvent.title, diffTime)
|
|
||||||
if (text.endsWith(diffTime)) {
|
|
||||||
bindingView.nextEvent.addOnLayoutChangeListener { v, _, _, _, _, _, _, _, _ ->
|
|
||||||
(v as TextView).layout?.run {
|
|
||||||
val diff = diffTime.trimStart();
|
|
||||||
val diffStart = text.length - diff.length
|
|
||||||
if (getLineStart(lineCount - 1) > diffStart)
|
|
||||||
v.text = (text.substring(0, diffStart).trimEnd() + '\n' + diff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bindingView.nextEvent.text = text
|
|
||||||
bindingView.nextEventDifferenceTime.isVisible = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bindingView.nextEventDifferenceTime.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
|
|
||||||
bindingView.subLineIcon.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(
|
|
||||||
context,
|
|
||||||
R.drawable.round_place_24
|
|
||||||
)
|
|
||||||
)
|
|
||||||
bindingView.subLineText.text = nextEvent.address
|
|
||||||
} else {
|
|
||||||
bindingView.subLineIcon.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(
|
|
||||||
context,
|
|
||||||
R.drawable.round_today_24
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if (!nextEvent.allDay) {
|
|
||||||
val startHour =
|
|
||||||
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault())
|
|
||||||
.format(nextEvent.startDate)
|
|
||||||
val endHour =
|
|
||||||
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault())
|
|
||||||
.format(nextEvent.endDate)
|
|
||||||
|
|
||||||
var dayDiff =
|
|
||||||
TimeUnit.MILLISECONDS.toDays(nextEvent.endDate - nextEvent.startDate)
|
|
||||||
|
|
||||||
val startCal = Calendar.getInstance()
|
|
||||||
startCal.timeInMillis = nextEvent.startDate
|
|
||||||
|
|
||||||
val endCal = Calendar.getInstance()
|
|
||||||
endCal.timeInMillis = nextEvent.endDate
|
|
||||||
|
|
||||||
if (startCal.get(Calendar.HOUR_OF_DAY) > endCal.get(Calendar.HOUR_OF_DAY)) {
|
|
||||||
dayDiff++
|
|
||||||
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(
|
|
||||||
Calendar.MINUTE
|
|
||||||
) > endCal.get(Calendar.MINUTE)
|
|
||||||
) {
|
|
||||||
dayDiff++
|
|
||||||
}
|
|
||||||
var multipleDay = ""
|
|
||||||
if (dayDiff > 0) {
|
|
||||||
multipleDay = String.format(
|
|
||||||
" (+%s%s)",
|
|
||||||
dayDiff,
|
|
||||||
context.getString(R.string.day_char)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextEvent.startDate != nextEvent.endDate) {
|
|
||||||
bindingView.subLineText.text =
|
|
||||||
String.format("%s - %s%s", startHour, endHour, multipleDay)
|
|
||||||
} else {
|
|
||||||
bindingView.subLineText.text =
|
|
||||||
String.format("%s", startHour)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
val start = Calendar.getInstance().apply { timeInMillis = nextEvent.startDate }
|
|
||||||
|
|
||||||
bindingView.subLineText.text = if (now.after(start)) {
|
|
||||||
DateHelper.getDateText(context, now)
|
|
||||||
} else {
|
|
||||||
DateHelper.getDateText(context, start)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bindingView.dateLayout.isVisible = false
|
|
||||||
bindingView.calendarLayout.isVisible = true
|
|
||||||
bindingView.subLine.isVisible = true
|
|
||||||
bindingView.weatherSubLine.isVisible = Preferences.showWeather && Preferences.weatherIcon != ""
|
|
||||||
|
|
||||||
bindingView.subLineTopMarginSmall.visibility =
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.rawValue) View.VISIBLE else View.GONE
|
|
||||||
bindingView.subLineTopMarginMedium.visibility =
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.rawValue) View.VISIBLE else View.GONE
|
|
||||||
bindingView.subLineTopMarginLarge.visibility =
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.rawValue) View.VISIBLE else View.GONE
|
|
||||||
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
|
|
||||||
bindingView.subLineIcon.isVisible = true
|
|
||||||
var showSomething = false
|
|
||||||
loop@ for (provider: Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(
|
|
||||||
context
|
|
||||||
)) {
|
|
||||||
when (provider) {
|
|
||||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
|
||||||
if (MediaPlayerHelper.isSomeonePlaying(context)) {
|
|
||||||
bindingView.subLineIcon.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(
|
|
||||||
context,
|
|
||||||
R.drawable.round_music_note_24
|
|
||||||
)
|
|
||||||
)
|
|
||||||
bindingView.subLineText.text = MediaPlayerHelper.getMediaInfo()
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
|
||||||
if (Preferences.showNextAlarm) {
|
|
||||||
val nextAlarm = AlarmHelper.getNextAlarm(context)
|
|
||||||
if (nextAlarm != "") {
|
|
||||||
bindingView.subLineIcon.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(
|
|
||||||
context,
|
|
||||||
R.drawable.round_alarm_24
|
|
||||||
)
|
|
||||||
)
|
|
||||||
bindingView.subLineText.text = nextAlarm
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
|
||||||
if (Preferences.showBatteryCharging) {
|
|
||||||
BatteryHelper.updateBatteryInfo(context)
|
|
||||||
if (Preferences.isCharging) {
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
val batteryLevel = BatteryHelper.getBatteryLevel(context)
|
|
||||||
if (batteryLevel != 100) {
|
|
||||||
bindingView.subLineText.text = context.getString(R.string.charging)
|
|
||||||
} else {
|
|
||||||
bindingView.subLineText.text =
|
|
||||||
context.getString(R.string.charged)
|
|
||||||
}
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
} else if (Preferences.isBatteryLevelLow) {
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
bindingView.subLineText.text =
|
|
||||||
context.getString(R.string.battery_low_warning)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
|
||||||
if (Preferences.customNotes.isNotEmpty()) {
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
bindingView.subLineText.text = Preferences.customNotes
|
|
||||||
bindingView.subLineText.maxLines = 2
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
|
||||||
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
bindingView.subLineText.text =
|
|
||||||
context.getString(R.string.daily_steps_counter)
|
|
||||||
.format(Preferences.googleFitSteps)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.NOTIFICATIONS -> {
|
|
||||||
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
|
|
||||||
try {
|
|
||||||
if (Preferences.lastNotificationIcon != 0) {
|
|
||||||
val remotePackageContext = context.createPackageContext(
|
|
||||||
Preferences.lastNotificationPackage, 0)
|
|
||||||
val icon = ContextCompat.getDrawable(remotePackageContext,
|
|
||||||
Preferences.lastNotificationIcon)
|
|
||||||
bindingView.subLineIcon.isVisible = true
|
|
||||||
bindingView.subLineIcon.setImageDrawable(icon)
|
|
||||||
} else {
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
}
|
|
||||||
bindingView.subLineText.text = Preferences.lastNotificationTitle
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
} catch (ex: Exception) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.GREETINGS -> {
|
|
||||||
val greetingsText = GreetingsHelper.getRandomString(context)
|
|
||||||
if (Preferences.showGreetings && GreetingsHelper.showGreetings() && greetingsText.isNotBlank()) {
|
|
||||||
bindingView.subLineText.text = greetingsText
|
|
||||||
bindingView.subLineText.maxLines = 2
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.EVENTS -> {
|
|
||||||
if (Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(
|
|
||||||
Manifest.permission.READ_CALENDAR) && nextEvent != null) {
|
|
||||||
bindingView.subLineText.text = context.getString(R.string.events_glance_provider_format).format(nextEvent.title, if (Preferences.showDiffTime && now.timeInMillis < nextEvent.startDate) {
|
|
||||||
if (!nextEvent.allDay) {
|
|
||||||
SettingsStringHelper.getDifferenceText(
|
|
||||||
context,
|
|
||||||
now.timeInMillis,
|
|
||||||
nextEvent.startDate
|
|
||||||
).toLowerCase(Locale.getDefault())
|
|
||||||
} else {
|
|
||||||
SettingsStringHelper.getAllDayEventDifferenceText(
|
|
||||||
context,
|
|
||||||
now.timeInMillis,
|
|
||||||
nextEvent.startDate
|
|
||||||
).toLowerCase(Locale.getDefault())
|
|
||||||
}
|
|
||||||
} else "").trimEnd()
|
|
||||||
bindingView.subLineIcon.isVisible = true
|
|
||||||
bindingView.subLineIcon.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(
|
|
||||||
context,
|
|
||||||
R.drawable.round_today_24
|
|
||||||
)
|
|
||||||
)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.WEATHER -> {
|
|
||||||
if (Preferences.showWeatherAsGlanceProvider && Preferences.showWeather && Preferences.weatherIcon != "") {
|
|
||||||
bindingView.subLineText.text = String.format(
|
|
||||||
Locale.getDefault(),
|
|
||||||
"%d°%s %s",
|
|
||||||
Preferences.weatherTemp.roundToInt(),
|
|
||||||
Preferences.weatherRealTempUnit,
|
|
||||||
WeatherHelper.getWeatherLabel(context, Preferences.weatherIcon)
|
|
||||||
)
|
|
||||||
bindingView.subLineIcon.isVisible = true
|
|
||||||
|
|
||||||
val icon: String = Preferences.weatherIcon
|
|
||||||
if (icon == "") {
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
} else {
|
|
||||||
bindingView.subLineIcon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon))
|
|
||||||
bindingView.subLineIcon.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
bindingView.weatherDateLine.isVisible = false
|
|
||||||
bindingView.weatherSubLine.isVisible = false
|
|
||||||
|
|
||||||
showSomething = true
|
|
||||||
isWeatherShownAsGlanceProvider = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (showSomething) {
|
|
||||||
bindingView.dateLayout.isVisible = true
|
|
||||||
bindingView.calendarLayout.isVisible = false
|
|
||||||
bindingView.subLine.isVisible = true
|
|
||||||
bindingView.weatherSubLine.isVisible = false
|
|
||||||
|
|
||||||
bindingView.subLineTopMarginSmall.visibility =
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.rawValue) View.VISIBLE else View.GONE
|
|
||||||
bindingView.subLineTopMarginMedium.visibility =
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.rawValue) View.VISIBLE else View.GONE
|
|
||||||
bindingView.subLineTopMarginLarge.visibility =
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.rawValue) View.VISIBLE else View.GONE
|
|
||||||
} else {
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Color
|
|
||||||
listOf<TextView>(
|
|
||||||
bindingView.date,
|
|
||||||
bindingView.weatherDateLineTemperature,
|
|
||||||
bindingView.nextEvent,
|
|
||||||
bindingView.nextEventDifferenceTime,
|
|
||||||
).forEach {
|
|
||||||
it.setTextColor(ColorHelper.getFontColor(context.applicationContext.isDarkTheme()))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.rawValue) {
|
|
||||||
listOf<ImageView>(bindingView.actionNext)
|
|
||||||
} else {
|
|
||||||
listOf<ImageView>(
|
|
||||||
bindingView.actionNext,
|
|
||||||
bindingView.weatherDateLineWeatherIcon,
|
|
||||||
bindingView.weatherSubLineWeatherIcon
|
|
||||||
)
|
|
||||||
}.forEach {
|
|
||||||
it.setColorFilter(ColorHelper.getFontColorRgb(context.applicationContext.isDarkTheme()))
|
|
||||||
it.alpha =
|
|
||||||
(if (context.isDarkTheme()) Preferences.textGlobalAlphaDark.toIntValue()
|
|
||||||
.toFloat() else Preferences.textGlobalAlpha.toIntValue()
|
|
||||||
.toFloat()) / 100
|
|
||||||
}
|
|
||||||
|
|
||||||
listOf<TextView>(bindingView.subLineText, bindingView.weatherSubLineDivider, bindingView.weatherSubLineTemperature).forEach {
|
|
||||||
it.setTextColor(ColorHelper.getSecondaryFontColor(context.applicationContext.isDarkTheme()))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isWeatherShownAsGlanceProvider) {
|
|
||||||
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.rawValue) {
|
|
||||||
listOf<ImageView>(bindingView.subLineIcon, bindingView.subLineIconShadow)
|
|
||||||
} else {
|
|
||||||
listOf<ImageView>(
|
|
||||||
bindingView.subLineIcon,
|
|
||||||
bindingView.weatherSubLineWeatherIcon,
|
|
||||||
bindingView.subLineIconShadow
|
|
||||||
)
|
|
||||||
}.forEach {
|
|
||||||
it.setColorFilter(ColorHelper.getSecondaryFontColorRgb(context.applicationContext.isDarkTheme()))
|
|
||||||
it.alpha =
|
|
||||||
(if (context.isDarkTheme()) Preferences.textSecondaryAlphaDark.toIntValue()
|
|
||||||
.toFloat() else Preferences.textSecondaryAlpha.toIntValue()
|
|
||||||
.toFloat()) / 100
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Text Size
|
|
||||||
listOf<Pair<TextView, Float>>(
|
|
||||||
bindingView.date to Preferences.textMainSize,
|
|
||||||
bindingView.weatherDateLineTemperature to ((Preferences.textMainSize + Preferences.textSecondSize) / 2),
|
|
||||||
bindingView.nextEvent to Preferences.textMainSize,
|
|
||||||
bindingView.nextEventDifferenceTime to Preferences.textMainSize,
|
|
||||||
bindingView.subLineText to Preferences.textSecondSize,
|
|
||||||
bindingView.weatherSubLineDivider to (Preferences.textSecondSize * 0.9f),
|
|
||||||
bindingView.weatherSubLineTemperature to Preferences.textSecondSize,
|
|
||||||
).forEach {
|
|
||||||
it.first.setTextSize(TypedValue.COMPLEX_UNIT_SP, it.second)
|
|
||||||
if (!it.first.includeFontPadding && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P)
|
|
||||||
it.first.isFallbackLineSpacing = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Icons scale
|
|
||||||
listOf(
|
|
||||||
bindingView.subLineIcon to Preferences.textSecondSize / 16f,
|
|
||||||
bindingView.subLineIconShadow to Preferences.textSecondSize / 16f,
|
|
||||||
bindingView.weatherSubLineWeatherIcon to Preferences.textSecondSize / 16f,
|
|
||||||
bindingView.weatherDateLineWeatherIcon to ((Preferences.textMainSize + Preferences.textSecondSize) / 2) / 24f,
|
|
||||||
bindingView.actionNext to Preferences.textMainSize / 24f,
|
|
||||||
bindingView.actionNextShadow to Preferences.textMainSize / 24f
|
|
||||||
).forEach {
|
|
||||||
if (it.first.tag == null)
|
|
||||||
it.first.tag = it.first.layoutParams.height
|
|
||||||
it.first.layoutParams = it.first.layoutParams.apply {
|
|
||||||
height = ((it.first.tag as Int) * it.second).roundToInt()
|
|
||||||
width = height
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Shadows
|
|
||||||
val shadowRadius =
|
|
||||||
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
|
||||||
0 -> 0f
|
|
||||||
1 -> 2f
|
|
||||||
2 -> 3f
|
|
||||||
else -> 2f
|
|
||||||
}.toPixel(context)
|
|
||||||
val shadowColor =
|
|
||||||
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
|
||||||
0 -> Color.TRANSPARENT
|
|
||||||
1 -> Color.DKGRAY
|
|
||||||
2 -> Color.BLACK
|
|
||||||
else -> Color.DKGRAY
|
|
||||||
}
|
|
||||||
val shadowOffset =
|
|
||||||
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
|
||||||
0 -> 0f
|
|
||||||
1 -> 0f
|
|
||||||
2 -> 0.5f
|
|
||||||
else -> 0f
|
|
||||||
}.toPixel(context)
|
|
||||||
|
|
||||||
listOf<TextView>(
|
|
||||||
bindingView.date,
|
|
||||||
bindingView.weatherDateLineTemperature,
|
|
||||||
bindingView.nextEvent,
|
|
||||||
bindingView.nextEventDifferenceTime,
|
|
||||||
bindingView.subLineText,
|
|
||||||
bindingView.weatherSubLineDivider,
|
|
||||||
bindingView.weatherSubLineTemperature,
|
|
||||||
).forEach {
|
|
||||||
it.setShadowLayer(shadowRadius, shadowOffset, shadowOffset, shadowColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Icons shadow
|
|
||||||
|
|
||||||
listOf(
|
|
||||||
Pair(bindingView.subLineIcon, bindingView.subLineIconShadow),
|
|
||||||
).forEach {
|
|
||||||
if ((if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) == 0) {
|
|
||||||
it.second.isVisible = false
|
|
||||||
} else {
|
|
||||||
it.second.isVisible = it.first.isVisible
|
|
||||||
it.second.scaleX = it.first.scaleX
|
|
||||||
it.second.scaleY = it.first.scaleY
|
|
||||||
it.second.applyShadow(it.first, 0.8f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
listOf(
|
|
||||||
Pair(bindingView.actionNext, bindingView.actionNextShadow),
|
|
||||||
).forEach {
|
|
||||||
if ((if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) == 0) {
|
|
||||||
it.second.isVisible = false
|
|
||||||
} else {
|
|
||||||
it.second.isVisible = it.first.isVisible
|
|
||||||
it.second.scaleX = it.first.scaleX
|
|
||||||
it.second.scaleY = it.first.scaleY
|
|
||||||
it.second.applyShadow(it.first, 0.6f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom Font
|
|
||||||
if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) {
|
|
||||||
val googleSans: Typeface? = androidx.core.content.res.ResourcesCompat.getFont(
|
|
||||||
context,
|
|
||||||
when (Preferences.customFontVariant) {
|
|
||||||
"100" -> R.font.google_sans_thin
|
|
||||||
"200" -> R.font.google_sans_light
|
|
||||||
"500" -> R.font.google_sans_medium
|
|
||||||
"700" -> R.font.google_sans_bold
|
|
||||||
"800" -> R.font.google_sans_black
|
|
||||||
else -> R.font.google_sans_regular
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
listOf<TextView>(
|
|
||||||
bindingView.date,
|
|
||||||
bindingView.weatherDateLineTemperature,
|
|
||||||
bindingView.nextEvent,
|
|
||||||
bindingView.nextEventDifferenceTime,
|
|
||||||
bindingView.subLineText,
|
|
||||||
bindingView.weatherSubLineDivider,
|
|
||||||
bindingView.weatherSubLineTemperature,
|
|
||||||
).forEach {
|
|
||||||
it.typeface = googleSans
|
|
||||||
}
|
|
||||||
} else if (Preferences.customFont == Constants.CUSTOM_FONT_DOWNLOADED && typeface != null) {
|
|
||||||
listOf<TextView>(
|
|
||||||
bindingView.date,
|
|
||||||
bindingView.weatherDateLineTemperature,
|
|
||||||
bindingView.nextEvent,
|
|
||||||
bindingView.nextEventDifferenceTime,
|
|
||||||
bindingView.subLineText,
|
|
||||||
bindingView.weatherSubLineDivider,
|
|
||||||
bindingView.weatherSubLineTemperature,
|
|
||||||
).forEach {
|
|
||||||
it.typeface = typeface
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dividers
|
|
||||||
arrayOf(bindingView.weatherSubLineDivider).forEach {
|
|
||||||
it.visibility = if (Preferences.showDividers) View.VISIBLE else View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
// Right Aligned
|
|
||||||
if (rightAligned) {
|
|
||||||
bindingView.mainContent.layoutParams = (bindingView.mainContent.layoutParams as RelativeLayout.LayoutParams).apply {
|
|
||||||
addRule(RelativeLayout.ALIGN_PARENT_END)
|
|
||||||
}
|
|
||||||
bindingView.mainContent.gravity = Gravity.END
|
|
||||||
bindingView.dateLayout.gravity = Gravity.END
|
|
||||||
bindingView.date.gravity = Gravity.END
|
|
||||||
bindingView.calendarLayout.gravity = Gravity.END or Gravity.CENTER_VERTICAL
|
|
||||||
bindingView.nextEvent.gravity = Gravity.END
|
|
||||||
bindingView.subLineContainer.gravity = Gravity.END or Gravity.CENTER_VERTICAL
|
|
||||||
bindingView.subLineText.gravity = Gravity.END
|
|
||||||
}
|
|
||||||
|
|
||||||
return bindingView
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,115 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.widgets
|
|
||||||
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.RemoteViews
|
|
||||||
import com.tommasoberlose.anotherwidget.R
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
|
||||||
|
|
||||||
class ClockWidget(val context: Context) {
|
|
||||||
fun updateClockView(views: RemoteViews, widgetID: Int): RemoteViews {
|
|
||||||
try {
|
|
||||||
if (!Preferences.showClock) {
|
|
||||||
views.setViewVisibility(R.id.time, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.time_am_pm, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.clock_bottom_margin_none, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.clock_bottom_margin_small, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.clock_bottom_margin_medium, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.clock_bottom_margin_large, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.timezones_container, View.GONE)
|
|
||||||
} else {
|
|
||||||
views.setTextColor(R.id.time, ColorHelper.getClockFontColor(context.isDarkTheme()))
|
|
||||||
views.setTextColor(R.id.time_am_pm, ColorHelper.getClockFontColor(context.isDarkTheme()))
|
|
||||||
views.setTextViewTextSize(
|
|
||||||
R.id.time,
|
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
|
||||||
Preferences.clockTextSize
|
|
||||||
)
|
|
||||||
views.setTextViewTextSize(
|
|
||||||
R.id.time_am_pm,
|
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
|
||||||
Preferences.clockTextSize / 5 * 2
|
|
||||||
)
|
|
||||||
val clockPIntent = IntentHelper.getPendingIntent(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getClockIntent(context),
|
|
||||||
PendingIntent.FLAG_IMMUTABLE
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.time, clockPIntent)
|
|
||||||
views.setOnClickPendingIntent(R.id.time_am_pm, clockPIntent)
|
|
||||||
views.setViewVisibility(R.id.time, View.VISIBLE)
|
|
||||||
views.setViewVisibility(R.id.time_am_pm, if (Preferences.showAMPMIndicator) View.VISIBLE else View.GONE)
|
|
||||||
|
|
||||||
views.setViewVisibility(
|
|
||||||
R.id.clock_bottom_margin_none,
|
|
||||||
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.rawValue) View.VISIBLE else View.GONE
|
|
||||||
)
|
|
||||||
views.setViewVisibility(
|
|
||||||
R.id.clock_bottom_margin_small,
|
|
||||||
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.rawValue) View.VISIBLE else View.GONE
|
|
||||||
)
|
|
||||||
views.setViewVisibility(
|
|
||||||
R.id.clock_bottom_margin_medium,
|
|
||||||
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.rawValue) View.VISIBLE else View.GONE
|
|
||||||
)
|
|
||||||
views.setViewVisibility(
|
|
||||||
R.id.clock_bottom_margin_large,
|
|
||||||
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.rawValue) View.VISIBLE else View.GONE
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
// Timezones
|
|
||||||
if (Preferences.altTimezoneId != "" && Preferences.altTimezoneLabel != "") {
|
|
||||||
views.setString(R.id.alt_timezone_time, "setTimeZone", Preferences.altTimezoneId)
|
|
||||||
views.setString(R.id.alt_timezone_time_am_pm, "setTimeZone", Preferences.altTimezoneId)
|
|
||||||
views.setTextViewText(R.id.alt_timezone_label, Preferences.altTimezoneLabel)
|
|
||||||
|
|
||||||
views.setTextColor(R.id.alt_timezone_time, ColorHelper.getClockFontColor(context.isDarkTheme()))
|
|
||||||
views.setTextColor(R.id.alt_timezone_time_am_pm, ColorHelper.getClockFontColor(context.isDarkTheme()))
|
|
||||||
views.setTextColor(R.id.alt_timezone_label, ColorHelper.getClockFontColor(context.isDarkTheme()))
|
|
||||||
views.setTextViewTextSize(
|
|
||||||
R.id.alt_timezone_time,
|
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
|
||||||
Preferences.clockTextSize / 3
|
|
||||||
)
|
|
||||||
views.setTextViewTextSize(
|
|
||||||
R.id.alt_timezone_time_am_pm,
|
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
|
||||||
(Preferences.clockTextSize / 3) / 5 * 2
|
|
||||||
)
|
|
||||||
views.setTextViewTextSize(
|
|
||||||
R.id.alt_timezone_label,
|
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
|
||||||
(Preferences.clockTextSize / 3) / 5 * 2
|
|
||||||
)
|
|
||||||
|
|
||||||
val padding = (TypedValue.applyDimension(
|
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
|
||||||
Preferences.clockTextSize,
|
|
||||||
context.resources.displayMetrics
|
|
||||||
) * 0.2).toInt()
|
|
||||||
if (Preferences.widgetAlign == Constants.WidgetAlign.RIGHT.rawValue)
|
|
||||||
views.setViewPadding(R.id.timezones_container, 0, padding, padding, 0)
|
|
||||||
else
|
|
||||||
views.setViewPadding(R.id.timezones_container, padding, padding, 0,0)
|
|
||||||
|
|
||||||
views.setOnClickPendingIntent(R.id.timezones_container, clockPIntent)
|
|
||||||
views.setViewVisibility(R.id.timezones_container, View.VISIBLE)
|
|
||||||
} else {
|
|
||||||
views.setViewVisibility(R.id.timezones_container, View.GONE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
}
|
|
||||||
|
|
||||||
return views
|
|
||||||
}
|
|
||||||
}
|
|
@ -21,23 +21,18 @@ import android.content.res.Resources
|
|||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.animation.AlphaAnimation
|
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import androidx.annotation.UiThread
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
|
||||||
import androidx.browser.customtabs.CustomTabColorSchemeParams
|
import androidx.browser.customtabs.CustomTabColorSchemeParams
|
||||||
import androidx.core.animation.addListener
|
import androidx.core.animation.addListener
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.components.OnSingleClickListener
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
fun PackageManager.missingSystemFeature(name: String): Boolean = !hasSystemFeature(name)
|
fun PackageManager.missingSystemFeature(name: String): Boolean = !hasSystemFeature(name)
|
||||||
|
|
||||||
fun Context.toast(message: String, long: Boolean = false) {
|
fun Context.toast(message: String, long: Boolean = false) {
|
||||||
val toast = Toast.makeText(applicationContext, message, if (long) Toast.LENGTH_LONG else Toast.LENGTH_SHORT)
|
val toast = Toast.makeText(this, message, if (long) Toast.LENGTH_LONG else Toast.LENGTH_SHORT)
|
||||||
// toast.setGravity(Gravity.CENTER, 0, 0)
|
// toast.setGravity(Gravity.CENTER, 0, 0)
|
||||||
toast.show()
|
toast.show()
|
||||||
}
|
}
|
||||||
@ -194,7 +189,7 @@ fun String.isValidEmail(): Boolean
|
|||||||
Patterns.EMAIL_ADDRESS.matcher(this).matches()
|
Patterns.EMAIL_ADDRESS.matcher(this).matches()
|
||||||
|
|
||||||
fun Context.isDarkTheme(): Boolean {
|
fun Context.isDarkTheme(): Boolean {
|
||||||
return Preferences.darkThemePreference == AppCompatDelegate.MODE_NIGHT_YES || Preferences.darkThemePreference == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM && resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
|
return resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Activity.isNotificationAccessGranted(): Boolean = Settings.Secure.getString(this.contentResolver,"enabled_notification_listeners").contains(this.packageName)
|
fun Activity.isNotificationAccessGranted(): Boolean = Settings.Secure.getString(this.contentResolver,"enabled_notification_listeners").contains(this.packageName)
|
||||||
@ -214,14 +209,6 @@ fun Context.checkGrantedPermission(permission: String): Boolean {
|
|||||||
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
|
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
|
||||||
}
|
}
|
||||||
|
|
||||||
fun android.app.AlarmManager.setExactIfCanSchedule(type: Int, triggerAtMillis: Long, operation: android.app.PendingIntent) {
|
|
||||||
// uncomment the following check after bumping compileSdkVersion/targetSdkVersion to 31
|
|
||||||
//if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.S || canScheduleExactAlarms())
|
|
||||||
setExact(type, triggerAtMillis, operation)
|
|
||||||
//else
|
|
||||||
// set(type, triggerAtMillis, operation)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Context.getCurrentWallpaper(): Drawable? = try {
|
fun Context.getCurrentWallpaper(): Drawable? = try {
|
||||||
WallpaperManager.getInstance(this).drawable
|
WallpaperManager.getInstance(this).drawable
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@ -266,20 +253,4 @@ fun Locale.isMetric(): Boolean {
|
|||||||
"US", "LR", "MM", "GB" -> false
|
"US", "LR", "MM", "GB" -> false
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun View.setOnSingleClickListener(l: View.OnClickListener) {
|
|
||||||
setOnClickListener(OnSingleClickListener(l))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun View.setOnSingleClickListener(l: (View) -> Unit) {
|
|
||||||
setOnClickListener(OnSingleClickListener(l))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ignoreExceptions(function: () -> Unit) = run {
|
|
||||||
try {
|
|
||||||
function.invoke()
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 750 B After Width: | Height: | Size: 674 B |