Compare commits
120 Commits
v2.0.12
...
v2.0.15-be
Author | SHA1 | Date | |
---|---|---|---|
56d95c5559 | |||
c0e747a714 | |||
16076dc145 | |||
c95f9fb943 | |||
331d5772af | |||
e2719b6445 | |||
bd35022f7d | |||
6d9cb750a7 | |||
f85b4c9a6a | |||
df54a4a79e | |||
6ea97e7724 | |||
d27071739d | |||
738781225f | |||
12d32f852b | |||
f0baa60363 | |||
785eb39334 | |||
d289699d08 | |||
c68d0a8327 | |||
de2e223713 | |||
6150dd7e22 | |||
d9ecebe770 | |||
52327715b1 | |||
e301e6e6ec | |||
c884fae362 | |||
eb78257e52 | |||
109aa24af1 | |||
2403f066a3 | |||
9bc7d7b62e | |||
a1a6f9f607 | |||
815a88a079 | |||
1c1f55e20a | |||
5259a81cfb | |||
3b963dae1c | |||
878ddcb05e | |||
0ce446f0ef | |||
c5fefb0e06 | |||
c5eb5358aa | |||
c4a16224f0 | |||
122c0627d9 | |||
6d80ec97a8 | |||
1c7df585fe | |||
9f4cdc950b | |||
0a0c5a90a7 | |||
011517e12d | |||
fdd82e0f91 | |||
abafe108c6 | |||
03f08e4f08 | |||
9ecb9b4819 | |||
2bb30aae69 | |||
01d219d38c | |||
6c7831d972 | |||
4ab12e33c7 | |||
364198ef08 | |||
2c81c7cfd2 | |||
3b723e5a1b | |||
6a912ee003 | |||
1644fb7682 | |||
bd4869540b | |||
31103303be | |||
e9c0cdd61c | |||
59e42029e8 | |||
b2ef2adb2a | |||
bab92f9169 | |||
cb480ed4ee | |||
6f83a45865 | |||
9e528e1f6f | |||
20d3ae0e32 | |||
ecea1265e7 | |||
c38b7a335c | |||
6ab8e40d45 | |||
d14dfee980 | |||
0a454f0b5f | |||
b7bc93e174 | |||
1dee4cc8e5 | |||
02b521c0b8 | |||
c04040e242 | |||
a208aa97b2 | |||
e3fda9457e | |||
b84631a2b2 | |||
bad06c5762 | |||
74d8966f0a | |||
d8a76936a6 | |||
e72ca4fc6f | |||
dd62212b06 | |||
8dfc12e412 | |||
2762f12151 | |||
a873c71918 | |||
e8f3c110a8 | |||
72bf3b04a7 | |||
ca6fb75dfd | |||
59dc5de21a | |||
ec40a277d7 | |||
507b7f2318 | |||
1a709a9406 | |||
770ba0cd13 | |||
6a92225edf | |||
ce801d4a7d | |||
25da807bd5 | |||
63212d13b1 | |||
79ad9b2500 | |||
9c0aa0a9ef | |||
b9197ddf2e | |||
d1362f7d81 | |||
a8c7d115ae | |||
a5a753e198 | |||
39ede20518 | |||
5527e6e405 | |||
565ed11f53 | |||
4bd8653d32 | |||
d121119ca9 | |||
e82a34bcc7 | |||
8867a1fbbd | |||
7265883d6c | |||
7a4fc6ff58 | |||
9f61215caa | |||
7ccf7eb8f6 | |||
704448a848 | |||
fa366b3d45 | |||
e58fef66aa | |||
c120bad9c6 |
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
|
patreon: # Replace with a single Patreon username
|
||||||
|
open_collective: # Replace with a single Open Collective username
|
||||||
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||||
|
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||||
|
liberapay: # Replace with a single Liberapay username
|
||||||
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
|
otechie: # Replace with a single Otechie username
|
||||||
|
custom: ['paypal.me/tommasoberlose']
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,3 +8,4 @@
|
|||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
/tasksintegration/build
|
/tasksintegration/build
|
||||||
/app/google-services.json
|
/app/google-services.json
|
||||||
|
apikey.properties
|
BIN
.idea/caches/build_file_checksums.ser
generated
BIN
.idea/caches/build_file_checksums.ser
generated
Binary file not shown.
17
.idea/codeStyles/Project.xml
generated
17
.idea/codeStyles/Project.xml
generated
@ -1,6 +1,23 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
<code_scheme name="Project" version="173">
|
<code_scheme name="Project" version="173">
|
||||||
<JetCodeStyleSettings>
|
<JetCodeStyleSettings>
|
||||||
|
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||||
|
<value>
|
||||||
|
<package name="java.util" alias="false" withSubpackages="false" />
|
||||||
|
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||||
|
<package name="io.ktor" alias="false" withSubpackages="true" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||||
|
<value>
|
||||||
|
<package name="" alias="false" withSubpackages="true" />
|
||||||
|
<package name="java" alias="false" withSubpackages="true" />
|
||||||
|
<package name="javax" alias="false" withSubpackages="true" />
|
||||||
|
<package name="kotlin" alias="false" withSubpackages="true" />
|
||||||
|
<package name="" alias="true" withSubpackages="true" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<option name="ALLOW_TRAILING_COMMA" value="true" />
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||||
</JetCodeStyleSettings>
|
</JetCodeStyleSettings>
|
||||||
<codeStyleSettings language="XML">
|
<codeStyleSettings language="XML">
|
||||||
|
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
@ -14,6 +14,7 @@
|
|||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
<option name="resolveModulePerSourceSet" value="false" />
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
|
<option name="useQualifiedModuleNames" value="true" />
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -61,7 +61,7 @@
|
|||||||
</profile-state>
|
</profile-state>
|
||||||
</entry>
|
</entry>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" 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">
|
||||||
|
4
.idea/modules.xml
generated
4
.idea/modules.xml
generated
@ -2,8 +2,8 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectModuleManager">
|
<component name="ProjectModuleManager">
|
||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/Another Widget.iml" filepath="$PROJECT_DIR$/Another Widget.iml" group="Another Widget" />
|
<module fileurl="file://$PROJECT_DIR$/.idea/modules/Another_Widget.iml" filepath="$PROJECT_DIR$/.idea/modules/Another_Widget.iml" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" group="Another Widget/app" />
|
<module fileurl="file://$PROJECT_DIR$/.idea/modules/app/Another_Widget.app.iml" filepath="$PROJECT_DIR$/.idea/modules/app/Another_Widget.app.iml" />
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -11,7 +11,7 @@ While respecting the design of the application, there is a great opportunity to
|
|||||||
Also, as much as possible, there are always updates and new features in the short run.
|
Also, as much as possible, there are always updates and new features in the short run.
|
||||||
|
|
||||||
Help me developing with feedback and support me on how you can.
|
Help me developing with feedback and support me on how you can.
|
||||||
<div style="text-align:center"><a href="https://play.google.com/store/apps/details?id=com.tommasoberlose.anotherwidget" target="_blank"><img src="google-play-badge.png" height="100" /></a></div>
|
<div style="text-align:center"><a href='https://play.google.com/store/apps/details?id=com.tommasoberlose.anotherwidget&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height='100px' src='https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png'/></a></div>
|
||||||
|
|
||||||
|
|
||||||
Help with translations
|
Help with translations
|
||||||
|
@ -10,7 +10,12 @@ apply plugin: 'kotlin-android-extensions'
|
|||||||
|
|
||||||
apply plugin: 'realm-android'
|
apply plugin: 'realm-android'
|
||||||
|
|
||||||
|
def apikeyPropertiesFile = rootProject.file("apikey.properties")
|
||||||
|
def apikeyProperties = new Properties()
|
||||||
|
apikeyProperties.load(new FileInputStream(apikeyPropertiesFile))
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|
||||||
compileSdkVersion 29
|
compileSdkVersion 29
|
||||||
buildToolsVersion "29.0.3"
|
buildToolsVersion "29.0.3"
|
||||||
|
|
||||||
@ -18,10 +23,13 @@ android {
|
|||||||
applicationId "com.tommasoberlose.anotherwidget"
|
applicationId "com.tommasoberlose.anotherwidget"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 101
|
versionCode 109
|
||||||
versionName "2.0.12"
|
versionName "2.0.15"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY'])
|
||||||
|
|
||||||
|
renderscriptSupportModeEnabled true
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@ -58,14 +66,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'
|
testImplementation 'junit:junit:4.13.1'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
|
||||||
implementation 'com.google.android.material:material:1.2.0-alpha06'
|
implementation 'com.google.android.material:material:1.3.0-alpha03'
|
||||||
implementation 'androidx.browser:browser:1.2.0'
|
implementation 'androidx.browser:browser:1.2.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'
|
||||||
@ -75,18 +83,18 @@ dependencies {
|
|||||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
|
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.3.4"
|
implementation "androidx.work:work-runtime-ktx:2.4.0"
|
||||||
|
|
||||||
// EventBus
|
// EventBus
|
||||||
implementation 'org.greenrobot:eventbus:3.1.1'
|
implementation 'org.greenrobot:eventbus:3.2.0'
|
||||||
|
|
||||||
// Navigation
|
// Navigation
|
||||||
implementation 'androidx.navigation:navigation-fragment:2.3.0-alpha05'
|
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
|
||||||
implementation 'androidx.navigation:navigation-ui-ktx:2.2.2'
|
implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
implementation 'androidx.multidex:multidex:2.0.1'
|
implementation 'androidx.multidex:multidex:2.0.1'
|
||||||
implementation 'joda-time:joda-time:2.9.9'
|
implementation 'joda-time:joda-time:2.10.6'
|
||||||
implementation 'me.everything:providers-android:1.0.1'
|
implementation 'me.everything:providers-android:1.0.1'
|
||||||
implementation 'com.github.warkiz.widget:indicatorseekbar:2.1.2'
|
implementation 'com.github.warkiz.widget:indicatorseekbar:2.1.2'
|
||||||
|
|
||||||
@ -96,34 +104,43 @@ dependencies {
|
|||||||
|
|
||||||
// Fitness
|
// Fitness
|
||||||
implementation 'com.google.android.gms:play-services-fitness:18.0.0'
|
implementation 'com.google.android.gms:play-services-fitness:18.0.0'
|
||||||
implementation 'com.google.android.gms:play-services-auth:18.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.0.0'
|
implementation 'com.google.android.gms:play-services-location:17.1.0'
|
||||||
|
|
||||||
// Billing
|
// Billing
|
||||||
implementation 'com.android.billingclient:billing:2.2.0'
|
implementation 'com.android.billingclient:billing:3.0.1'
|
||||||
implementation 'com.android.billingclient:billing-ktx:2.2.0'
|
implementation 'com.android.billingclient:billing-ktx:3.0.1'
|
||||||
|
|
||||||
// KTX
|
// KTX
|
||||||
implementation "androidx.core:core-ktx:1.2.0"
|
implementation "androidx.core:core-ktx:1.3.2"
|
||||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
|
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.2.0'
|
implementation 'androidx.core:core-ktx:1.3.2'
|
||||||
|
|
||||||
|
//Retrofit
|
||||||
|
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||||
|
implementation 'com.google.code.gson:gson:2.8.6'
|
||||||
|
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||||
|
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
|
||||||
|
implementation "com.github.haroldadmin:NetworkResponseAdapter:4.0.1"
|
||||||
|
|
||||||
|
//Coroutines
|
||||||
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5'
|
||||||
|
|
||||||
// Add the Firebase SDK for Crashlytics.
|
// Add the Firebase SDK for Crashlytics.
|
||||||
implementation 'com.google.firebase:firebase-crashlytics:17.0.0'
|
implementation 'com.google.firebase:firebase-crashlytics:17.2.2'
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
implementation 'com.chibatching.kotpref:kotpref:2.10.0'
|
implementation 'com.chibatching.kotpref:kotpref:2.11.0'
|
||||||
implementation 'com.chibatching.kotpref:livedata-support:2.10.0'
|
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
|
||||||
implementation 'com.karumi:dexter:6.1.0'
|
implementation 'com.karumi:dexter:6.2.1'
|
||||||
|
|
||||||
// Billing
|
// Fonts
|
||||||
implementation 'com.android.billingclient:billing:2.2.0'
|
implementation 'com.github.firatkarababa:downloadable-font-list-library:1.0.2'
|
||||||
implementation 'com.android.billingclient:billing-ktx:2.2.0'
|
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
@ -22,6 +22,7 @@
|
|||||||
android:name=".AWApplication"
|
android:name=".AWApplication"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
|
android:usesCleartextTraffic="true"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
tools:ignore="LockedOrientationActivity">
|
tools:ignore="LockedOrientationActivity">
|
||||||
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" 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">
|
||||||
@ -32,11 +33,14 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".ui.activities.ChooseApplicationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.ChooseApplicationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
|
<activity android:name=".ui.activities.CustomFontActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.CustomLocationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.CustomLocationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.WeatherProviderActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.WeatherProviderActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.SupportDevActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.SupportDevActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.CustomDateActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.CustomDateActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.IntegrationsActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.IntegrationsActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
|
<activity android:name=".ui.activities.MusicPlayersFilterActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
|
<activity android:name=".ui.activities.AppNotificationsFilterActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
|
|
||||||
|
|
||||||
<receiver android:name=".ui.widgets.MainWidget">
|
<receiver android:name=".ui.widgets.MainWidget">
|
||||||
@ -117,7 +121,7 @@
|
|||||||
|
|
||||||
<service android:name=".services.BatteryListenerJob" android:permission="android.permission.BIND_JOB_SERVICE" />
|
<service android:name=".services.BatteryListenerJob" android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||||
|
|
||||||
<service android:name=".receivers.MusicNotificationListener"
|
<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" />
|
||||||
|
BIN
app/src/main/assets/fonts/google_sans_black.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_black.ttf
Normal file
Binary file not shown.
BIN
app/src/main/assets/fonts/google_sans_black_italic.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_black_italic.ttf
Normal file
Binary file not shown.
BIN
app/src/main/assets/fonts/google_sans_bold.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_bold.ttf
Normal file
Binary file not shown.
BIN
app/src/main/assets/fonts/google_sans_bold_italic.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_bold_italic.ttf
Normal file
Binary file not shown.
BIN
app/src/main/assets/fonts/google_sans_italic.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_italic.ttf
Normal file
Binary file not shown.
BIN
app/src/main/assets/fonts/google_sans_light.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_light.ttf
Normal file
Binary file not shown.
BIN
app/src/main/assets/fonts/google_sans_light_italic.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_light_italic.ttf
Normal file
Binary file not shown.
BIN
app/src/main/assets/fonts/google_sans_medium.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_medium.ttf
Normal file
Binary file not shown.
BIN
app/src/main/assets/fonts/google_sans_medium_italic.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_medium_italic.ttf
Normal file
Binary file not shown.
BIN
app/src/main/assets/fonts/google_sans_regular.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_regular.ttf
Normal file
Binary file not shown.
BIN
app/src/main/assets/fonts/google_sans_thin.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_thin.ttf
Normal file
Binary file not shown.
BIN
app/src/main/assets/fonts/google_sans_thin_italic.ttf
Normal file
BIN
app/src/main/assets/fonts/google_sans_thin_italic.ttf
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -2,6 +2,7 @@ package com.tommasoberlose.anotherwidget.components
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
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 com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
@ -9,6 +10,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import kotlinx.android.synthetic.main.bottom_sheet_menu.view.*
|
import kotlinx.android.synthetic.main.bottom_sheet_menu.view.*
|
||||||
import kotlinx.android.synthetic.main.bottom_sheet_menu_item.view.*
|
import kotlinx.android.synthetic.main.bottom_sheet_menu_item.view.*
|
||||||
|
import org.w3c.dom.Text
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [BottomSheetDialogFragment] that uses a custom
|
* [BottomSheetDialogFragment] that uses a custom
|
||||||
@ -32,8 +34,8 @@ open class BottomSheetMenu<T>(context: Context, private val header: String? = nu
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addItem(title: String, value: T? = null): BottomSheetMenu<T> {
|
fun addItem(title: String, value: T? = null, renderCallback: ((view: TextView) -> Unit)? = null): BottomSheetMenu<T> {
|
||||||
items.add(MenuItem(title, value))
|
items.add(MenuItem(title, value, renderCallback))
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +96,10 @@ open class BottomSheetMenu<T>(context: Context, private val header: String? = nu
|
|||||||
) else ContextCompat.getColor(context, R.color.colorSecondaryText)
|
) else ContextCompat.getColor(context, R.color.colorSecondaryText)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item.renderCallback?.invoke(itemView.label)
|
||||||
}
|
}
|
||||||
|
|
||||||
view.menu.addView(itemView)
|
view.menu.addView(itemView)
|
||||||
} else {
|
} else {
|
||||||
val itemView = View.inflate(context, R.layout.bottom_sheet_menu_divider, null)
|
val itemView = View.inflate(context, R.layout.bottom_sheet_menu_divider, null)
|
||||||
@ -106,6 +111,6 @@ open class BottomSheetMenu<T>(context: Context, private val header: String? = nu
|
|||||||
super.show()
|
super.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
class MenuItem<T>(val title: String, val value: T? = null)
|
class MenuItem<T>(val title: String, val value: T? = null, val renderCallback: ((view: TextView) -> Unit)? = null)
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.components
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
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.utils.openURI
|
||||||
|
import kotlinx.android.synthetic.main.weather_provider_settings_layout.view.*
|
||||||
|
|
||||||
|
class BottomSheetWeatherProviderSettings(context: Context, callback: () -> Unit) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
val view = View.inflate(context, R.layout.weather_provider_settings_layout, null)
|
||||||
|
view.api_key_container.isVisible = WeatherHelper.isKeyRequired()
|
||||||
|
view.action_save_key.isVisible = WeatherHelper.isKeyRequired()
|
||||||
|
|
||||||
|
WeatherHelper.getProviderInfoTitle(context).let { title ->
|
||||||
|
view.info_title.text = title
|
||||||
|
view.info_title.isVisible = title != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
WeatherHelper.getProviderInfoSubtitle(context).let { subtitle ->
|
||||||
|
view.info_subtitle.text = subtitle
|
||||||
|
view.info_subtitle.isVisible = subtitle != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
view.info_provider.text = WeatherHelper.getProviderName(context)
|
||||||
|
|
||||||
|
view.api_key.editText?.setText(when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
|
||||||
|
Constants.WeatherProvider.OPEN_WEATHER -> Preferences.weatherProviderApiOpen
|
||||||
|
Constants.WeatherProvider.WEATHER_BIT -> Preferences.weatherProviderApiWeatherBit
|
||||||
|
Constants.WeatherProvider.WEATHER_API -> Preferences.weatherProviderApiWeatherApi
|
||||||
|
Constants.WeatherProvider.HERE -> Preferences.weatherProviderApiHere
|
||||||
|
Constants.WeatherProvider.ACCUWEATHER -> Preferences.weatherProviderApiAccuweather
|
||||||
|
Constants.WeatherProvider.WEATHER_GOV,
|
||||||
|
Constants.WeatherProvider.YR,
|
||||||
|
null -> ""
|
||||||
|
})
|
||||||
|
|
||||||
|
view.action_open_provider.setOnClickListener {
|
||||||
|
context.openURI(WeatherHelper.getProviderLink())
|
||||||
|
}
|
||||||
|
|
||||||
|
view.action_save_key.setOnClickListener {
|
||||||
|
val key = view.api_key.editText?.text.toString()
|
||||||
|
when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
|
||||||
|
Constants.WeatherProvider.OPEN_WEATHER -> Preferences.weatherProviderApiOpen = key
|
||||||
|
Constants.WeatherProvider.WEATHER_BIT -> Preferences.weatherProviderApiWeatherBit = key
|
||||||
|
Constants.WeatherProvider.WEATHER_API -> Preferences.weatherProviderApiWeatherApi = key
|
||||||
|
Constants.WeatherProvider.HERE -> Preferences.weatherProviderApiHere = key
|
||||||
|
Constants.WeatherProvider.ACCUWEATHER -> Preferences.weatherProviderApiAccuweather = key
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
callback.invoke()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
setContentView(view)
|
||||||
|
}
|
||||||
|
}
|
@ -6,13 +6,14 @@ import android.util.AttributeSet
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ScrollView
|
import android.widget.ScrollView
|
||||||
|
import androidx.core.widget.NestedScrollView
|
||||||
|
|
||||||
|
|
||||||
class FixedFocusScrollView @JvmOverloads constructor(
|
class FixedFocusScrollView @JvmOverloads constructor(
|
||||||
context: Context,
|
context: Context,
|
||||||
attrs: AttributeSet? = null,
|
attrs: AttributeSet? = null,
|
||||||
defStyle: Int = 0
|
defStyle: Int = 0
|
||||||
) : ScrollView(context, attrs, defStyle) {
|
) : NestedScrollView(context, attrs, defStyle) {
|
||||||
|
|
||||||
var isScrollable = true
|
var isScrollable = true
|
||||||
|
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.components
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.res.ColorStateList
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.appcompat.widget.AppCompatImageView
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
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.global.Constants
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.GlanceProviderHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.models.GlanceProvider
|
|
||||||
import kotlinx.android.synthetic.main.glance_provider_sort_bottom_menu.view.*
|
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import net.idik.lib.slimadapter.SlimAdapter
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
class GlanceProviderSortMenu(
|
|
||||||
context: Context
|
|
||||||
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
|
||||||
|
|
||||||
private lateinit var adapter: SlimAdapter
|
|
||||||
|
|
||||||
override fun show() {
|
|
||||||
val view = View.inflate(context, R.layout.glance_provider_sort_bottom_menu, null)
|
|
||||||
|
|
||||||
// Header
|
|
||||||
view.header_text.text = context.getString(R.string.settings_sort_glance_providers_title)
|
|
||||||
|
|
||||||
// List
|
|
||||||
adapter = SlimAdapter.create()
|
|
||||||
|
|
||||||
view.menu.setHasFixedSize(true)
|
|
||||||
val mLayoutManager = LinearLayoutManager(context)
|
|
||||||
view.menu.layoutManager = mLayoutManager
|
|
||||||
|
|
||||||
adapter = SlimAdapter.create()
|
|
||||||
adapter
|
|
||||||
.register<GlanceProvider>(R.layout.glance_provider_item) { item, injector ->
|
|
||||||
injector
|
|
||||||
.text(R.id.title, item.title)
|
|
||||||
.with<ImageView>(R.id.icon) {
|
|
||||||
it.setImageDrawable(ContextCompat.getDrawable(context, item.icon))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.attachTo(view.menu)
|
|
||||||
|
|
||||||
val mIth = ItemTouchHelper(
|
|
||||||
object : ItemTouchHelper.SimpleCallback(
|
|
||||||
ItemTouchHelper.UP or ItemTouchHelper.DOWN,
|
|
||||||
ItemTouchHelper.LEFT
|
|
||||||
) {
|
|
||||||
override fun onMove(
|
|
||||||
recyclerView: RecyclerView,
|
|
||||||
viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder
|
|
||||||
): Boolean {
|
|
||||||
val fromPos = viewHolder.adapterPosition
|
|
||||||
val toPos = target.adapterPosition
|
|
||||||
// move item in `fromPos` to `toPos` in adapter.
|
|
||||||
adapter.notifyItemMoved(fromPos, toPos)
|
|
||||||
|
|
||||||
val list = GlanceProviderHelper.getGlanceProviders(context)
|
|
||||||
Collections.swap(list, fromPos, toPos)
|
|
||||||
GlanceProviderHelper.saveGlanceProviderOrder(list)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSwiped(
|
|
||||||
viewHolder: RecyclerView.ViewHolder,
|
|
||||||
direction: Int
|
|
||||||
) {
|
|
||||||
// remove from adapter
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
mIth.attachToRecyclerView(view.menu)
|
|
||||||
|
|
||||||
adapter.updateData(
|
|
||||||
GlanceProviderHelper.getGlanceProviders(context)
|
|
||||||
.mapNotNull { GlanceProviderHelper.getGlanceProviderById(context, it) }
|
|
||||||
)
|
|
||||||
|
|
||||||
setContentView(view)
|
|
||||||
super.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,346 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.components
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.AlarmManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.View
|
||||||
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
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.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.global.Constants
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.GreetingsHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.AppNotificationsFilterActivity
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.MusicPlayersFilterActivity
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
|
import kotlinx.android.synthetic.main.glance_provider_settings_layout.view.*
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
|
||||||
|
class GlanceSettingsDialog(val context: Activity, val provider: Constants.GlanceProviderId, private val statusCallback: (() -> Unit)?) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||||
|
|
||||||
|
override fun show() {
|
||||||
|
val view = View.inflate(context, R.layout.glance_provider_settings_layout, null)
|
||||||
|
|
||||||
|
/* TITLE */
|
||||||
|
view.title.text = when (provider) {
|
||||||
|
Constants.GlanceProviderId.PLAYING_SONG -> context.getString(R.string.settings_show_music_title)
|
||||||
|
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> context.getString(R.string.settings_show_next_alarm_title)
|
||||||
|
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> context.getString(R.string.settings_low_battery_level_title)
|
||||||
|
Constants.GlanceProviderId.CUSTOM_INFO -> context.getString(R.string.settings_custom_notes_title)
|
||||||
|
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> context.getString(R.string.settings_daily_steps_title)
|
||||||
|
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_title)
|
||||||
|
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_title)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SUBTITLE*/
|
||||||
|
view.subtitle.text = when (provider) {
|
||||||
|
Constants.GlanceProviderId.PLAYING_SONG -> context.getString(R.string.settings_show_music_subtitle)
|
||||||
|
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> context.getString(R.string.settings_show_next_alarm_subtitle)
|
||||||
|
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> context.getString(R.string.settings_low_battery_level_subtitle)
|
||||||
|
Constants.GlanceProviderId.CUSTOM_INFO -> ""
|
||||||
|
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> context.getString(R.string.settings_daily_steps_subtitle)
|
||||||
|
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_subtitle)
|
||||||
|
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_subtitle)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SONG */
|
||||||
|
view.action_filter_music_players.isVisible = provider == Constants.GlanceProviderId.PLAYING_SONG
|
||||||
|
if (provider == Constants.GlanceProviderId.PLAYING_SONG) {
|
||||||
|
view.action_filter_music_players.setOnClickListener {
|
||||||
|
dismiss()
|
||||||
|
context.startActivityForResult(Intent(context, MusicPlayersFilterActivity::class.java), 0)
|
||||||
|
}
|
||||||
|
checkNotificationPermission(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ALARM */
|
||||||
|
view.alarm_set_by_container.isVisible = provider == Constants.GlanceProviderId.NEXT_CLOCK_ALARM
|
||||||
|
if (provider == Constants.GlanceProviderId.NEXT_CLOCK_ALARM) {
|
||||||
|
view.header.text = context.getString(R.string.information_header)
|
||||||
|
view.warning_container.isVisible = false
|
||||||
|
checkNextAlarm(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GOOGLE STEPS */
|
||||||
|
view.action_toggle_google_fit.isVisible = provider == Constants.GlanceProviderId.GOOGLE_FIT_STEPS
|
||||||
|
if (provider == Constants.GlanceProviderId.GOOGLE_FIT_STEPS) {
|
||||||
|
view.warning_container.isVisible = false
|
||||||
|
checkFitnessPermission(view)
|
||||||
|
checkGoogleFitConnection(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BATTERY INFO */
|
||||||
|
if (provider == Constants.GlanceProviderId.BATTERY_LEVEL_LOW) {
|
||||||
|
view.warning_container.isVisible = false
|
||||||
|
view.header.isVisible = false
|
||||||
|
view.divider.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTIFICATIONS */
|
||||||
|
view.action_filter_notifications_app.isVisible = provider == Constants.GlanceProviderId.NOTIFICATIONS
|
||||||
|
view.action_change_notification_timer.isVisible = provider == Constants.GlanceProviderId.NOTIFICATIONS
|
||||||
|
if (provider == Constants.GlanceProviderId.NOTIFICATIONS) {
|
||||||
|
checkLastNotificationsPermission(view)
|
||||||
|
val stringArray = context.resources.getStringArray(R.array.glance_notifications_timeout)
|
||||||
|
view.action_filter_notifications_app.setOnClickListener {
|
||||||
|
dismiss()
|
||||||
|
context.startActivityForResult(Intent(context, AppNotificationsFilterActivity::class.java), 0)
|
||||||
|
}
|
||||||
|
view.notification_timer_label.text = stringArray[Preferences.hideNotificationAfter]
|
||||||
|
view.action_change_notification_timer.setOnClickListener {
|
||||||
|
val dialog = BottomSheetMenu<Int>(context, header = context.getString(R.string.glance_notification_hide_timeout_title)).setSelectedValue(Preferences.hideNotificationAfter)
|
||||||
|
Constants.GlanceNotificationTimer.values().forEachIndexed { index, timeout ->
|
||||||
|
dialog.addItem(stringArray[index], timeout.value)
|
||||||
|
}
|
||||||
|
dialog.addOnSelectItemListener { value ->
|
||||||
|
Preferences.hideNotificationAfter = value
|
||||||
|
this.show()
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GREETINGS */
|
||||||
|
if (provider == Constants.GlanceProviderId.GREETINGS) {
|
||||||
|
view.warning_container.isVisible = false
|
||||||
|
view.header.isVisible = false
|
||||||
|
view.divider.isVisible = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TOGGLE */
|
||||||
|
view.provider_switch.isChecked = when (provider) {
|
||||||
|
Constants.GlanceProviderId.PLAYING_SONG -> Preferences.showMusic
|
||||||
|
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> Preferences.showNextAlarm
|
||||||
|
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> Preferences.showBatteryCharging
|
||||||
|
Constants.GlanceProviderId.CUSTOM_INFO -> true
|
||||||
|
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> Preferences.showDailySteps
|
||||||
|
Constants.GlanceProviderId.NOTIFICATIONS -> Preferences.showNotifications
|
||||||
|
Constants.GlanceProviderId.GREETINGS -> Preferences.showGreetings
|
||||||
|
}
|
||||||
|
|
||||||
|
var job: Job? = null
|
||||||
|
|
||||||
|
view.provider_switch.setOnCheckedChangeListener { _, isChecked ->
|
||||||
|
job?.cancel()
|
||||||
|
job = GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
delay(300)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
when (provider) {
|
||||||
|
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||||
|
Preferences.showMusic = isChecked
|
||||||
|
checkNotificationPermission(view)
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
||||||
|
Preferences.showNextAlarm = isChecked
|
||||||
|
checkNextAlarm(view)
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
||||||
|
Preferences.showBatteryCharging = isChecked
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.NOTIFICATIONS -> {
|
||||||
|
Preferences.showNotifications = isChecked
|
||||||
|
checkLastNotificationsPermission(view)
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.GREETINGS -> {
|
||||||
|
Preferences.showGreetings = isChecked
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
view.warning_container.isVisible = false
|
||||||
|
checkFitnessPermission(view)
|
||||||
|
checkGoogleFitConnection(view)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statusCallback?.invoke()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setContentView(view)
|
||||||
|
super.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkNextAlarm(view: View) {
|
||||||
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
|
val alarm = nextAlarmClock
|
||||||
|
if (alarm != null && alarm.showIntent != null) {
|
||||||
|
val pm = context.packageManager as PackageManager
|
||||||
|
val appNameOrPackage = try {
|
||||||
|
pm.getApplicationLabel(pm.getApplicationInfo(alarm.showIntent?.creatorPackage ?: "", 0))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
alarm.showIntent?.creatorPackage ?: ""
|
||||||
|
}
|
||||||
|
view.alarm_set_by_title.text = context.getString(R.string.settings_show_next_alarm_app_title).format(appNameOrPackage)
|
||||||
|
view.alarm_set_by_subtitle.text = if (AlarmHelper.isAlarmProbablyWrong(context)) context.getString(R.string.settings_show_next_alarm_app_subtitle_wrong) else context.getString(R.string.settings_show_next_alarm_app_subtitle_correct)
|
||||||
|
view.alarm_set_by_title.isVisible = true
|
||||||
|
} else {
|
||||||
|
view.alarm_set_by_title.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statusCallback?.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkNotificationPermission(view: View) {
|
||||||
|
when {
|
||||||
|
ActiveNotificationsHelper.checkNotificationAccess(context) -> {
|
||||||
|
view.warning_container.isVisible = false
|
||||||
|
MediaPlayerHelper.updatePlayingMediaInfo(context)
|
||||||
|
}
|
||||||
|
Preferences.showMusic -> {
|
||||||
|
view.warning_container.isVisible = true
|
||||||
|
view.warning_title.text = context.getString(R.string.settings_request_notification_access)
|
||||||
|
view.warning_container.setOnClickListener {
|
||||||
|
context.startActivity(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
view.warning_container.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statusCallback?.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkLastNotificationsPermission(view: View) {
|
||||||
|
when {
|
||||||
|
ActiveNotificationsHelper.checkNotificationAccess(context) -> {
|
||||||
|
view.warning_container.isVisible = false
|
||||||
|
}
|
||||||
|
Preferences.showNotifications -> {
|
||||||
|
view.warning_container.isVisible = true
|
||||||
|
view.warning_title.text = context.getString(R.string.settings_request_last_notification_access)
|
||||||
|
view.warning_container.setOnClickListener {
|
||||||
|
context.startActivity(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
view.warning_container.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
statusCallback?.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkFitnessPermission(view: View) {
|
||||||
|
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)
|
||||||
|
view.warning_container.isVisible = true
|
||||||
|
view.warning_title.text = context.getString(R.string.settings_request_fitness_access)
|
||||||
|
view.warning_container.setOnClickListener {
|
||||||
|
requireFitnessPermission(view)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ActivityDetectionReceiver.unregisterFence(context)
|
||||||
|
}
|
||||||
|
statusCallback?.invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkGoogleFitConnection(view: View) {
|
||||||
|
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
|
||||||
|
if (!GoogleSignIn.hasPermissions(account,
|
||||||
|
ActivityDetectionReceiver.FITNESS_OPTIONS
|
||||||
|
)) {
|
||||||
|
view.warning_container.isVisible = true
|
||||||
|
view.warning_title.text = context.getString(R.string.settings_request_fitness_access)
|
||||||
|
view.warning_container.setOnClickListener {
|
||||||
|
GoogleSignIn.requestPermissions(
|
||||||
|
context,
|
||||||
|
1,
|
||||||
|
account,
|
||||||
|
ActivityDetectionReceiver.FITNESS_OPTIONS)
|
||||||
|
}
|
||||||
|
view.action_connect_to_google_fit.isVisible = true
|
||||||
|
view.action_disconnect_to_google_fit.isVisible = false
|
||||||
|
view.action_connect_to_google_fit.setOnClickListener {
|
||||||
|
GoogleSignIn.requestPermissions(
|
||||||
|
context,
|
||||||
|
1,
|
||||||
|
account,
|
||||||
|
ActivityDetectionReceiver.FITNESS_OPTIONS)
|
||||||
|
}
|
||||||
|
view.action_disconnect_to_google_fit.setOnClickListener(null)
|
||||||
|
view.google_fit_status_label.text = context.getString(R.string.google_fit_account_not_connected)
|
||||||
|
} else {
|
||||||
|
view.action_connect_to_google_fit.isVisible = false
|
||||||
|
view.action_disconnect_to_google_fit.isVisible = true
|
||||||
|
view.action_connect_to_google_fit.setOnClickListener(null)
|
||||||
|
view.action_disconnect_to_google_fit.setOnClickListener {
|
||||||
|
GoogleSignIn.getClient(context, GoogleSignInOptions.Builder(
|
||||||
|
GoogleSignInOptions.DEFAULT_SIGN_IN).addExtension(
|
||||||
|
ActivityDetectionReceiver.FITNESS_OPTIONS
|
||||||
|
).build()).signOut().addOnCompleteListener {
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
view.google_fit_status_label.text = context.getString(R.string.google_fit_account_connected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun requireFitnessPermission(view: View) {
|
||||||
|
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(view)
|
||||||
|
}
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
@ -32,10 +32,10 @@ class IconPackSelector(context: Context, private val header: String? = null) : B
|
|||||||
itemView.label.text = context.getString(R.string.settings_weather_icon_pack_default).format(item.value + 1)
|
itemView.label.text = context.getString(R.string.settings_weather_icon_pack_default).format(item.value + 1)
|
||||||
itemView.isSelected = item.value == Preferences.weatherIconPack
|
itemView.isSelected = item.value == Preferences.weatherIconPack
|
||||||
|
|
||||||
itemView.icon_1.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource("01d", item.value)))
|
itemView.icon_1.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "01d", item.value)))
|
||||||
itemView.icon_2.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource("01n", item.value)))
|
itemView.icon_2.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "01n", item.value)))
|
||||||
itemView.icon_3.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource("10d", item.value)))
|
itemView.icon_3.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "10d", item.value)))
|
||||||
itemView.icon_4.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource("09n", item.value)))
|
itemView.icon_4.setImageDrawable(ContextCompat.getDrawable(context, WeatherHelper.getWeatherIconResource(context, "09n", item.value)))
|
||||||
|
|
||||||
listOf<ImageView>(itemView.icon_1, itemView.icon_2, itemView.icon_3, itemView.icon_4).forEach {
|
listOf<ImageView>(itemView.icon_1, itemView.icon_2, itemView.icon_3, itemView.icon_4).forEach {
|
||||||
if (item == Constants.WeatherIconPack.MINIMAL) {
|
if (item == Constants.WeatherIconPack.MINIMAL) {
|
||||||
|
@ -11,8 +11,8 @@ typealias DialogCallback = () -> Unit
|
|||||||
|
|
||||||
class MaterialBottomSheetDialog(
|
class MaterialBottomSheetDialog(
|
||||||
context: Context,
|
context: Context,
|
||||||
private val title: String? = "",
|
private val title: String? = null,
|
||||||
private val message: String? = ""
|
private val message: String? = null
|
||||||
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||||
|
|
||||||
private var positiveButtonLabel: String? = null
|
private var positiveButtonLabel: String? = null
|
||||||
@ -36,7 +36,7 @@ class MaterialBottomSheetDialog(
|
|||||||
val view = View.inflate(context, R.layout.bottom_sheet_dialog, null)
|
val view = View.inflate(context, R.layout.bottom_sheet_dialog, null)
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
view.message.isVisible = title != null
|
view.title.isVisible = title != null
|
||||||
view.title.text = title ?: ""
|
view.title.text = title ?: ""
|
||||||
|
|
||||||
view.message.isVisible = message != null
|
view.message.isVisible = message != null
|
||||||
|
@ -5,18 +5,20 @@ import android.provider.CalendarContract
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
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.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.Realm
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmResults
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.Comparator
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class EventRepository(val context: Context) {
|
class EventRepository(val context: Context) {
|
||||||
private val realm by lazy { Realm.getDefaultInstance() }
|
private val realm by lazy { Realm.getDefaultInstance() }
|
||||||
|
|
||||||
fun saveEvents(eventList: ArrayList<Event>) {
|
fun saveEvents(eventList: List<Event>) {
|
||||||
realm.executeTransaction { realm ->
|
realm.executeTransaction { realm ->
|
||||||
realm.where(Event::class.java).findAll().deleteAllFromRealm()
|
realm.where(Event::class.java).findAll().deleteAllFromRealm()
|
||||||
realm.copyToRealm(eventList)
|
realm.copyToRealm(eventList)
|
||||||
@ -68,7 +70,7 @@ class EventRepository(val context: Context) {
|
|||||||
val events = getEvents()
|
val events = getEvents()
|
||||||
if (events.isNotEmpty()) {
|
if (events.isNotEmpty()) {
|
||||||
val newNextEvent = events.first()
|
val newNextEvent = events.first()
|
||||||
Preferences.nextEventId = newNextEvent!!.eventID
|
Preferences.nextEventId = newNextEvent.eventID
|
||||||
newNextEvent
|
newNextEvent
|
||||||
} else {
|
} else {
|
||||||
resetNextEventData()
|
resetNextEventData()
|
||||||
@ -96,9 +98,9 @@ class EventRepository(val context: Context) {
|
|||||||
if (eventList.isNotEmpty()) {
|
if (eventList.isNotEmpty()) {
|
||||||
val index = eventList.indexOfFirst { it.eventID == Preferences.nextEventId }
|
val index = eventList.indexOfFirst { it.eventID == Preferences.nextEventId }
|
||||||
if (index > -1 && index < eventList.size - 1) {
|
if (index > -1 && index < eventList.size - 1) {
|
||||||
Preferences.nextEventId = eventList[index + 1]!!.eventID
|
Preferences.nextEventId = eventList[index + 1].eventID
|
||||||
} else {
|
} else {
|
||||||
Preferences.nextEventId = eventList.first()!!.eventID
|
Preferences.nextEventId = eventList.first().eventID
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
resetNextEventData()
|
resetNextEventData()
|
||||||
@ -112,9 +114,9 @@ class EventRepository(val context: Context) {
|
|||||||
if (eventList.isNotEmpty()) {
|
if (eventList.isNotEmpty()) {
|
||||||
val index = eventList.indexOfFirst { it.eventID == Preferences.nextEventId }
|
val index = eventList.indexOfFirst { it.eventID == Preferences.nextEventId }
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
Preferences.nextEventId = eventList[index - 1]!!.eventID
|
Preferences.nextEventId = eventList[index - 1].eventID
|
||||||
} else {
|
} else {
|
||||||
Preferences.nextEventId = eventList.last()!!.eventID
|
Preferences.nextEventId = eventList.last().eventID
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
resetNextEventData()
|
resetNextEventData()
|
||||||
@ -130,8 +132,7 @@ class EventRepository(val context: Context) {
|
|||||||
.where(Event::class.java)
|
.where(Event::class.java)
|
||||||
.greaterThan("endDate", now)
|
.greaterThan("endDate", now)
|
||||||
.findAll()
|
.findAll()
|
||||||
.filter { (Preferences.showDeclinedEvents || it.selfAttendeeStatus != CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED) }
|
.applyFilters()
|
||||||
.filter { (Preferences.calendarAllDay || !it.allDay) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getEvents(): List<Event> {
|
private fun getEvents(): List<Event> {
|
||||||
@ -156,8 +157,7 @@ class EventRepository(val context: Context) {
|
|||||||
.greaterThan("endDate", now)
|
.greaterThan("endDate", now)
|
||||||
.lessThanOrEqualTo("startDate", limit.timeInMillis)
|
.lessThanOrEqualTo("startDate", limit.timeInMillis)
|
||||||
.findAll()
|
.findAll()
|
||||||
.filter { (Preferences.showDeclinedEvents || it.selfAttendeeStatus != CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED) }
|
.applyFilters()
|
||||||
.filter { (Preferences.calendarAllDay || !it.allDay) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEventsCount(): Int = getEvents().size
|
fun getEventsCount(): Int = getEvents().size
|
||||||
|
@ -5,10 +5,13 @@ object Actions {
|
|||||||
const val ACTION_EXTRA_DISABLE_GPS_NOTIFICATION = "ACTION_EXTRA_DISABLE_GPS_NOTIFICATION"
|
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_CALENDAR_UPDATE = "com.tommasoberlose.anotherwidget.action.CALENDAR_UPDATE"
|
const val ACTION_CALENDAR_UPDATE = "com.tommasoberlose.anotherwidget.action.CALENDAR_UPDATE"
|
||||||
const val ACTION_WEATHER_UPDATE = "com.tommasoberlose.anotherwidget.action.WEATHER_UPDATE"
|
const val ACTION_WEATHER_UPDATE = "com.tommasoberlose.anotherwidget.action.WEATHER_UPDATE"
|
||||||
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_REPORT_CRASH = "com.tommasoberlose.anotherwidget.action.REPORT_CRASH"
|
||||||
|
const val ACTION_CLEAR_NOTIFICATION = "com.tommasoberlose.anotherwidget.action.CLEAR_NOTIFICATION"
|
||||||
|
const val ACTION_UPDATE_GREETINGS = "com.tommasoberlose.anotherwidget.action.UPDATE_GREETINGS"
|
||||||
}
|
}
|
@ -7,7 +7,10 @@ object Constants {
|
|||||||
const val RESULT_APP_NAME = "RESULT_APP_NAME"
|
const val RESULT_APP_NAME = "RESULT_APP_NAME"
|
||||||
const val RESULT_APP_PACKAGE = "RESULT_APP_PACKAGE"
|
const val RESULT_APP_PACKAGE = "RESULT_APP_PACKAGE"
|
||||||
|
|
||||||
const val CUSTOM_FONT_PRODUCT_SANS = 1
|
const val CUSTOM_FONT_GOOGLE_SANS = 1
|
||||||
|
const val CUSTOM_FONT_DOWNLOADED = 2
|
||||||
|
const val CUSTOM_FONT_DOWNLOAD_NEW = 3
|
||||||
|
|
||||||
enum class ClockBottomMargin(val value: Int) {
|
enum class ClockBottomMargin(val value: Int) {
|
||||||
NONE(0),
|
NONE(0),
|
||||||
SMALL(1),
|
SMALL(1),
|
||||||
@ -15,12 +18,26 @@ object Constants {
|
|||||||
LARGE(3)
|
LARGE(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class SecondRowTopMargin(val value: Int) {
|
||||||
|
NONE(0),
|
||||||
|
SMALL(1),
|
||||||
|
MEDIUM(2),
|
||||||
|
LARGE(3)
|
||||||
|
}
|
||||||
|
|
||||||
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"),
|
||||||
BATTERY_LEVEL_LOW("BATTERY_LEVEL_LOW"),
|
BATTERY_LEVEL_LOW("BATTERY_LEVEL_LOW"),
|
||||||
CUSTOM_INFO("CUSTOM_INFO"),
|
CUSTOM_INFO("CUSTOM_INFO"),
|
||||||
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS")
|
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS"),
|
||||||
|
NOTIFICATIONS("NOTIFICATIONS"),
|
||||||
|
GREETINGS("GREETINGS");
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val map = GlanceProviderId.values().associateBy(GlanceProviderId::id)
|
||||||
|
fun from(type: String) = map[type]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class WidgetUpdateFrequency(val value: Int) {
|
enum class WidgetUpdateFrequency(val value: Int) {
|
||||||
@ -29,6 +46,35 @@ object Constants {
|
|||||||
HIGH(2)
|
HIGH(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class WeatherProvider(val value: Int) {
|
||||||
|
OPEN_WEATHER(0),
|
||||||
|
WEATHER_BIT(1),
|
||||||
|
WEATHER_API(2),
|
||||||
|
HERE(3),
|
||||||
|
ACCUWEATHER(4),
|
||||||
|
WEATHER_GOV(5),
|
||||||
|
YR(6);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val map = WeatherProvider.values().associateBy(WeatherProvider::value)
|
||||||
|
fun fromInt(type: Int) = map[type]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class GlanceNotificationTimer(val value: Int) {
|
||||||
|
HALF_MINUTE(0),
|
||||||
|
ONE_MINUTE(1),
|
||||||
|
FIVE_MINUTES(2),
|
||||||
|
TEN_MINUTES(3),
|
||||||
|
FIFTEEN_MINUTES(4),
|
||||||
|
WHEN_DISMISSED(5);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val map = values().associateBy(GlanceNotificationTimer::value)
|
||||||
|
fun fromInt(type: Int) = map[type]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum class WeatherIconPack(val value: Int) {
|
enum class WeatherIconPack(val value: Int) {
|
||||||
DEFAULT(0),
|
DEFAULT(0),
|
||||||
MINIMAL(1),
|
MINIMAL(1),
|
||||||
|
@ -31,13 +31,21 @@ object Preferences : KotprefModel() {
|
|||||||
var customLocationAdd by stringPref(key = "PREF_CUSTOM_LOCATION_ADD", default = "")
|
var customLocationAdd by stringPref(key = "PREF_CUSTOM_LOCATION_ADD", default = "")
|
||||||
var dateFormat by stringPref(default = "")
|
var dateFormat by stringPref(default = "")
|
||||||
var isDateCapitalize by booleanPref(default = true)
|
var isDateCapitalize by booleanPref(default = true)
|
||||||
|
var isDateUppercase by booleanPref(default = false)
|
||||||
var weatherRefreshPeriod by intPref(key = "PREF_WEATHER_REFRESH_PERIOD", default = 1)
|
var weatherRefreshPeriod by intPref(key = "PREF_WEATHER_REFRESH_PERIOD", default = 1)
|
||||||
var showUntil by intPref(key = "PREF_SHOW_UNTIL", default = 1)
|
var showUntil by intPref(key = "PREF_SHOW_UNTIL", default = 1)
|
||||||
var calendarAppName by stringPref(key = "PREF_CALENDAR_APP_NAME", default = "")
|
var calendarAppName by stringPref(key = "PREF_CALENDAR_APP_NAME", default = "")
|
||||||
var calendarAppPackage by stringPref(key = "PREF_CALENDAR_APP_PACKAGE", default = "")
|
var calendarAppPackage by stringPref(key = "PREF_CALENDAR_APP_PACKAGE", default = "")
|
||||||
var weatherAppName by stringPref(key = "PREF_WEATHER_APP_NAME", default = "")
|
var weatherAppName by stringPref(key = "PREF_WEATHER_APP_NAME", default = "")
|
||||||
var weatherAppPackage by stringPref(key = "PREF_WEATHER_APP_PACKAGE", default = "")
|
var weatherAppPackage by stringPref(key = "PREF_WEATHER_APP_PACKAGE", default = "")
|
||||||
var weatherProviderApi by stringPref(key = "PREF_WEATHER_PROVIDER_API_KEY", default = "")
|
var weatherProviderApiOpen by stringPref(key = "PREF_WEATHER_PROVIDER_API_KEY", default = "")
|
||||||
|
var weatherProviderApiHere by stringPref(default = "")
|
||||||
|
var weatherProviderApiWeatherApi by stringPref(default = "")
|
||||||
|
var weatherProviderApiWeatherBit by stringPref(default = "")
|
||||||
|
var weatherProviderApiAccuweather by stringPref(default = "")
|
||||||
|
var weatherProvider by intPref(default = Constants.WeatherProvider.OPEN_WEATHER.value)
|
||||||
|
var weatherProviderError 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)
|
||||||
@ -55,6 +63,20 @@ object Preferences : KotprefModel() {
|
|||||||
|
|
||||||
var clockTextColor by stringPref(default = "#FFFFFF")
|
var clockTextColor by stringPref(default = "#FFFFFF")
|
||||||
var clockTextAlpha by stringPref(default = "FF")
|
var clockTextAlpha by stringPref(default = "FF")
|
||||||
|
|
||||||
|
var textGlobalColorDark by stringPref(default = "#FFFFFF")
|
||||||
|
var textGlobalAlphaDark by stringPref(default = "FF")
|
||||||
|
|
||||||
|
var textSecondaryColorDark by stringPref(default = "#FFFFFF")
|
||||||
|
var textSecondaryAlphaDark by stringPref(default = "FF")
|
||||||
|
|
||||||
|
var backgroundCardColorDark by stringPref(default = "#000000")
|
||||||
|
var backgroundCardAlphaDark by stringPref(default = "00")
|
||||||
|
|
||||||
|
var clockTextColorDark by stringPref(default = "#FFFFFF")
|
||||||
|
var clockTextAlphaDark by stringPref(default = "FF")
|
||||||
|
|
||||||
|
|
||||||
var showAMPMIndicator by booleanPref(default = true)
|
var showAMPMIndicator by booleanPref(default = true)
|
||||||
|
|
||||||
var weatherIconPack by intPref(default = Constants.WeatherIconPack.DEFAULT.value)
|
var weatherIconPack by intPref(default = Constants.WeatherIconPack.DEFAULT.value)
|
||||||
@ -64,15 +86,22 @@ object Preferences : KotprefModel() {
|
|||||||
var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 18f)
|
var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 18f)
|
||||||
var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 90f)
|
var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 90f)
|
||||||
var clockBottomMargin by intPref(default = Constants.ClockBottomMargin.MEDIUM.value)
|
var clockBottomMargin by intPref(default = Constants.ClockBottomMargin.MEDIUM.value)
|
||||||
|
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 = "")
|
||||||
var textShadow by intPref(key = "PREF_TEXT_SHADOW", default = 1)
|
var textShadow by intPref(key = "PREF_TEXT_SHADOW", default = 1)
|
||||||
|
var textShadowDark by intPref(default = 1)
|
||||||
var showDiffTime by booleanPref(key = "PREF_SHOW_DIFF_TIME", default = true)
|
var showDiffTime by booleanPref(key = "PREF_SHOW_DIFF_TIME", default = true)
|
||||||
var showDeclinedEvents by booleanPref(key = "PREF_SHOW_DECLINED_EVENTS", default = false)
|
var showDeclinedEvents by booleanPref(key = "PREF_SHOW_DECLINED_EVENTS", default = false)
|
||||||
|
var showInvitedEvents by booleanPref(default = false)
|
||||||
|
var showAcceptedEvents by booleanPref(default = true)
|
||||||
|
var showOnlyBusyEvents by booleanPref(default = false)
|
||||||
var secondRowInformation by intPref(key = "PREF_SECOND_ROW_INFORMATION", default = 0)
|
var secondRowInformation by intPref(key = "PREF_SECOND_ROW_INFORMATION", default = 0)
|
||||||
var customFont by intPref(key = "PREF_CUSTOM_FONT", default = Constants.CUSTOM_FONT_PRODUCT_SANS)
|
var customFont by intPref(key = "PREF_CUSTOM_FONT", default = Constants.CUSTOM_FONT_GOOGLE_SANS)
|
||||||
var customFontFile by stringPref(key = "PREF_CUSTOM_FONT_FILE")
|
var customFontFile by stringPref(default = "")
|
||||||
|
var customFontName by stringPref(default = "")
|
||||||
|
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 showDividers by booleanPref(default = true)
|
var showDividers by booleanPref(default = true)
|
||||||
@ -94,6 +123,14 @@ object Preferences : KotprefModel() {
|
|||||||
var isCharging by booleanPref(default = false)
|
var isCharging by booleanPref(default = false)
|
||||||
var googleFitSteps by longPref(default = -1)
|
var googleFitSteps by longPref(default = -1)
|
||||||
var showDailySteps by booleanPref(default = false)
|
var showDailySteps by booleanPref(default = false)
|
||||||
|
var showGreetings by booleanPref(default = false)
|
||||||
|
var showNotifications by booleanPref(default = false)
|
||||||
|
var hideNotificationAfter by intPref(default = Constants.GlanceNotificationTimer.ONE_MINUTE.value)
|
||||||
|
|
||||||
|
var lastNotificationId by intPref(default = -1)
|
||||||
|
var lastNotificationTitle by stringPref(default = "")
|
||||||
|
var lastNotificationIcon by intPref(default = 0)
|
||||||
|
var lastNotificationPackage by stringPref(default = "")
|
||||||
|
|
||||||
var showMusic by booleanPref(default = false)
|
var showMusic by booleanPref(default = false)
|
||||||
var mediaInfoFormat by stringPref(default = "")
|
var mediaInfoFormat by stringPref(default = "")
|
||||||
@ -101,6 +138,8 @@ object Preferences : KotprefModel() {
|
|||||||
var mediaPlayerAlbum by stringPref(default = "")
|
var mediaPlayerAlbum by stringPref(default = "")
|
||||||
var mediaPlayerArtist by stringPref(default = "")
|
var mediaPlayerArtist by stringPref(default = "")
|
||||||
var mediaPlayerPackage by stringPref(default = "")
|
var mediaPlayerPackage by stringPref(default = "")
|
||||||
|
var musicPlayersFilter by stringPref(default = "")
|
||||||
|
var appNotificationsFilter by stringPref(default = "")
|
||||||
|
|
||||||
// Integrations
|
// Integrations
|
||||||
var installedIntegrations by intPref(default = 0)
|
var installedIntegrations by intPref(default = 0)
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
|
import android.content.ContentResolver
|
||||||
|
import android.content.Context
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import com.chibatching.kotpref.Kotpref
|
||||||
|
import com.chibatching.kotpref.blockingBulk
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.NotificationListener
|
||||||
|
|
||||||
|
object ActiveNotificationsHelper {
|
||||||
|
fun showLastNotification(): Boolean {
|
||||||
|
return Preferences.lastNotificationId != -1 && Preferences.lastNotificationIcon != 0 && Preferences.lastNotificationPackage.isNotBlank() && Preferences.lastNotificationTitle.isNotBlank()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearLastNotification(context: Context) {
|
||||||
|
Kotpref.init(context)
|
||||||
|
Preferences.blockingBulk {
|
||||||
|
remove(Preferences::lastNotificationId)
|
||||||
|
remove(Preferences::lastNotificationTitle)
|
||||||
|
remove(Preferences::lastNotificationPackage)
|
||||||
|
remove(Preferences::lastNotificationIcon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkNotificationAccess(context: Context): Boolean {
|
||||||
|
val contentResolver: ContentResolver = context.contentResolver
|
||||||
|
val enabledNotificationListeners =
|
||||||
|
Settings.Secure.getString(contentResolver, "enabled_notification_listeners")
|
||||||
|
val packageName: String = context.packageName
|
||||||
|
return NotificationManagerCompat.getEnabledListenerPackages(context).contains(packageName) && (enabledNotificationListeners != null && enabledNotificationListeners.contains(NotificationListener::class.java.name))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isAppAccepted(appPkg: String): Boolean = Preferences.appNotificationsFilter == "" || Preferences.appNotificationsFilter.contains(appPkg)
|
||||||
|
|
||||||
|
fun toggleAppFilter(appPkg: String) {
|
||||||
|
if (Preferences.appNotificationsFilter == "" || !Preferences.appNotificationsFilter.contains(appPkg)) {
|
||||||
|
Preferences.appNotificationsFilter = Preferences.appNotificationsFilter.split(",").union(listOf(appPkg)).joinToString(separator = ",")
|
||||||
|
} else {
|
||||||
|
Preferences.appNotificationsFilter = Preferences.appNotificationsFilter.split(",").filter { it != appPkg }.joinToString(separator = ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,14 @@
|
|||||||
package com.tommasoberlose.anotherwidget.helpers
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
import android.app.AlarmManager
|
import android.app.AlarmManager
|
||||||
|
import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Actions
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -12,9 +17,9 @@ object AlarmHelper {
|
|||||||
val alarm = nextAlarmClock
|
val alarm = nextAlarmClock
|
||||||
return if (
|
return if (
|
||||||
alarm != null
|
alarm != null
|
||||||
&& alarm.triggerTime - Calendar.getInstance().timeInMillis > 10 * 60 * 1000
|
&& alarm.triggerTime - Calendar.getInstance().timeInMillis > 5 * 60 * 1000
|
||||||
&& alarm.triggerTime - Calendar.getInstance().timeInMillis < 12 * 60 * 60 * 1000
|
|
||||||
) {
|
) {
|
||||||
|
setTimeout(context, alarm.triggerTime)
|
||||||
"%s %s".format(
|
"%s %s".format(
|
||||||
SimpleDateFormat("EEE", Locale.getDefault()).format(alarm.triggerTime),
|
SimpleDateFormat("EEE", Locale.getDefault()).format(alarm.triggerTime),
|
||||||
DateFormat.getTimeFormat(context).format(Date(alarm.triggerTime))
|
DateFormat.getTimeFormat(context).format(Date(alarm.triggerTime))
|
||||||
@ -33,4 +38,25 @@ object AlarmHelper {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setTimeout(context: Context, trigger: Long) {
|
||||||
|
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, 0))
|
||||||
|
setExact(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
trigger,
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
ALARM_UPDATE_ID,
|
||||||
|
intent,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private const val ALARM_UPDATE_ID = 24953
|
||||||
}
|
}
|
@ -104,13 +104,12 @@ object BitmapHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun drawableToBitmap(drawable: Drawable): Bitmap? {
|
fun drawableToBitmap(drawable: Drawable): Bitmap? {
|
||||||
var bitmap: Bitmap? = null
|
|
||||||
if (drawable is BitmapDrawable) {
|
if (drawable is BitmapDrawable) {
|
||||||
if (drawable.bitmap != null) {
|
if (drawable.bitmap != null) {
|
||||||
return drawable.bitmap
|
return drawable.bitmap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bitmap = if (drawable.intrinsicWidth <= 0 || drawable.intrinsicHeight <= 0) {
|
val bitmap: Bitmap = if (drawable.intrinsicWidth <= 0 || drawable.intrinsicHeight <= 0) {
|
||||||
Bitmap.createBitmap(
|
Bitmap.createBitmap(
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
|
@ -69,4 +69,38 @@ object CalendarHelper {
|
|||||||
fun removeEventUpdatesAndroidN(context: Context) {
|
fun removeEventUpdatesAndroidN(context: Context) {
|
||||||
EventListenerJob.remove(context)
|
EventListenerJob.remove(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun List<Event>.applyFilters() : List<Event> {
|
||||||
|
return this
|
||||||
|
.asSequence()
|
||||||
|
.filter { (Preferences.showDeclinedEvents || it.selfAttendeeStatus != CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED) }
|
||||||
|
.filter { (Preferences.showAcceptedEvents || it.selfAttendeeStatus != CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED) }
|
||||||
|
.filter { (Preferences.showInvitedEvents || it.selfAttendeeStatus != CalendarContract.Attendees.ATTENDEE_STATUS_INVITED) }
|
||||||
|
.filter { (Preferences.calendarAllDay || !it.allDay) }
|
||||||
|
.filter { (!Preferences.showOnlyBusyEvents || it.availability != CalendarContract.EventsEntity.AVAILABILITY_FREE) }
|
||||||
|
.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun List<Event>.sortEvents(): List<Event> {
|
||||||
|
return sortedWith { event: Event, event1: Event ->
|
||||||
|
val date = Calendar.getInstance().apply { timeInMillis = event.startDate }
|
||||||
|
val date1 = Calendar.getInstance().apply { timeInMillis = event1.startDate }
|
||||||
|
|
||||||
|
if (date.get(Calendar.DAY_OF_YEAR) == date1.get(Calendar.DAY_OF_YEAR) && date.get(
|
||||||
|
Calendar.YEAR) == date1.get(Calendar.YEAR)
|
||||||
|
) {
|
||||||
|
if (event.allDay && event1.allDay) {
|
||||||
|
event.startDate.compareTo(event1.startDate)
|
||||||
|
} else if (event.allDay) {
|
||||||
|
1
|
||||||
|
} else if (event1.allDay) {
|
||||||
|
-1
|
||||||
|
} else {
|
||||||
|
event.startDate.compareTo(event1.startDate)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
event.startDate.compareTo(event1.startDate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -7,97 +7,97 @@ import com.tommasoberlose.anotherwidget.global.Preferences
|
|||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
object ColorHelper {
|
object ColorHelper {
|
||||||
fun getFontColor(): Int {
|
fun getFontColor(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
Color.parseColor("#%s%s".format(Preferences.textGlobalAlpha, Preferences.textGlobalColor.replace("#", "")))
|
Color.parseColor("#%s%s".format(if (!isDark) Preferences.textGlobalAlpha else Preferences.textGlobalAlphaDark, (if (!isDark) Preferences.textGlobalColor else Preferences.textGlobalColorDark).replace("#", "")))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Color.parseColor("#FFFFFFFF")
|
Color.parseColor("#FFFFFFFF")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFontColorAlpha(): Int {
|
fun getFontColorAlpha(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
Preferences.textGlobalAlpha.toIntValue().toDouble() * 255 / 100
|
(if (!isDark) Preferences.textGlobalAlpha else Preferences.textGlobalAlphaDark).toIntValue().toDouble() * 255 / 100
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
"FF".toIntValue().toDouble() * 255 / 100
|
"FF".toIntValue().toDouble() * 255 / 100
|
||||||
}.roundToInt()
|
}.roundToInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFontColorRgb(): Int {
|
fun getFontColorRgb(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
Color.parseColor(Preferences.textGlobalColor)
|
Color.parseColor((if (!isDark) Preferences.textGlobalColor else Preferences.textGlobalColorDark))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Color.parseColor("#000000")
|
Color.parseColor("#000000")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSecondaryFontColor(): Int {
|
fun getSecondaryFontColor(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
Color.parseColor("#%s%s".format(Preferences.textSecondaryAlpha, Preferences.textSecondaryColor.replace("#", "")))
|
Color.parseColor("#%s%s".format((if (!isDark) Preferences.textSecondaryAlpha else Preferences.textSecondaryAlphaDark), (if (!isDark) Preferences.textSecondaryColor else Preferences.textSecondaryColorDark).replace("#", "")))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Color.parseColor("#FFFFFFFF")
|
Color.parseColor("#FFFFFFFF")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSecondaryFontColorAlpha(): Int {
|
fun getSecondaryFontColorAlpha(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
Preferences.textSecondaryAlpha.toIntValue().toDouble() * 255 / 100
|
(if (!isDark) Preferences.textSecondaryAlpha else Preferences.textSecondaryAlphaDark).toIntValue().toDouble() * 255 / 100
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
"FF".toIntValue().toDouble() * 255 / 100
|
"FF".toIntValue().toDouble() * 255 / 100
|
||||||
}.roundToInt()
|
}.roundToInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSecondaryFontColorRgb(): Int {
|
fun getSecondaryFontColorRgb(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
Color.parseColor(Preferences.textSecondaryColor)
|
Color.parseColor((if (!isDark) Preferences.textSecondaryColor else Preferences.textSecondaryColorDark))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Color.parseColor("#000000")
|
Color.parseColor("#000000")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getClockFontColor(): Int {
|
fun getClockFontColor(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
Color.parseColor("#%s%s".format(Preferences.clockTextAlpha, Preferences.clockTextColor.replace("#", "")))
|
Color.parseColor("#%s%s".format((if (!isDark) Preferences.clockTextAlpha else Preferences.clockTextAlphaDark), (if (!isDark) Preferences.clockTextColor else Preferences.clockTextColorDark).replace("#", "")))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Color.parseColor("#FFFFFFFF")
|
Color.parseColor("#FFFFFFFF")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getClockFontColorAlpha(): Int {
|
fun getClockFontColorAlpha(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
Preferences.clockTextAlpha.toIntValue().toDouble() * 255 / 100
|
(if (!isDark) Preferences.clockTextAlpha else Preferences.clockTextAlphaDark).toIntValue().toDouble() * 255 / 100
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
"FF".toIntValue().toDouble() * 255 / 100
|
"FF".toIntValue().toDouble() * 255 / 100
|
||||||
}.roundToInt()
|
}.roundToInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getClockFontColorRgb(): Int {
|
fun getClockFontColorRgb(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
Color.parseColor(Preferences.clockTextColor)
|
Color.parseColor((if (!isDark) Preferences.clockTextColor else Preferences.clockTextColorDark))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Color.parseColor("#000000")
|
Color.parseColor("#000000")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBackgroundColor(): Int {
|
fun getBackgroundColor(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
Color.parseColor("#%s%s".format(Preferences.backgroundCardAlpha, Preferences.backgroundCardColor.replace("#", "")))
|
Color.parseColor("#%s%s".format((if (!isDark) Preferences.backgroundCardAlpha else Preferences.backgroundCardAlphaDark), (if (!isDark) Preferences.backgroundCardColor else Preferences.backgroundCardColorDark).replace("#", "")))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Color.parseColor("#00000000")
|
Color.parseColor("#00000000")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBackgroundAlpha(): Int {
|
fun getBackgroundAlpha(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
Preferences.backgroundCardAlpha.toIntValue().toDouble() * 255 / 100
|
(if (!isDark) Preferences.backgroundCardAlpha else Preferences.backgroundCardAlphaDark).toIntValue().toDouble() * 255 / 100
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
"00".toIntValue().toDouble() * 255 / 100
|
"00".toIntValue().toDouble() * 255 / 100
|
||||||
}.roundToInt()
|
}.roundToInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBackgroundColorRgb(): Int {
|
fun getBackgroundColorRgb(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
Color.parseColor(Preferences.backgroundCardColor)
|
Color.parseColor((if (!isDark) Preferences.backgroundCardColor else Preferences.backgroundCardColorDark))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Color.parseColor("#000000")
|
Color.parseColor("#000000")
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package com.tommasoberlose.anotherwidget.helpers
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.text.format.DateUtils
|
import android.text.format.DateUtils
|
||||||
import android.util.Log
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.utils.getCapWordString
|
import com.tommasoberlose.anotherwidget.utils.getCapWordString
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
@ -17,7 +16,11 @@ object DateHelper {
|
|||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
getDefaultDateText(context, date)
|
getDefaultDateText(context, date)
|
||||||
}
|
}
|
||||||
if (Preferences.isDateCapitalize) text.getCapWordString() else text
|
when {
|
||||||
|
Preferences.isDateUppercase -> text.toUpperCase(Locale.getDefault())
|
||||||
|
Preferences.isDateCapitalize -> text.getCapWordString()
|
||||||
|
else -> text
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
val flags: Int =
|
val flags: Int =
|
||||||
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
||||||
@ -25,17 +28,20 @@ object DateHelper {
|
|||||||
SimpleDateFormat("EEEE", Locale.getDefault()).format(date.time),
|
SimpleDateFormat("EEEE", Locale.getDefault()).format(date.time),
|
||||||
DateUtils.formatDateTime(context, date.timeInMillis, flags)
|
DateUtils.formatDateTime(context, date.timeInMillis, flags)
|
||||||
)
|
)
|
||||||
if (Preferences.isDateCapitalize) text.getCapWordString() else text
|
when {
|
||||||
|
Preferences.isDateUppercase -> text.toUpperCase(Locale.getDefault())
|
||||||
|
Preferences.isDateCapitalize -> text.getCapWordString()
|
||||||
|
else -> text
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDefaultDateText(context: Context, date: Calendar): String {
|
fun getDefaultDateText(context: Context, date: Calendar): String {
|
||||||
val flags: Int =
|
val flags: Int =
|
||||||
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
||||||
val text = "%s, %s".format(
|
return "%s, %s".format(
|
||||||
SimpleDateFormat("EEEE", Locale.getDefault()).format(date.time),
|
SimpleDateFormat("EEEE", Locale.getDefault()).format(date.time),
|
||||||
DateUtils.formatDateTime(context, date.timeInMillis, flags)
|
DateUtils.formatDateTime(context, date.timeInMillis, flags)
|
||||||
)
|
)
|
||||||
return if (Preferences.isDateCapitalize) text.getCapWordString() else text
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,7 +17,8 @@ object GlanceProviderHelper {
|
|||||||
val providers = Constants.GlanceProviderId.values()
|
val providers = Constants.GlanceProviderId.values()
|
||||||
.filter {
|
.filter {
|
||||||
context.checkIfFitInstalled() || it != Constants.GlanceProviderId.GOOGLE_FIT_STEPS
|
context.checkIfFitInstalled() || it != Constants.GlanceProviderId.GOOGLE_FIT_STEPS
|
||||||
}.toTypedArray()
|
}
|
||||||
|
.toTypedArray()
|
||||||
|
|
||||||
providers.sortWith(Comparator { p1, p2 ->
|
providers.sortWith(Comparator { p1, p2 ->
|
||||||
when {
|
when {
|
||||||
@ -35,7 +36,6 @@ object GlanceProviderHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return ArrayList(providers.toList())
|
return ArrayList(providers.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ object GlanceProviderHelper {
|
|||||||
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
||||||
GlanceProvider(providerId.id,
|
GlanceProvider(providerId.id,
|
||||||
context.getString(R.string.settings_show_next_alarm_title),
|
context.getString(R.string.settings_show_next_alarm_title),
|
||||||
R.drawable.round_alarm
|
R.drawable.round_access_alarm
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||||
@ -56,7 +56,7 @@ object GlanceProviderHelper {
|
|||||||
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
||||||
GlanceProvider(providerId.id,
|
GlanceProvider(providerId.id,
|
||||||
context.getString(R.string.settings_custom_notes_title),
|
context.getString(R.string.settings_custom_notes_title),
|
||||||
R.drawable.round_notes
|
R.drawable.round_sticky_note_2
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
||||||
@ -68,7 +68,19 @@ object GlanceProviderHelper {
|
|||||||
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||||
GlanceProvider(providerId.id,
|
GlanceProvider(providerId.id,
|
||||||
context.getString(R.string.settings_daily_steps_title),
|
context.getString(R.string.settings_daily_steps_title),
|
||||||
R.drawable.round_directions_walk
|
R.drawable.round_near_me
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.NOTIFICATIONS -> {
|
||||||
|
GlanceProvider(providerId.id,
|
||||||
|
context.getString(R.string.settings_show_notifications_title),
|
||||||
|
R.drawable.round_notifications
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.GREETINGS -> {
|
||||||
|
GlanceProvider(providerId.id,
|
||||||
|
context.getString(R.string.settings_show_greetings_title),
|
||||||
|
R.drawable.round_history_edu
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -82,12 +94,15 @@ object GlanceProviderHelper {
|
|||||||
val eventRepository = EventRepository(context)
|
val eventRepository = EventRepository(context)
|
||||||
BatteryHelper.updateBatteryInfo(context)
|
BatteryHelper.updateBatteryInfo(context)
|
||||||
|
|
||||||
val showGlance = Preferences.showGlance && (eventRepository.getEventsCount() == 0 || !Preferences.showEvents) && (
|
val showGlance = Preferences.showGlance && (eventRepository.getEventsCount() == 0 || !Preferences.showEvents)
|
||||||
|
&& (
|
||||||
|
(Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) ||
|
||||||
(Preferences.showNextAlarm && AlarmHelper.getNextAlarm(context) != "") ||
|
(Preferences.showNextAlarm && AlarmHelper.getNextAlarm(context) != "") ||
|
||||||
(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.showDailySteps && Preferences.googleFitSteps > 0)
|
(Preferences.showDailySteps && Preferences.googleFitSteps > 0) ||
|
||||||
|
(Preferences.showGreetings && GreetingsHelper.showGreetings())
|
||||||
)
|
)
|
||||||
eventRepository.close()
|
eventRepository.close()
|
||||||
return showGlance
|
return showGlance
|
||||||
|
@ -0,0 +1,110 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
|
import android.app.AlarmManager
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Actions
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
object GreetingsHelper {
|
||||||
|
private const val MORNING_TIME = 36
|
||||||
|
private const val MORNING_TIME_END = 37
|
||||||
|
private const val EVENING_TIME = 38
|
||||||
|
private const val NIGHT_TIME = 39
|
||||||
|
|
||||||
|
fun toggleGreetings(context: Context) {
|
||||||
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
|
val now = Calendar.getInstance().apply {
|
||||||
|
set(Calendar.SECOND, 0)
|
||||||
|
set(Calendar.MILLISECOND, 0)
|
||||||
|
set(Calendar.MINUTE, 0)
|
||||||
|
set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
}
|
||||||
|
if (Preferences.showGreetings) {
|
||||||
|
setRepeating(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
now.apply {
|
||||||
|
set(Calendar.HOUR_OF_DAY, 5)
|
||||||
|
}.timeInMillis,
|
||||||
|
1000 * 60 * 60 * 24,
|
||||||
|
PendingIntent.getBroadcast(context,
|
||||||
|
MORNING_TIME,
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_UPDATE_GREETINGS
|
||||||
|
},
|
||||||
|
0)
|
||||||
|
)
|
||||||
|
|
||||||
|
setRepeating(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
now.apply {
|
||||||
|
set(Calendar.HOUR_OF_DAY, 9)
|
||||||
|
}.timeInMillis,
|
||||||
|
1000 * 60 * 60 * 24,
|
||||||
|
PendingIntent.getBroadcast(context,
|
||||||
|
MORNING_TIME_END,
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_UPDATE_GREETINGS
|
||||||
|
},
|
||||||
|
0)
|
||||||
|
)
|
||||||
|
|
||||||
|
setRepeating(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
now.apply {
|
||||||
|
set(Calendar.HOUR_OF_DAY, 19)
|
||||||
|
}.timeInMillis,
|
||||||
|
1000 * 60 * 60 * 24,
|
||||||
|
PendingIntent.getBroadcast(context,
|
||||||
|
EVENING_TIME,
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_UPDATE_GREETINGS
|
||||||
|
},
|
||||||
|
0)
|
||||||
|
)
|
||||||
|
|
||||||
|
setRepeating(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
now.apply {
|
||||||
|
set(Calendar.HOUR_OF_DAY, 22)
|
||||||
|
}.timeInMillis,
|
||||||
|
1000 * 60 * 60 * 24,
|
||||||
|
PendingIntent.getBroadcast(context,
|
||||||
|
NIGHT_TIME,
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_UPDATE_GREETINGS
|
||||||
|
},
|
||||||
|
0)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
listOf(MORNING_TIME, MORNING_TIME_END, EVENING_TIME, NIGHT_TIME).forEach {
|
||||||
|
cancel(PendingIntent.getBroadcast(context, it, Intent(context,
|
||||||
|
UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_UPDATE_GREETINGS
|
||||||
|
}, 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showGreetings(): Boolean {
|
||||||
|
val hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY)
|
||||||
|
return hour < 9 || hour >= 19
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRandomString(context: Context): String {
|
||||||
|
val hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY)
|
||||||
|
val array = when {
|
||||||
|
hour in 5..8 -> context.resources.getStringArray(R.array.morning_greetings)
|
||||||
|
hour in 19..21 -> context.resources.getStringArray(R.array.evening_greetings)
|
||||||
|
hour >= 22 && hour < 5 -> context.resources.getStringArray(R.array.night_greetings)
|
||||||
|
else -> emptyArray()
|
||||||
|
}
|
||||||
|
return if (array.isNotEmpty()) array[Random().nextInt(array.size)] else ""
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.*
|
||||||
|
import android.renderscript.*
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.widget.ImageView
|
||||||
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||||
|
import java.util.prefs.Preferences
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
object ImageHelper {
|
||||||
|
fun ImageView.applyShadow(originalView: ImageView, factor: Float = 1f) {
|
||||||
|
clearColorFilter()
|
||||||
|
val cElevation = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, when (if (context.isDarkTheme()) com.tommasoberlose.anotherwidget.global.Preferences.textShadowDark else com.tommasoberlose.anotherwidget.global.Preferences.textShadow) {
|
||||||
|
0 -> 0f * factor
|
||||||
|
1 -> 8f * factor
|
||||||
|
2 -> 16f * factor
|
||||||
|
else -> 0f * factor
|
||||||
|
}, resources.displayMetrics)
|
||||||
|
|
||||||
|
if (originalView.drawable != null) {
|
||||||
|
val btm = originalView.drawable.toBitmap().copy(Bitmap.Config.ARGB_8888, true)
|
||||||
|
val comb = Bitmap.createBitmap(btm)
|
||||||
|
val shadowBitmap = generateShadowBitmap(context, cElevation, btm, factor)
|
||||||
|
|
||||||
|
shadowBitmap?.let {
|
||||||
|
val canvas = Canvas(comb)
|
||||||
|
canvas.drawColor(Color.TRANSPARENT)
|
||||||
|
canvas.save()
|
||||||
|
val rect = Rect()
|
||||||
|
val bounds = originalView.drawable.copyBounds()
|
||||||
|
canvas.getClipBounds(rect)
|
||||||
|
rect.inset(-2 * getBlurRadius(context, cElevation).toInt(), -2 * getBlurRadius(context, cElevation).toInt())
|
||||||
|
canvas.save()
|
||||||
|
canvas.clipRect(rect)
|
||||||
|
canvas.drawBitmap(shadowBitmap, 0f, 2f, null)
|
||||||
|
canvas.restore()
|
||||||
|
setImageBitmap(comb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateShadowBitmap(context: Context, cElevation: Float, bitmap: Bitmap?, factor: Float): Bitmap? {
|
||||||
|
val rs: RenderScript = RenderScript.create(context)
|
||||||
|
val element = Element.U8_4(rs)
|
||||||
|
val blurScript: ScriptIntrinsicBlur = ScriptIntrinsicBlur.create(rs, element)
|
||||||
|
val colorMatrixScript: ScriptIntrinsicColorMatrix = ScriptIntrinsicColorMatrix.create(rs)
|
||||||
|
val allocationIn = Allocation.createFromBitmap(rs, bitmap)
|
||||||
|
val allocationOut = Allocation.createTyped(rs, allocationIn.type)
|
||||||
|
|
||||||
|
val matrix = Matrix4f(floatArrayOf(
|
||||||
|
0f, 0f, 0f, 0f,
|
||||||
|
0f, 0f, 0f, 0f,
|
||||||
|
0f, 0f, 0f, 0f,
|
||||||
|
0f, 0f, 0f, when (if (context.isDarkTheme()) com.tommasoberlose.anotherwidget.global.Preferences.textShadowDark else com.tommasoberlose.anotherwidget.global.Preferences.textShadow) {
|
||||||
|
0 -> 0f * factor
|
||||||
|
1 -> 0.8f * factor
|
||||||
|
2 -> 1f * factor
|
||||||
|
else -> 0f
|
||||||
|
}))
|
||||||
|
|
||||||
|
colorMatrixScript.setColorMatrix(matrix)
|
||||||
|
colorMatrixScript.forEach(allocationIn, allocationOut)
|
||||||
|
|
||||||
|
blurScript.setRadius(getBlurRadius(context, cElevation))
|
||||||
|
|
||||||
|
blurScript.setInput(allocationOut)
|
||||||
|
blurScript.forEach(allocationIn)
|
||||||
|
|
||||||
|
allocationIn.copyTo(bitmap)
|
||||||
|
|
||||||
|
allocationIn.destroy()
|
||||||
|
allocationOut.destroy()
|
||||||
|
|
||||||
|
return bitmap
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBlurRadius(context: Context, customElevation: Float): Float {
|
||||||
|
val maxElevation = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24f, context.resources.displayMetrics)
|
||||||
|
return min(25f * (customElevation / maxElevation), 25f)
|
||||||
|
}
|
||||||
|
}
|
@ -66,7 +66,6 @@ object IntentHelper {
|
|||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
context.toast(context.getString(R.string.error_opening_app))
|
|
||||||
Intent()
|
Intent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -96,7 +95,6 @@ object IntentHelper {
|
|||||||
data = calendarUri
|
data = calendarUri
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
context.toast(context.getString(R.string.error_opening_app))
|
|
||||||
Intent()
|
Intent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,7 +179,6 @@ object IntentHelper {
|
|||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
context.toast(context.getString(R.string.error_opening_app))
|
|
||||||
Intent()
|
Intent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -204,7 +201,6 @@ object IntentHelper {
|
|||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
context.toast(context.getString(R.string.error_opening_app))
|
|
||||||
Intent()
|
Intent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,7 +214,17 @@ object IntentHelper {
|
|||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
context.toast(context.getString(R.string.error_opening_app))
|
Intent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getNotificationIntent(context: Context): Intent {
|
||||||
|
val pm: PackageManager = context.packageManager
|
||||||
|
return try {
|
||||||
|
pm.getLaunchIntentForPackage(Preferences.lastNotificationPackage)!!.apply {
|
||||||
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
Intent()
|
Intent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,21 @@
|
|||||||
package com.tommasoberlose.anotherwidget.helpers
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
import android.app.Notification
|
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.media.MediaMetadata
|
import android.media.MediaMetadata
|
||||||
import android.media.session.MediaController
|
import android.media.session.MediaController
|
||||||
import android.media.session.MediaSession
|
|
||||||
import android.media.session.MediaSessionManager
|
import android.media.session.MediaSessionManager
|
||||||
import android.media.session.PlaybackState
|
import android.media.session.PlaybackState
|
||||||
import android.util.Log
|
import com.chibatching.kotpref.Kotpref
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import com.chibatching.kotpref.blockingBulk
|
||||||
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.receivers.MusicNotificationListener
|
import com.tommasoberlose.anotherwidget.receivers.NotificationListener
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
|
|
||||||
object MediaPlayerHelper {
|
object MediaPlayerHelper {
|
||||||
fun isSomeonePlaying(context: Context) = Preferences.showMusic && NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName) && Preferences.mediaPlayerTitle != ""
|
fun isSomeonePlaying(context: Context) = Preferences.showMusic && ActiveNotificationsHelper.checkNotificationAccess(context) && Preferences.mediaPlayerTitle != ""
|
||||||
|
|
||||||
fun getMediaInfo(): String {
|
fun getMediaInfo(): String {
|
||||||
return if (Preferences.mediaPlayerArtist == "") {
|
return if (Preferences.mediaPlayerArtist == "") {
|
||||||
@ -28,13 +26,16 @@ object MediaPlayerHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun updatePlayingMediaInfo(context: Context) {
|
fun updatePlayingMediaInfo(context: Context) {
|
||||||
if (NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName)) {
|
Kotpref.init(context)
|
||||||
|
if (ActiveNotificationsHelper.checkNotificationAccess(context)) {
|
||||||
val list = try {
|
val list = try {
|
||||||
(context.getSystemService(Context.MEDIA_SESSION_SERVICE) as MediaSessionManager).getActiveSessions(
|
(context.getSystemService(Context.MEDIA_SESSION_SERVICE) as MediaSessionManager).getActiveSessions(
|
||||||
ComponentName(context.packageName, MusicNotificationListener::class.java.name)
|
ComponentName(context.packageName, NotificationListener::class.java.name)
|
||||||
)
|
)
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
emptyList<MediaController>()
|
emptyList<MediaController>()
|
||||||
|
}.filter {
|
||||||
|
Preferences.musicPlayersFilter == "" || isMusicPlayerAccepted(it.packageName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list.isNotEmpty()) {
|
if (list.isNotEmpty()) {
|
||||||
@ -65,24 +66,35 @@ object MediaPlayerHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isSomeonePlaying) {
|
if (!isSomeonePlaying) {
|
||||||
removeMediaInfo()
|
removeMediaInfo(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
removeMediaInfo()
|
removeMediaInfo(context)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
removeMediaInfo()
|
removeMediaInfo(context)
|
||||||
}
|
}
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeMediaInfo() {
|
private fun removeMediaInfo(context: Context) {
|
||||||
Preferences.bulk {
|
Kotpref.init(context)
|
||||||
|
Preferences.blockingBulk {
|
||||||
remove(Preferences::mediaPlayerTitle)
|
remove(Preferences::mediaPlayerTitle)
|
||||||
remove(Preferences::mediaPlayerArtist)
|
remove(Preferences::mediaPlayerArtist)
|
||||||
remove(Preferences::mediaPlayerAlbum)
|
remove(Preferences::mediaPlayerAlbum)
|
||||||
remove(Preferences::mediaPlayerPackage)
|
remove(Preferences::mediaPlayerPackage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isMusicPlayerAccepted(appPkg: String): Boolean = Preferences.musicPlayersFilter == "" || Preferences.musicPlayersFilter.contains(appPkg)
|
||||||
|
|
||||||
|
fun toggleMusicPlayerFilter(appPkg: String) {
|
||||||
|
if (Preferences.musicPlayersFilter == "" || !Preferences.musicPlayersFilter.contains(appPkg)) {
|
||||||
|
Preferences.musicPlayersFilter = Preferences.musicPlayersFilter.split(",").union(listOf(appPkg)).joinToString(separator = ",")
|
||||||
|
} else {
|
||||||
|
Preferences.musicPlayersFilter = Preferences.musicPlayersFilter.split(",").filter { it != appPkg }.joinToString(separator = ",")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -54,14 +54,27 @@ object SettingsStringHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCustomFontLabel(shadow: Int): Int {
|
fun getCustomFontLabel(context: Context, font: Int): String {
|
||||||
return when (shadow) {
|
return when (font) {
|
||||||
0 -> R.string.custom_font_subtitle_0
|
Constants.CUSTOM_FONT_GOOGLE_SANS -> context.getString(R.string.custom_font_subtitle_1) + " - ${getVariantLabel(context, Preferences.customFontVariant)}"
|
||||||
1 -> R.string.custom_font_subtitle_1
|
Constants.CUSTOM_FONT_DOWNLOADED -> Preferences.customFontName + " - ${getVariantLabel(context, Preferences.customFontVariant)}"
|
||||||
else -> R.string.custom_font_subtitle_1
|
else -> context.getString(R.string.custom_font_subtitle_0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getVariantLabel(context: Context, variant: String): String = when {
|
||||||
|
variant.contains("100") -> context.getString(R.string.font_100)
|
||||||
|
variant.contains("200") -> context.getString(R.string.font_200)
|
||||||
|
variant.contains("300") -> context.getString(R.string.font_300)
|
||||||
|
variant.contains("regular") || variant.contains("400") -> context.getString(R.string.font_400)
|
||||||
|
variant.contains("500") -> context.getString(R.string.font_500)
|
||||||
|
variant.contains("600") -> context.getString(R.string.font_600)
|
||||||
|
variant.contains("700") -> context.getString(R.string.font_700)
|
||||||
|
variant.contains("800") -> context.getString(R.string.font_800)
|
||||||
|
variant.contains("900") -> context.getString(R.string.font_900)
|
||||||
|
else -> context.getString(R.string.font_400)
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -3,6 +3,8 @@ 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.os.Build
|
||||||
|
import android.util.Log
|
||||||
|
import com.chibatching.kotpref.Kotpref
|
||||||
import com.google.android.gms.location.LocationServices
|
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
|
||||||
@ -11,6 +13,10 @@ import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
|||||||
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 com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
|
||||||
|
|
||||||
@ -20,7 +26,8 @@ import org.greenrobot.eventbus.EventBus
|
|||||||
|
|
||||||
object WeatherHelper {
|
object WeatherHelper {
|
||||||
|
|
||||||
fun updateWeather(context: Context) {
|
suspend fun updateWeather(context: Context) {
|
||||||
|
Kotpref.init(context)
|
||||||
val networkApi = WeatherNetworkApi(context)
|
val networkApi = WeatherNetworkApi(context)
|
||||||
if (Preferences.customLocationAdd != "") {
|
if (Preferences.customLocationAdd != "") {
|
||||||
networkApi.updateWeather()
|
networkApi.updateWeather()
|
||||||
@ -31,10 +38,17 @@ object WeatherHelper {
|
|||||||
if (location != null) {
|
if (location != null) {
|
||||||
Preferences.customLocationLat = location.latitude.toString()
|
Preferences.customLocationLat = location.latitude.toString()
|
||||||
Preferences.customLocationLon = location.longitude.toString()
|
Preferences.customLocationLon = location.longitude.toString()
|
||||||
|
|
||||||
networkApi.updateWeather()
|
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
networkApi.updateWeather()
|
||||||
|
}
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
} else {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
networkApi.updateWeather()
|
||||||
|
}
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,17 +57,92 @@ object WeatherHelper {
|
|||||||
fun removeWeather(context: Context) {
|
fun removeWeather(context: Context) {
|
||||||
Preferences.remove(Preferences::weatherTemp)
|
Preferences.remove(Preferences::weatherTemp)
|
||||||
Preferences.remove(Preferences::weatherRealTempUnit)
|
Preferences.remove(Preferences::weatherRealTempUnit)
|
||||||
|
Preferences.remove(Preferences::weatherIcon)
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getWeatherIconResource(icon: String, style: Int = Preferences.weatherIconPack): Int {
|
fun getProviderName(context: Context, provider: Constants.WeatherProvider = Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!): String {
|
||||||
|
return context.getString(when(provider) {
|
||||||
|
Constants.WeatherProvider.OPEN_WEATHER -> R.string.settings_weather_provider_open_weather
|
||||||
|
Constants.WeatherProvider.WEATHER_BIT -> R.string.settings_weather_provider_weatherbit
|
||||||
|
Constants.WeatherProvider.WEATHER_API -> R.string.settings_weather_provider_weather_api
|
||||||
|
Constants.WeatherProvider.HERE -> R.string.settings_weather_provider_here
|
||||||
|
Constants.WeatherProvider.ACCUWEATHER -> R.string.settings_weather_provider_accuweather
|
||||||
|
Constants.WeatherProvider.WEATHER_GOV -> R.string.settings_weather_provider_weather_gov
|
||||||
|
Constants.WeatherProvider.YR -> R.string.settings_weather_provider_yr
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getProviderInfoTitle(context: Context, provider: Constants.WeatherProvider? = Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!): String {
|
||||||
|
return context.getString(when(provider) {
|
||||||
|
Constants.WeatherProvider.OPEN_WEATHER -> R.string.weather_provider_info_open_weather_title
|
||||||
|
Constants.WeatherProvider.WEATHER_BIT -> R.string.weather_provider_info_weatherbit_title
|
||||||
|
Constants.WeatherProvider.WEATHER_API -> R.string.weather_provider_info_weatherapi_title
|
||||||
|
Constants.WeatherProvider.HERE -> R.string.weather_provider_info_here_title
|
||||||
|
Constants.WeatherProvider.ACCUWEATHER -> R.string.weather_provider_info_accuweather_title
|
||||||
|
Constants.WeatherProvider.WEATHER_GOV -> R.string.weather_provider_info_weather_gov_title
|
||||||
|
Constants.WeatherProvider.YR -> R.string.weather_provider_info_yr_title
|
||||||
|
else -> R.string.nothing
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getProviderInfoSubtitle(context: Context, provider: Constants.WeatherProvider? = Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!): String {
|
||||||
|
return context.getString(when(provider) {
|
||||||
|
Constants.WeatherProvider.OPEN_WEATHER -> R.string.weather_provider_info_open_weather_subtitle
|
||||||
|
Constants.WeatherProvider.WEATHER_BIT -> R.string.weather_provider_info_weatherbit_subtitle
|
||||||
|
Constants.WeatherProvider.WEATHER_API -> R.string.weather_provider_info_weatherapi_subtitle
|
||||||
|
Constants.WeatherProvider.HERE -> R.string.weather_provider_info_here_subtitle
|
||||||
|
Constants.WeatherProvider.ACCUWEATHER -> R.string.weather_provider_info_accuweather_subtitle
|
||||||
|
Constants.WeatherProvider.WEATHER_GOV -> R.string.weather_provider_info_weather_gov_subtitle
|
||||||
|
Constants.WeatherProvider.YR -> R.string.weather_provider_info_yr_subtitle
|
||||||
|
else -> R.string.nothing
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getProviderLink(provider: Constants.WeatherProvider? = Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!): String {
|
||||||
|
return when(provider) {
|
||||||
|
Constants.WeatherProvider.OPEN_WEATHER -> "https://home.openweathermap.org/users/sign_in"
|
||||||
|
Constants.WeatherProvider.WEATHER_BIT -> "https://www.weatherbit.io/account/login"
|
||||||
|
Constants.WeatherProvider.WEATHER_API -> "https://www.weatherapi.com/login.aspx"
|
||||||
|
Constants.WeatherProvider.HERE -> "https://developer.here.com/login"
|
||||||
|
Constants.WeatherProvider.ACCUWEATHER -> "https://developer.accuweather.com/user/login"
|
||||||
|
Constants.WeatherProvider.WEATHER_GOV -> "http://www.weather.gov/"
|
||||||
|
Constants.WeatherProvider.YR -> "https://www.yr.no/"
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isKeyRequired(provider: Constants.WeatherProvider? = Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!): Boolean = when (provider) {
|
||||||
|
Constants.WeatherProvider.OPEN_WEATHER,
|
||||||
|
Constants.WeatherProvider.WEATHER_BIT,
|
||||||
|
Constants.WeatherProvider.WEATHER_API,
|
||||||
|
Constants.WeatherProvider.HERE,
|
||||||
|
Constants.WeatherProvider.ACCUWEATHER -> true
|
||||||
|
|
||||||
|
Constants.WeatherProvider.WEATHER_GOV,
|
||||||
|
Constants.WeatherProvider.YR -> false
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getApiKey(provider: Constants.WeatherProvider? = Constants.WeatherProvider.fromInt(Preferences.weatherProvider)!!): String = when (provider) {
|
||||||
|
Constants.WeatherProvider.OPEN_WEATHER -> Preferences.weatherProviderApiOpen
|
||||||
|
Constants.WeatherProvider.WEATHER_BIT -> Preferences.weatherProviderApiWeatherBit
|
||||||
|
Constants.WeatherProvider.WEATHER_API -> Preferences.weatherProviderApiWeatherApi
|
||||||
|
Constants.WeatherProvider.HERE -> Preferences.weatherProviderApiHere
|
||||||
|
Constants.WeatherProvider.ACCUWEATHER -> Preferences.weatherProviderApiAccuweather
|
||||||
|
Constants.WeatherProvider.WEATHER_GOV -> ""
|
||||||
|
Constants.WeatherProvider.YR -> ""
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getWeatherIconResource(context: Context, icon: String, style: Int = Preferences.weatherIconPack): Int {
|
||||||
return when (icon) {
|
return when (icon) {
|
||||||
"01d" -> {
|
"01d" -> {
|
||||||
when (style) {
|
when (style) {
|
||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.clear_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.clear_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.clear_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.clear_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.clear_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.clear_day_4
|
||||||
else -> R.drawable.clear_day
|
else -> if (context.isDarkTheme()) R.drawable.clear_day_5 else R.drawable.clear_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"02d" -> {
|
"02d" -> {
|
||||||
@ -61,7 +150,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.partly_cloudy_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.partly_cloudy_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.partly_cloudy_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.partly_cloudy_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.partly_cloudy_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.partly_cloudy_4
|
||||||
else -> R.drawable.partly_cloudy
|
else -> if (context.isDarkTheme()) R.drawable.partly_cloudy_5 else R.drawable.partly_cloudy_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"03d" -> {
|
"03d" -> {
|
||||||
@ -69,7 +158,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.mostly_cloudy_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.mostly_cloudy_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.mostly_cloudy_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.mostly_cloudy_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.mostly_cloudy_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.mostly_cloudy_4
|
||||||
else -> R.drawable.mostly_cloudy
|
else -> if (context.isDarkTheme()) R.drawable.mostly_cloudy_5 else R.drawable.mostly_cloudy_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"04d" -> {
|
"04d" -> {
|
||||||
@ -77,7 +166,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.cloudy_weather_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.cloudy_weather_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.cloudy_weather_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.cloudy_weather_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.cloudy_weather_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.cloudy_weather_4
|
||||||
else -> R.drawable.cloudy_weather
|
else -> if (context.isDarkTheme()) R.drawable.cloudy_weather_5 else R.drawable.cloudy_weather_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"09d" -> {
|
"09d" -> {
|
||||||
@ -85,7 +174,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.storm_weather_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.storm_weather_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.storm_weather_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.storm_weather_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.storm_weather_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.storm_weather_day_4
|
||||||
else -> R.drawable.storm_weather_day
|
else -> if (context.isDarkTheme()) R.drawable.storm_weather_day_5 else R.drawable.storm_weather_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"10d" -> {
|
"10d" -> {
|
||||||
@ -93,7 +182,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.rainy_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.rainy_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rainy_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rainy_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rainy_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rainy_day_4
|
||||||
else -> R.drawable.rainy_day
|
else -> if (context.isDarkTheme()) R.drawable.rainy_day_5 else R.drawable.rainy_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"11d" -> {
|
"11d" -> {
|
||||||
@ -101,7 +190,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.thunder_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.thunder_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.thunder_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.thunder_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.thunder_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.thunder_day_4
|
||||||
else -> R.drawable.thunder_day
|
else -> if (context.isDarkTheme()) R.drawable.thunder_day_5 else R.drawable.thunder_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"13d" -> {
|
"13d" -> {
|
||||||
@ -109,7 +198,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.snow_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.snow_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.snow_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.snow_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.snow_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.snow_day_4
|
||||||
else -> R.drawable.snow_day
|
else -> if (context.isDarkTheme()) R.drawable.snow_day_5 else R.drawable.snow_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"50d" -> {
|
"50d" -> {
|
||||||
@ -117,7 +206,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_day_4
|
||||||
else -> R.drawable.haze_day
|
else -> if (context.isDarkTheme()) R.drawable.haze_day_5 else R.drawable.haze_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"80d" -> {
|
"80d" -> {
|
||||||
@ -125,7 +214,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.windy_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.windy_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.windy_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.windy_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.windy_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.windy_day_4
|
||||||
else -> R.drawable.windy_day
|
else -> if (context.isDarkTheme()) R.drawable.windy_day_5 else R.drawable.windy_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"81d" -> {
|
"81d" -> {
|
||||||
@ -133,7 +222,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.rain_snow_day_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.rain_snow_day_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rain_snow_day_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rain_snow_day_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rain_snow_day_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rain_snow_day_4
|
||||||
else -> R.drawable.rain_snow_day
|
else -> if (context.isDarkTheme()) R.drawable.rain_snow_day_5 else R.drawable.rain_snow_day_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"82d" -> {
|
"82d" -> {
|
||||||
@ -141,7 +230,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_weather_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_weather_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_weather_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_weather_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_weather_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_weather_4
|
||||||
else -> R.drawable.haze_weather
|
else -> if (context.isDarkTheme()) R.drawable.haze_weather_5 else R.drawable.haze_weather_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +241,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.clear_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.clear_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.clear_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.clear_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.clear_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.clear_night_4
|
||||||
else -> R.drawable.clear_night
|
else -> if (context.isDarkTheme()) R.drawable.clear_night_5 else R.drawable.clear_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"02n" -> {
|
"02n" -> {
|
||||||
@ -160,7 +249,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.partly_cloudy_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.partly_cloudy_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.partly_cloudy_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.partly_cloudy_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.partly_cloudy_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.partly_cloudy_night_4
|
||||||
else -> R.drawable.partly_cloudy_night
|
else -> if (context.isDarkTheme()) R.drawable.partly_cloudy_night_5 else R.drawable.partly_cloudy_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"03n" -> {
|
"03n" -> {
|
||||||
@ -168,7 +257,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.mostly_cloudy_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.mostly_cloudy_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.mostly_cloudy_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.mostly_cloudy_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.mostly_cloudy_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.mostly_cloudy_night_4
|
||||||
else -> R.drawable.mostly_cloudy_night
|
else -> if (context.isDarkTheme()) R.drawable.mostly_cloudy_night_5 else R.drawable.mostly_cloudy_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"04n" -> {
|
"04n" -> {
|
||||||
@ -176,7 +265,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.cloudy_weather_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.cloudy_weather_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.cloudy_weather_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.cloudy_weather_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.cloudy_weather_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.cloudy_weather_4
|
||||||
else -> R.drawable.cloudy_weather
|
else -> if (context.isDarkTheme()) R.drawable.cloudy_weather_5 else R.drawable.cloudy_weather_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"09n" -> {
|
"09n" -> {
|
||||||
@ -184,7 +273,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.storm_weather_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.storm_weather_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.storm_weather_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.storm_weather_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.storm_weather_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.storm_weather_night_4
|
||||||
else -> R.drawable.storm_weather_night
|
else -> if (context.isDarkTheme()) R.drawable.storm_weather_night_5 else R.drawable.storm_weather_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"10n" -> {
|
"10n" -> {
|
||||||
@ -192,7 +281,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.rainy_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.rainy_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rainy_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rainy_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rainy_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rainy_night_4
|
||||||
else -> R.drawable.rainy_night
|
else -> if (context.isDarkTheme()) R.drawable.rainy_night_5 else R.drawable.rainy_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"11n" -> {
|
"11n" -> {
|
||||||
@ -200,7 +289,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.thunder_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.thunder_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.thunder_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.thunder_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.thunder_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.thunder_night_4
|
||||||
else -> R.drawable.thunder_night
|
else -> if (context.isDarkTheme()) R.drawable.thunder_night_5 else R.drawable.thunder_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"13n" -> {
|
"13n" -> {
|
||||||
@ -208,7 +297,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.snow_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.snow_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.snow_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.snow_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.snow_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.snow_night_4
|
||||||
else -> R.drawable.snow_night
|
else -> if (context.isDarkTheme()) R.drawable.snow_night_5 else R.drawable.snow_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"50n" -> {
|
"50n" -> {
|
||||||
@ -216,7 +305,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_night_4
|
||||||
else -> R.drawable.haze_night
|
else -> if (context.isDarkTheme()) R.drawable.haze_night_5 else R.drawable.haze_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"80n" -> {
|
"80n" -> {
|
||||||
@ -224,7 +313,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.windy_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.windy_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.windy_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.windy_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.windy_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.windy_night_4
|
||||||
else -> R.drawable.windy_night
|
else -> if (context.isDarkTheme()) R.drawable.windy_night_5 else R.drawable.windy_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"81n" -> {
|
"81n" -> {
|
||||||
@ -232,7 +321,7 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.rain_snow_night_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.rain_snow_night_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rain_snow_night_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.rain_snow_night_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rain_snow_night_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.rain_snow_night_4
|
||||||
else -> R.drawable.rain_snow_night
|
else -> if (context.isDarkTheme()) R.drawable.rain_snow_night_5 else R.drawable.rain_snow_night_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"82n" -> {
|
"82n" -> {
|
||||||
@ -240,12 +329,183 @@ object WeatherHelper {
|
|||||||
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_weather_3
|
Constants.WeatherIconPack.COOL.value -> R.drawable.haze_weather_3
|
||||||
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_weather_2
|
Constants.WeatherIconPack.MINIMAL.value -> R.drawable.haze_weather_2
|
||||||
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_weather_4
|
Constants.WeatherIconPack.GOOGLE_NEWS.value -> R.drawable.haze_weather_4
|
||||||
else -> R.drawable.haze_weather
|
else -> if (context.isDarkTheme()) R.drawable.haze_weather_5 else R.drawable.haze_weather_5_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
return R.drawable.unknown
|
return if (context.isDarkTheme()) R.drawable.unknown_dark else R.drawable.unknown_light
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getWeatherGovIcon(iconString: String, isDaytime: Boolean): String = when {
|
||||||
|
iconString.contains("skc") -> "01"
|
||||||
|
iconString.contains("few") -> "02"
|
||||||
|
iconString.contains("sct") -> "03"
|
||||||
|
iconString.contains("bkn") -> "04"
|
||||||
|
iconString.contains("ovc") -> "04"
|
||||||
|
iconString.contains("wind_skc") -> "01"
|
||||||
|
iconString.contains("wind_few") -> "02"
|
||||||
|
iconString.contains("wind_sct") -> "03"
|
||||||
|
iconString.contains("wind_bkn") -> "04"
|
||||||
|
iconString.contains("wind_ovc") -> "04"
|
||||||
|
iconString.contains("snow") -> "13"
|
||||||
|
iconString.contains("rain_snow") -> "81"
|
||||||
|
iconString.contains("rain_sleet") -> "81"
|
||||||
|
iconString.contains("snow_sleet") -> "81"
|
||||||
|
iconString.contains("fzra") -> "81"
|
||||||
|
iconString.contains("rain_fzra") -> "81"
|
||||||
|
iconString.contains("snow_fzra") -> "81"
|
||||||
|
iconString.contains("sleet") -> "81"
|
||||||
|
iconString.contains("rain") -> "10"
|
||||||
|
iconString.contains("rain_showers") -> "10"
|
||||||
|
iconString.contains("rain_showers_hi") -> "10"
|
||||||
|
iconString.contains("tsra") -> "82"
|
||||||
|
iconString.contains("tsra_sct") -> "82"
|
||||||
|
iconString.contains("tsra_hi") -> "82"
|
||||||
|
iconString.contains("tornado") -> "80"
|
||||||
|
iconString.contains("hurricane") -> "80"
|
||||||
|
iconString.contains("tropical_storm") -> "09"
|
||||||
|
iconString.contains("dust") -> "Dust"
|
||||||
|
iconString.contains("smoke") -> "Smoke"
|
||||||
|
iconString.contains("haze") -> "50"
|
||||||
|
iconString.contains("hot") -> "01"
|
||||||
|
iconString.contains("cold") -> "13"
|
||||||
|
iconString.contains("blizzard") -> "80"
|
||||||
|
iconString.contains("fog") -> "82"
|
||||||
|
else -> ""
|
||||||
|
} + if (isDaytime) "d" else "n"
|
||||||
|
|
||||||
|
fun getWeatherBitIcon(iconString: String): String = when {
|
||||||
|
iconString.contains("t01") -> "11"
|
||||||
|
iconString.contains("t02") -> "09"
|
||||||
|
iconString.contains("t03") -> "09"
|
||||||
|
iconString.contains("t04") -> "09"
|
||||||
|
iconString.contains("t05") -> "09"
|
||||||
|
iconString.contains("d01") -> "10"
|
||||||
|
iconString.contains("d02") -> "10"
|
||||||
|
iconString.contains("d03") -> "10"
|
||||||
|
iconString.contains("r01") -> "10"
|
||||||
|
iconString.contains("r02") -> "10"
|
||||||
|
iconString.contains("r03") -> "10"
|
||||||
|
iconString.contains("f01") -> "10"
|
||||||
|
iconString.contains("r04") -> "10"
|
||||||
|
iconString.contains("r05") -> "10"
|
||||||
|
iconString.contains("r06") -> "10"
|
||||||
|
iconString.contains("s01") -> "13"
|
||||||
|
iconString.contains("s02") -> "13"
|
||||||
|
iconString.contains("s03") -> "13"
|
||||||
|
iconString.contains("s04") -> "81"
|
||||||
|
iconString.contains("s05") -> "90"
|
||||||
|
iconString.contains("s06") -> "13"
|
||||||
|
iconString.contains("a01") -> "82"
|
||||||
|
iconString.contains("a02") -> "82"
|
||||||
|
iconString.contains("a03") -> "82"
|
||||||
|
iconString.contains("a04") -> "82"
|
||||||
|
iconString.contains("a05") -> "82"
|
||||||
|
iconString.contains("a06") -> "82"
|
||||||
|
iconString.contains("c01") -> "01"
|
||||||
|
iconString.contains("c02") -> "02"
|
||||||
|
iconString.contains("c03") -> "04"
|
||||||
|
iconString.contains("c04") -> "04"
|
||||||
|
else -> ""
|
||||||
|
} + if (iconString.contains("d")) "d" else "n"
|
||||||
|
|
||||||
|
fun getWeatherApiIcon(icon: Int, isDaytime: Boolean): String = when(icon) {
|
||||||
|
1000 -> "01"
|
||||||
|
1003 -> "02"
|
||||||
|
1006 -> "03"
|
||||||
|
1009 -> "04"
|
||||||
|
1030 -> "82"
|
||||||
|
1063 -> "10"
|
||||||
|
1066 -> "10"
|
||||||
|
1069 -> "10"
|
||||||
|
1072 -> "81"
|
||||||
|
1087 -> "11"
|
||||||
|
1114 -> "13"
|
||||||
|
1117 -> "09"
|
||||||
|
1135 -> "82"
|
||||||
|
1147 -> "82"
|
||||||
|
1150 -> "10"
|
||||||
|
1153 -> "10"
|
||||||
|
1168 -> "10"
|
||||||
|
1171 -> "10"
|
||||||
|
1180 -> "10"
|
||||||
|
1183 -> "10"
|
||||||
|
1186 -> "10"
|
||||||
|
1189 -> "10"
|
||||||
|
1192 -> "10"
|
||||||
|
1195 -> "10"
|
||||||
|
1198 -> "81"
|
||||||
|
1201 -> "81"
|
||||||
|
1204 -> "13"
|
||||||
|
1207 -> "13"
|
||||||
|
1210 -> "13"
|
||||||
|
1213 -> "13"
|
||||||
|
1216 -> "13"
|
||||||
|
1219 -> "13"
|
||||||
|
1222 -> "13"
|
||||||
|
1225 -> "13"
|
||||||
|
1237 -> "13"
|
||||||
|
1240 -> "10"
|
||||||
|
1243 -> "10"
|
||||||
|
1246 -> "10"
|
||||||
|
1249 -> "13"
|
||||||
|
1252 -> "13"
|
||||||
|
1255 -> "13"
|
||||||
|
1258 -> "13"
|
||||||
|
1261 -> "13"
|
||||||
|
1264 -> "13"
|
||||||
|
1273 -> "09"
|
||||||
|
1276 -> "09"
|
||||||
|
1279 -> "13"
|
||||||
|
1282 -> "13"
|
||||||
|
else -> ""
|
||||||
|
} + if (isDaytime) "d" else "n"
|
||||||
|
|
||||||
|
fun getYRIcon(iconCode: String, isDaytime: Boolean): String = when {
|
||||||
|
iconCode.contains("clearsky") -> "01"
|
||||||
|
iconCode.contains("cloudy") -> "04"
|
||||||
|
iconCode.contains("fair") -> "02"
|
||||||
|
iconCode.contains("fog") -> "82"
|
||||||
|
iconCode.contains("heavyrain") -> "10"
|
||||||
|
iconCode.contains("heavyrainandthunder") -> "11"
|
||||||
|
iconCode.contains("heavyrainshowers") -> "10"
|
||||||
|
iconCode.contains("heavyrainshowersandthunder") -> "11"
|
||||||
|
iconCode.contains("heavysleet") -> "10"
|
||||||
|
iconCode.contains("heavysleetandthunder") -> "11"
|
||||||
|
iconCode.contains("heavysleetshowers") -> "10"
|
||||||
|
iconCode.contains("heavysleetshowersandthunder") -> "11"
|
||||||
|
iconCode.contains("heavysnow") -> "13"
|
||||||
|
iconCode.contains("heavysnowandthunder") -> "13"
|
||||||
|
iconCode.contains("heavysnowshowers") -> "13"
|
||||||
|
iconCode.contains("heavysnowshowersandthunder") -> "13"
|
||||||
|
iconCode.contains("lightrain") -> "10"
|
||||||
|
iconCode.contains("lightrainandthunder") -> "11"
|
||||||
|
iconCode.contains("lightrainshowers") -> "10"
|
||||||
|
iconCode.contains("lightrainshowersandthunder") -> "11"
|
||||||
|
iconCode.contains("lightsleet") -> "10"
|
||||||
|
iconCode.contains("lightsleetandthunder") -> "11"
|
||||||
|
iconCode.contains("lightsleetshowers") -> "10"
|
||||||
|
iconCode.contains("lightsnow") -> "13"
|
||||||
|
iconCode.contains("lightsnowandthunder") -> "13"
|
||||||
|
iconCode.contains("lightsnowshowers") -> "13"
|
||||||
|
iconCode.contains("lightssleetshowersandthunder") -> "81"
|
||||||
|
iconCode.contains("lightssnowshowersandthunder") -> "81"
|
||||||
|
iconCode.contains("partlycloudy") -> "03"
|
||||||
|
iconCode.contains("rain") -> "10"
|
||||||
|
iconCode.contains("rainandthunder") -> "11"
|
||||||
|
iconCode.contains("rainshowers") -> "10"
|
||||||
|
iconCode.contains("rainshowersandthunder") -> "11"
|
||||||
|
iconCode.contains("sleet") -> "10"
|
||||||
|
iconCode.contains("sleetandthunder") -> "11"
|
||||||
|
iconCode.contains("sleetshowers") -> "10"
|
||||||
|
iconCode.contains("sleetshowersandthunder") -> "11"
|
||||||
|
iconCode.contains("snow") -> "13"
|
||||||
|
iconCode.contains("snowandthunder") -> "13"
|
||||||
|
iconCode.contains("snowshowers") -> "13"
|
||||||
|
iconCode.contains("snowshowersandthunder") -> "13"
|
||||||
|
else -> ""
|
||||||
|
} + if (isDaytime) "d" else "n"
|
||||||
|
|
||||||
}
|
}
|
@ -3,10 +3,20 @@ package com.tommasoberlose.anotherwidget.helpers
|
|||||||
import android.appwidget.AppWidgetManager
|
import android.appwidget.AppWidgetManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Configuration.ORIENTATION_PORTRAIT
|
import android.content.res.Configuration.ORIENTATION_PORTRAIT
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.HandlerThread
|
||||||
|
import android.os.Looper
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.core.provider.FontRequest
|
||||||
|
import androidx.core.provider.FontsContractCompat
|
||||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
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(
|
||||||
@ -44,4 +54,37 @@ object WidgetHelper {
|
|||||||
width to second * factor
|
width to second * factor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun runWithCustomTypeface(context: Context, function: (typeface: Typeface?) -> Unit) {
|
||||||
|
if (Preferences.customFontFile != "") {
|
||||||
|
val request = FontRequest(
|
||||||
|
"com.google.android.gms.fonts",
|
||||||
|
"com.google.android.gms",
|
||||||
|
Preferences.customFontFile,
|
||||||
|
R.array.com_google_android_gms_fonts_certs
|
||||||
|
)
|
||||||
|
|
||||||
|
val callback = object : FontsContractCompat.FontRequestCallback() {
|
||||||
|
override fun onTypefaceRetrieved(typeface: Typeface) {
|
||||||
|
function.invoke(typeface)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTypefaceRequestFailed(reason: Int) {
|
||||||
|
function.invoke(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val handlerThread = HandlerThread("generateView")
|
||||||
|
handlerThread.start()
|
||||||
|
if (Looper.myLooper() == null) {
|
||||||
|
Looper.prepare()
|
||||||
|
}
|
||||||
|
|
||||||
|
Handler(handlerThread.looper).run {
|
||||||
|
FontsContractCompat.requestFont(context, request, callback, this)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
function.invoke(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -17,7 +17,8 @@ open class Event(
|
|||||||
var calendarID: Int = 0,
|
var calendarID: Int = 0,
|
||||||
var allDay: Boolean = false,
|
var allDay: Boolean = false,
|
||||||
var address: String = "",
|
var address: String = "",
|
||||||
var selfAttendeeStatus: Int = CalendarContract.Attendees.ATTENDEE_STATUS_NONE
|
var selfAttendeeStatus: Int = CalendarContract.Attendees.ATTENDEE_STATUS_NONE,
|
||||||
|
var availability: Int = CalendarContract.EventsEntity.AVAILABILITY_BUSY
|
||||||
) : RealmObject() {
|
) : RealmObject() {
|
||||||
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,20 +1,56 @@
|
|||||||
package com.tommasoberlose.anotherwidget.network
|
package com.tommasoberlose.anotherwidget.network
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
|
import com.google.gson.internal.LinkedTreeMap
|
||||||
|
import com.haroldadmin.cnradapter.NetworkResponse
|
||||||
|
import com.haroldadmin.cnradapter.executeWithRetry
|
||||||
import com.kwabenaberko.openweathermaplib.constants.Units
|
import com.kwabenaberko.openweathermaplib.constants.Units
|
||||||
import com.kwabenaberko.openweathermaplib.implementation.OpenWeatherMapHelper
|
import com.kwabenaberko.openweathermaplib.implementation.OpenWeatherMapHelper
|
||||||
import com.kwabenaberko.openweathermaplib.implementation.callbacks.CurrentWeatherCallback
|
import com.kwabenaberko.openweathermaplib.implementation.callbacks.CurrentWeatherCallback
|
||||||
import com.kwabenaberko.openweathermaplib.models.currentweather.CurrentWeather
|
import com.kwabenaberko.openweathermaplib.models.currentweather.CurrentWeather
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
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.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 org.greenrobot.eventbus.EventBus
|
||||||
|
import java.lang.Exception
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class WeatherNetworkApi(val context: Context) {
|
class WeatherNetworkApi(val context: Context) {
|
||||||
fun updateWeather() {
|
suspend fun updateWeather() {
|
||||||
if (Preferences.showWeather && Preferences.weatherProviderApi != "" && Preferences.customLocationLat != "" && Preferences.customLocationLon != "") {
|
Preferences.weatherProviderError = "-"
|
||||||
val helper = OpenWeatherMapHelper(Preferences.weatherProviderApi)
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
|
if (Preferences.showWeather && Preferences.customLocationLat != "" && Preferences.customLocationLon != "") {
|
||||||
|
when (Constants.WeatherProvider.fromInt(Preferences.weatherProvider)) {
|
||||||
|
Constants.WeatherProvider.OPEN_WEATHER -> useOpenWeatherMap(context)
|
||||||
|
Constants.WeatherProvider.WEATHER_GOV -> useWeatherGov(context)
|
||||||
|
Constants.WeatherProvider.WEATHER_BIT -> useWeatherBitProvider(context)
|
||||||
|
Constants.WeatherProvider.WEATHER_API -> useWeatherApiProvider(context)
|
||||||
|
Constants.WeatherProvider.HERE -> useHereProvider(context)
|
||||||
|
Constants.WeatherProvider.ACCUWEATHER -> useAccuweatherProvider(context)
|
||||||
|
Constants.WeatherProvider.YR -> useYrProvider(context)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
WeatherHelper.removeWeather(
|
||||||
|
context
|
||||||
|
)
|
||||||
|
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun useOpenWeatherMap(context: Context) {
|
||||||
|
if (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)
|
||||||
helper.getCurrentWeatherByGeoCoordinates(Preferences.customLocationLat.toDouble(), Preferences.customLocationLon.toDouble(), object :
|
helper.getCurrentWeatherByGeoCoordinates(Preferences.customLocationLat.toDouble(), Preferences.customLocationLon.toDouble(), object :
|
||||||
CurrentWeatherCallback {
|
CurrentWeatherCallback {
|
||||||
@ -24,19 +60,383 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
Preferences.weatherIcon = currentWeather.weather[0].icon
|
Preferences.weatherIcon = currentWeather.weather[0].icon
|
||||||
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
Preferences.weatherProviderError = ""
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(throwable: Throwable?) {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
|
WeatherHelper.removeWeather(
|
||||||
|
context
|
||||||
|
)
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(throwable: Throwable?) {
|
private suspend fun useWeatherGov(context: Context) {
|
||||||
|
val repository = WeatherGovRepository()
|
||||||
|
val pointsResponse = executeWithRetry(times = 5) {
|
||||||
|
repository.getGridPoints(
|
||||||
|
Preferences.customLocationLat,
|
||||||
|
Preferences.customLocationLon
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
when (pointsResponse) {
|
||||||
|
is NetworkResponse.Success -> {
|
||||||
|
try {
|
||||||
|
val pp = pointsResponse.body["properties"] as LinkedTreeMap<*, *>
|
||||||
|
val gridId = pp["gridId"] as String
|
||||||
|
val gridX = pp["gridX"] as Double
|
||||||
|
val gridY = pp["gridY"] as Double
|
||||||
|
|
||||||
|
when (val weatherResponse = repository.getWeather(
|
||||||
|
gridId,
|
||||||
|
gridX,
|
||||||
|
gridY,
|
||||||
|
if (Preferences.weatherTempUnit == "F") "us" else "si"
|
||||||
|
)) {
|
||||||
|
is NetworkResponse.Success -> {
|
||||||
|
try {
|
||||||
|
val props =
|
||||||
|
weatherResponse.body["properties"] as LinkedTreeMap<*, *>
|
||||||
|
val periods = props["periods"] as List<*>
|
||||||
|
val now = periods[0] as LinkedTreeMap<*, *>
|
||||||
|
|
||||||
|
val temp = now["temperature"] as Double
|
||||||
|
val fullIcon = now["icon"] as String
|
||||||
|
val isDaytime = now["isDaytime"] as Boolean
|
||||||
|
|
||||||
|
Preferences.weatherTemp = temp.toFloat()
|
||||||
|
Preferences.weatherIcon = WeatherHelper.getWeatherGovIcon(fullIcon, isDaytime)
|
||||||
|
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||||
|
|
||||||
|
Preferences.weatherProviderError = ""
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
} finally {
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 -> {
|
||||||
|
if (pointsResponse.body?.containsKey("status") == true && (pointsResponse.body?.get("status") as Double).toInt() == 404) {
|
||||||
|
Preferences.weatherProviderError = ""
|
||||||
|
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_wrong_location)
|
||||||
} else {
|
} else {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
}
|
||||||
|
|
||||||
WeatherHelper.removeWeather(
|
WeatherHelper.removeWeather(
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_connection)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun useHereProvider(context: Context) {
|
||||||
|
if (Preferences.weatherProviderApiHere != "") {
|
||||||
|
val repository = HereRepository()
|
||||||
|
|
||||||
|
when (val response = repository.getWeather()) {
|
||||||
|
is NetworkResponse.Success -> {
|
||||||
|
try {
|
||||||
|
Log.d("ciao - here", response.body.toString())
|
||||||
|
Preferences.weatherProviderError = ""
|
||||||
|
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 -> {
|
||||||
|
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 {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
|
WeatherHelper.removeWeather(
|
||||||
|
context
|
||||||
|
)
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun useWeatherBitProvider(context: Context) {
|
||||||
|
if (Preferences.weatherProviderApiWeatherBit != "") {
|
||||||
|
val repository = WeatherbitRepository()
|
||||||
|
|
||||||
|
when (val response = repository.getWeather()) {
|
||||||
|
is NetworkResponse.Success -> {
|
||||||
|
try {
|
||||||
|
val data = response.body["data"] as List<LinkedTreeMap<String, Any>>?
|
||||||
|
data?.first()?.let {
|
||||||
|
val temp = it["temp"] as Double
|
||||||
|
val weatherInfo = it["weather"] as LinkedTreeMap<String, Any>
|
||||||
|
val iconCode = weatherInfo["icon"] as String
|
||||||
|
|
||||||
|
Preferences.weatherTemp = temp.toFloat()
|
||||||
|
Preferences.weatherIcon = WeatherHelper.getWeatherBitIcon(iconCode)
|
||||||
|
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
|
||||||
|
Preferences.weatherProviderError = ""
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
} 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 (response.code) {
|
||||||
|
403 -> {
|
||||||
|
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
|
||||||
|
)
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_connection)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
|
WeatherHelper.removeWeather(
|
||||||
|
context
|
||||||
|
)
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun useWeatherApiProvider(context: Context) {
|
||||||
|
if (Preferences.weatherProviderApiWeatherApi != "") {
|
||||||
|
val repository = WeatherApiRepository()
|
||||||
|
|
||||||
|
when (val response = repository.getWeather()) {
|
||||||
|
is NetworkResponse.Success -> {
|
||||||
|
try {
|
||||||
|
val current = response.body["current"] as LinkedTreeMap<String, Any>?
|
||||||
|
current?.let {
|
||||||
|
val tempC = current["temp_c"] as Double
|
||||||
|
val tempF = current["temp_f"] as Double
|
||||||
|
val isDay = current["is_day"] as Double
|
||||||
|
val condition = current["condition"] as LinkedTreeMap<String, Any>
|
||||||
|
val iconCode = condition["code"] as Double
|
||||||
|
|
||||||
|
Preferences.weatherTemp = if (Preferences.weatherTempUnit == "F") tempF.toFloat() else tempC.toFloat()
|
||||||
|
Preferences.weatherIcon = WeatherHelper.getWeatherApiIcon(iconCode.toInt(), isDay.toInt() == 1)
|
||||||
|
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
|
||||||
|
Preferences.weatherProviderError = ""
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
} 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 (response.code) {
|
||||||
|
401 -> {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_invalid_key)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
}
|
||||||
|
403 -> {
|
||||||
|
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 {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
|
WeatherHelper.removeWeather(
|
||||||
|
context
|
||||||
|
)
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun useAccuweatherProvider(context: Context) {
|
||||||
|
if (Preferences.weatherProviderApiAccuweather != "") {
|
||||||
|
val repository = AccuweatherRepository()
|
||||||
|
|
||||||
|
// when (val response = repository.getWeather()) {
|
||||||
|
// is NetworkResponse.Success -> {
|
||||||
|
// try {
|
||||||
|
// 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())
|
||||||
|
// }
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_missing_key)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
|
||||||
|
WeatherHelper.removeWeather(
|
||||||
|
context
|
||||||
|
)
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun useYrProvider(context: Context) {
|
||||||
|
val repository = YrRepository()
|
||||||
|
|
||||||
|
when (val response = repository.getWeather()) {
|
||||||
|
is NetworkResponse.Success -> {
|
||||||
|
try {
|
||||||
|
val pp = response.body["properties"] as LinkedTreeMap<*, *>
|
||||||
|
val data = pp["timeseries"] as List<LinkedTreeMap<String, Any>>?
|
||||||
|
data?.let {
|
||||||
|
val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
|
||||||
|
for (item in data) {
|
||||||
|
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 temp = details["air_temperature"] as Double
|
||||||
|
|
||||||
|
val summary = next["summary"] as LinkedTreeMap<*, *>
|
||||||
|
val iconCode = summary["symbol_code"] as String
|
||||||
|
|
||||||
|
Preferences.weatherTemp = temp.toFloat()
|
||||||
|
Preferences.weatherIcon = WeatherHelper.getYRIcon(iconCode, now.get(Calendar.HOUR_OF_DAY) >= 22 || now.get(Calendar.HOUR_OF_DAY) <= 8)
|
||||||
|
Preferences.weatherTempUnit = "C"
|
||||||
|
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
|
||||||
|
Preferences.weatherProviderError = ""
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} catch(ex: Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.weather_provider_error_generic)
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
} finally {
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is NetworkResponse.ServerError -> {
|
||||||
|
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())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.network.api
|
||||||
|
|
||||||
|
import com.haroldadmin.cnradapter.NetworkResponse
|
||||||
|
import retrofit2.http.*
|
||||||
|
|
||||||
|
object ApiServices {
|
||||||
|
interface WeatherGovApiService {
|
||||||
|
@Headers("User-Agent: (Another Widget, tommaso.berlose@gmail.com)")
|
||||||
|
@GET("points/{latitude},{longitude}")
|
||||||
|
suspend fun getGridPoints(
|
||||||
|
@Path("latitude") latitude: String,
|
||||||
|
@Path("longitude") longitude: String
|
||||||
|
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
||||||
|
|
||||||
|
@Headers("User-Agent: (Another Widget, tommaso.berlose@gmail.com)")
|
||||||
|
@GET("gridpoints/{gridId}/{gridX},{gridY}/forecast")
|
||||||
|
suspend fun getWeather(
|
||||||
|
@Path("gridId") gridId: String,
|
||||||
|
@Path("gridX") gridX: Int,
|
||||||
|
@Path("gridY") gridY: Int,
|
||||||
|
@Query("units") unit: String
|
||||||
|
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WeatherBitService {
|
||||||
|
@GET("current")
|
||||||
|
suspend fun getWeather(
|
||||||
|
@Query("key") key: String,
|
||||||
|
@Query("lat") lat: String,
|
||||||
|
@Query("lon") lon: String,
|
||||||
|
@Query("units") units: String,
|
||||||
|
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface WeatherApiService {
|
||||||
|
@Headers("Accept: application/json")
|
||||||
|
@GET("current.json")
|
||||||
|
suspend fun getWeather(
|
||||||
|
@Query("key") key: String,
|
||||||
|
@Query("q") location: String,
|
||||||
|
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HereService {
|
||||||
|
@GET("report.json")
|
||||||
|
suspend fun getWeather(
|
||||||
|
@Query("apiKey") apiKey: String,
|
||||||
|
@Query("latitude") latitude: String,
|
||||||
|
@Query("longitude") longitude: String,
|
||||||
|
@Query("product") product: String,
|
||||||
|
@Query("oneobservation") oneobservation: Boolean,
|
||||||
|
@Query("metric") metric: Boolean,
|
||||||
|
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AccuweatherService {
|
||||||
|
@GET("")
|
||||||
|
suspend fun getWeather(
|
||||||
|
@Path("gridId") gridId: String,
|
||||||
|
@Path("gridX") gridX: Int,
|
||||||
|
@Path("gridY") gridY: Int,
|
||||||
|
@Query("units") unit: String
|
||||||
|
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface YrService {
|
||||||
|
@Headers("User-Agent: AnotherWidget")
|
||||||
|
@GET("compact.json")
|
||||||
|
suspend fun getWeather(
|
||||||
|
@Query("lat") lat: String,
|
||||||
|
@Query("lon") lon: String,
|
||||||
|
): NetworkResponse<HashMap<String, Any>, HashMap<String, Any>>
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
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 AccuweatherRepository {
|
||||||
|
|
||||||
|
/* ACCUWEATHER */
|
||||||
|
private val apiServiceAccu: ApiServices.AccuweatherService = getRetrofit().create(ApiServices.AccuweatherService::class.java)
|
||||||
|
suspend fun getWeather(): Nothing = TODO()
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val BASE_URL_ACCU = ""
|
||||||
|
|
||||||
|
private fun getRetrofit(): Retrofit {
|
||||||
|
return Retrofit.Builder()
|
||||||
|
.baseUrl(BASE_URL_ACCU)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.addCallAdapterFactory(NetworkResponseAdapterFactory())
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.network.repository
|
||||||
|
|
||||||
|
import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.network.api.ApiServices
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
|
class HereRepository {
|
||||||
|
|
||||||
|
/* HERE */
|
||||||
|
private val apiServiceHere: ApiServices.HereService = getRetrofit().create(ApiServices.HereService::class.java)
|
||||||
|
suspend fun getWeather() = apiServiceHere.getWeather(Preferences.weatherProviderApiHere, Preferences.customLocationLat, Preferences.customLocationLon, "observation", true, Preferences.weatherTempUnit != "F")
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val BASE_URL_HERE = "https://weather.ls.hereapi.com/weather/1.0/"
|
||||||
|
|
||||||
|
private fun getRetrofit(): Retrofit {
|
||||||
|
return Retrofit.Builder()
|
||||||
|
.baseUrl(BASE_URL_HERE)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.addCallAdapterFactory(NetworkResponseAdapterFactory())
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.network.repository
|
||||||
|
|
||||||
|
import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.network.api.ApiServices
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
|
class WeatherApiRepository {
|
||||||
|
|
||||||
|
/* WEATHER API*/
|
||||||
|
private val apiServiceApi: ApiServices.WeatherApiService = getRetrofit().create(ApiServices.WeatherApiService::class.java)
|
||||||
|
suspend fun getWeather() = apiServiceApi.getWeather(Preferences.weatherProviderApiWeatherApi, "${Preferences.customLocationLat},${Preferences.customLocationLon}")
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val BASE_URL_API = "http://api.weatherapi.com/v1/"
|
||||||
|
|
||||||
|
private fun getRetrofit(): Retrofit {
|
||||||
|
return Retrofit.Builder()
|
||||||
|
.baseUrl(BASE_URL_API)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.addCallAdapterFactory(NetworkResponseAdapterFactory())
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
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 WeatherGovRepository {
|
||||||
|
|
||||||
|
/* WEATHER GOV*/
|
||||||
|
private val apiServiceGov: ApiServices.WeatherGovApiService = getRetrofit().create(ApiServices.WeatherGovApiService::class.java)
|
||||||
|
suspend fun getGridPoints(latitude: String, longitude: String) = apiServiceGov.getGridPoints(latitude, longitude)
|
||||||
|
suspend fun getWeather(gridId: String, gridX: Double, gridY: Double, unit: String) = apiServiceGov.getWeather(gridId, gridX.toInt(), gridY.toInt(), unit)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val BASE_URL_GOV = "https://api.weather.gov/"
|
||||||
|
|
||||||
|
private fun getRetrofit(): Retrofit {
|
||||||
|
return Retrofit.Builder()
|
||||||
|
.baseUrl(BASE_URL_GOV)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.addCallAdapterFactory(NetworkResponseAdapterFactory())
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.network.repository
|
||||||
|
|
||||||
|
import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.network.api.ApiServices
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
|
class WeatherbitRepository {
|
||||||
|
|
||||||
|
/* BIT */
|
||||||
|
private val apiServiceBit: ApiServices.WeatherBitService = getRetrofit().create(ApiServices.WeatherBitService::class.java)
|
||||||
|
suspend fun getWeather() = apiServiceBit.getWeather(Preferences.weatherProviderApiWeatherBit, Preferences.customLocationLat, Preferences.customLocationLon, if (Preferences.weatherTempUnit == "F") "I" else "M")
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val BASE_URL_BIT = "https://api.weatherbit.io/v2.0/"
|
||||||
|
|
||||||
|
private fun getRetrofit(): Retrofit {
|
||||||
|
return Retrofit.Builder()
|
||||||
|
.baseUrl(BASE_URL_BIT)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.addCallAdapterFactory(NetworkResponseAdapterFactory())
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.network.repository
|
||||||
|
|
||||||
|
import com.haroldadmin.cnradapter.NetworkResponseAdapterFactory
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.network.api.ApiServices
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
|
||||||
|
class YrRepository {
|
||||||
|
|
||||||
|
/* YR */
|
||||||
|
private val apiServiceYr: ApiServices.YrService = getRetrofit().create(ApiServices.YrService::class.java)
|
||||||
|
suspend fun getWeather() = apiServiceYr.getWeather(Preferences.customLocationLat, Preferences.customLocationLon)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val BASE_URL_YR = "https://api.met.no/weatherapi/locationforecast/2.0/"
|
||||||
|
|
||||||
|
private fun getRetrofit(): Retrofit {
|
||||||
|
return Retrofit.Builder()
|
||||||
|
.baseUrl(BASE_URL_YR)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.addCallAdapterFactory(NetworkResponseAdapterFactory())
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,8 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.Log
|
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.GoogleSignIn
|
||||||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
||||||
import com.google.android.gms.fitness.Fitness
|
import com.google.android.gms.fitness.Fitness
|
||||||
@ -35,16 +37,19 @@ class ActivityDetectionReceiver : BroadcastReceiver() {
|
|||||||
}
|
}
|
||||||
} else {
|
} 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)) {
|
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()
|
resetDailySteps(context)
|
||||||
registerFence(context)
|
registerFence(context)
|
||||||
} else {
|
} else {
|
||||||
resetDailySteps()
|
resetDailySteps(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetDailySteps() {
|
private fun resetDailySteps(context: Context) {
|
||||||
Preferences.googleFitSteps = -1
|
Kotpref.init(context)
|
||||||
|
Preferences.blockingBulk {
|
||||||
|
remove(Preferences::googleFitSteps)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -54,6 +59,7 @@ class ActivityDetectionReceiver : BroadcastReceiver() {
|
|||||||
.build()
|
.build()
|
||||||
|
|
||||||
fun registerFence(context: Context) {
|
fun registerFence(context: Context) {
|
||||||
|
Kotpref.init(context)
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || context.checkGrantedPermission(
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || context.checkGrantedPermission(
|
||||||
Manifest.permission.ACTIVITY_RECOGNITION)) {
|
Manifest.permission.ACTIVITY_RECOGNITION)) {
|
||||||
val transitions = mutableListOf<ActivityTransition>()
|
val transitions = mutableListOf<ActivityTransition>()
|
||||||
@ -116,6 +122,7 @@ class ActivityDetectionReceiver : BroadcastReceiver() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun requestDailySteps(context: Context) {
|
fun requestDailySteps(context: Context) {
|
||||||
|
Kotpref.init(context)
|
||||||
|
|
||||||
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
|
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
|
||||||
if (account != null && GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
|
if (account != null && GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
|
||||||
@ -160,7 +167,7 @@ class ActivityDetectionReceiver : BroadcastReceiver() {
|
|||||||
private fun setTimeout(context: Context) {
|
private fun setTimeout(context: Context) {
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
cancel(PendingIntent.getBroadcast(context, 5, Intent(context, ActivityDetectionReceiver::class.java), 0))
|
cancel(PendingIntent.getBroadcast(context, 5, Intent(context, ActivityDetectionReceiver::class.java), 0))
|
||||||
setExactAndAllowWhileIdle(
|
setExact(
|
||||||
AlarmManager.RTC,
|
AlarmManager.RTC,
|
||||||
Calendar.getInstance().timeInMillis + 5 * 60 * 1000,
|
Calendar.getInstance().timeInMillis + 5 * 60 * 1000,
|
||||||
PendingIntent.getBroadcast(
|
PendingIntent.getBroadcast(
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.receivers
|
|
||||||
|
|
||||||
import android.app.Notification
|
|
||||||
import android.media.MediaMetadata
|
|
||||||
import android.media.session.MediaController
|
|
||||||
import android.media.session.MediaSession
|
|
||||||
import android.media.session.PlaybackState
|
|
||||||
import android.service.notification.NotificationListenerService
|
|
||||||
import android.service.notification.StatusBarNotification
|
|
||||||
import android.util.Log
|
|
||||||
import com.chibatching.kotpref.bulk
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.WidgetHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
|
||||||
|
|
||||||
|
|
||||||
class MusicNotificationListener : NotificationListenerService() {
|
|
||||||
override fun onListenerConnected() {
|
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
|
||||||
super.onListenerConnected()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNotificationPosted(sbn: StatusBarNotification?) {
|
|
||||||
sbn?.notification?.extras?.let { bundle ->
|
|
||||||
bundle.getParcelable<MediaSession.Token>(Notification.EXTRA_MEDIA_SESSION)?.let {
|
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.onNotificationPosted(sbn)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNotificationRemoved(sbn: StatusBarNotification?) {
|
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
|
||||||
super.onNotificationRemoved(sbn)
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,104 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.receivers
|
||||||
|
|
||||||
|
import android.app.*
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.media.session.MediaSession
|
||||||
|
import android.os.Build
|
||||||
|
import android.service.notification.NotificationListenerService
|
||||||
|
import android.service.notification.StatusBarNotification
|
||||||
|
import android.util.Log
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Actions
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
import java.lang.Exception
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationListener : NotificationListenerService() {
|
||||||
|
override fun onListenerConnected() {
|
||||||
|
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
||||||
|
MainWidget.updateWidget(this)
|
||||||
|
super.onListenerConnected()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNotificationPosted(sbn: StatusBarNotification?) {
|
||||||
|
sbn?.notification?.extras?.let { bundle ->
|
||||||
|
bundle.getParcelable<MediaSession.Token>(Notification.EXTRA_MEDIA_SESSION)?.let {
|
||||||
|
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
||||||
|
} ?: run {
|
||||||
|
val isGroupHeader = sbn.notification.flags and Notification.FLAG_GROUP_SUMMARY != 0
|
||||||
|
val isOngoing = sbn.notification.flags and Notification.FLAG_ONGOING_EVENT != 0
|
||||||
|
|
||||||
|
if (bundle.containsKey(Notification.EXTRA_TITLE) && !isGroupHeader && !isOngoing && ActiveNotificationsHelper.isAppAccepted(sbn.packageName)) {
|
||||||
|
Preferences.lastNotificationId = sbn.id
|
||||||
|
Preferences.lastNotificationTitle = bundle.getString(Notification.EXTRA_TITLE) ?: ""
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
|
try {
|
||||||
|
Preferences.lastNotificationIcon = sbn.notification.smallIcon.resId
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Preferences.lastNotificationIcon = 0
|
||||||
|
}
|
||||||
|
Preferences.lastNotificationPackage = sbn.notification.smallIcon.resPackage
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
Preferences.lastNotificationIcon = sbn.notification.icon
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
Preferences.lastNotificationIcon = 0
|
||||||
|
}
|
||||||
|
Preferences.lastNotificationPackage = sbn.packageName
|
||||||
|
}
|
||||||
|
MainWidget.updateWidget(this)
|
||||||
|
setTimeout(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onNotificationPosted(sbn)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNotificationRemoved(sbn: StatusBarNotification?) {
|
||||||
|
MediaPlayerHelper.updatePlayingMediaInfo(this)
|
||||||
|
|
||||||
|
sbn?.let {
|
||||||
|
if (sbn.id == Preferences.lastNotificationId && sbn.packageName == Preferences.lastNotificationPackage) {
|
||||||
|
ActiveNotificationsHelper.clearLastNotification(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWidget.updateWidget(this)
|
||||||
|
super.onNotificationRemoved(sbn)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setTimeout(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, 28943, intent, 0))
|
||||||
|
val timeoutPref = Constants.GlanceNotificationTimer.fromInt(Preferences.hideNotificationAfter)
|
||||||
|
if (timeoutPref != Constants.GlanceNotificationTimer.WHEN_DISMISSED) {
|
||||||
|
setExact(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
Calendar.getInstance().timeInMillis + when (timeoutPref) {
|
||||||
|
Constants.GlanceNotificationTimer.HALF_MINUTE -> 30 * 1000
|
||||||
|
Constants.GlanceNotificationTimer.ONE_MINUTE -> 60 * 1000
|
||||||
|
Constants.GlanceNotificationTimer.FIVE_MINUTES -> 5 * 60 * 1000
|
||||||
|
Constants.GlanceNotificationTimer.TEN_MINUTES -> 10 * 60 * 1000
|
||||||
|
Constants.GlanceNotificationTimer.FIFTEEN_MINUTES -> 15 * 60 * 1000
|
||||||
|
else -> 0
|
||||||
|
},
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
5,
|
||||||
|
intent,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,8 +12,10 @@ 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.ActiveNotificationsHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.BatteryHelper
|
import com.tommasoberlose.anotherwidget.helpers.BatteryHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
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 org.joda.time.Period
|
import org.joda.time.Period
|
||||||
@ -32,16 +34,27 @@ class UpdatesReceiver : BroadcastReceiver() {
|
|||||||
Intent.ACTION_DATE_CHANGED,
|
Intent.ACTION_DATE_CHANGED,
|
||||||
Actions.ACTION_CALENDAR_UPDATE -> {
|
Actions.ACTION_CALENDAR_UPDATE -> {
|
||||||
CalendarHelper.updateEventList(context)
|
CalendarHelper.updateEventList(context)
|
||||||
|
ActiveNotificationsHelper.clearLastNotification(context)
|
||||||
|
MediaPlayerHelper.updatePlayingMediaInfo(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
|
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
|
||||||
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
|
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)) {
|
||||||
setUpdates(context, intent.getLongExtra(EVENT_ID, -1))
|
setUpdates(context, intent.getLongExtra(EVENT_ID, -1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Actions.ACTION_CLEAR_NOTIFICATION -> {
|
||||||
|
ActiveNotificationsHelper.clearLastNotification(context)
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
}
|
||||||
|
Actions.ACTION_UPDATE_GREETINGS -> {
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,10 +5,12 @@ 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 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 kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
@ -23,17 +25,19 @@ class WeatherReceiver : BroadcastReceiver() {
|
|||||||
Intent.ACTION_TIME_CHANGED -> setUpdates(context)
|
Intent.ACTION_TIME_CHANGED -> setUpdates(context)
|
||||||
|
|
||||||
Actions.ACTION_WEATHER_UPDATE -> {
|
Actions.ACTION_WEATHER_UPDATE -> {
|
||||||
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
WeatherHelper.updateWeather(context)
|
WeatherHelper.updateWeather(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val MINUTE = 60 * 1000L
|
private const val MINUTE = 60 * 1000L
|
||||||
fun setUpdates(context: Context) {
|
fun setUpdates(context: Context) {
|
||||||
removeUpdates(context)
|
removeUpdates(context)
|
||||||
|
|
||||||
if (Preferences.showWeather && Preferences.weatherProviderApi != "") {
|
if (Preferences.showWeather) {
|
||||||
val interval = MINUTE * when (Preferences.weatherRefreshPeriod) {
|
val interval = MINUTE * when (Preferences.weatherRefreshPeriod) {
|
||||||
0 -> 30
|
0 -> 30
|
||||||
1 -> 60
|
1 -> 60
|
||||||
@ -55,7 +59,7 @@ class WeatherReceiver : BroadcastReceiver() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun setOneTimeUpdate(context: Context) {
|
fun setOneTimeUpdate(context: Context) {
|
||||||
if (Preferences.showWeather && Preferences.weatherProviderApi != "") {
|
if (Preferences.showWeather) {
|
||||||
listOf(10, 20, 30).forEach {
|
listOf(10, 20, 30).forEach {
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
setExactAndAllowWhileIdle(
|
setExactAndAllowWhileIdle(
|
||||||
|
@ -52,7 +52,7 @@ class BatteryListenerJob : JobService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun remove(context: Context) {
|
private fun remove(context: Context) {
|
||||||
val js = context.getSystemService(JobScheduler::class.java)
|
val js = context.getSystemService(JobScheduler::class.java)
|
||||||
js?.cancel(chargingJobId)
|
js?.cancel(chargingJobId)
|
||||||
js?.cancel(notChargingJobId)
|
js?.cancel(notChargingJobId)
|
||||||
|
@ -3,11 +3,14 @@ package com.tommasoberlose.anotherwidget.services
|
|||||||
import android.Manifest
|
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.util.Log
|
import android.util.Log
|
||||||
import androidx.core.app.JobIntentService
|
import androidx.core.app.JobIntentService
|
||||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||||
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.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.fragments.MainFragment
|
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||||
@ -22,7 +25,7 @@ import kotlin.collections.ArrayList
|
|||||||
class UpdateCalendarJob : JobIntentService() {
|
class UpdateCalendarJob : JobIntentService() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val jobId = 1200
|
private const val jobId = 1200
|
||||||
|
|
||||||
fun enqueueWork(context: Context, work: Intent) {
|
fun enqueueWork(context: Context, work: Intent) {
|
||||||
enqueueWork(context, UpdateCalendarJob::class.java, jobId, work)
|
enqueueWork(context, UpdateCalendarJob::class.java, jobId, work)
|
||||||
@ -42,8 +45,17 @@ class UpdateCalendarJob : JobIntentService() {
|
|||||||
set(Calendar.HOUR_OF_DAY, 0)
|
set(Calendar.HOUR_OF_DAY, 0)
|
||||||
}
|
}
|
||||||
val limit = Calendar.getInstance().apply {
|
val limit = Calendar.getInstance().apply {
|
||||||
timeInMillis = begin.timeInMillis
|
when (Preferences.showUntil) {
|
||||||
add(Calendar.DAY_OF_YEAR, 2)
|
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(
|
if (!checkGrantedPermission(
|
||||||
@ -83,7 +95,8 @@ class UpdateCalendarJob : JobIntentService() {
|
|||||||
calendarID = e.calendarId.toInt(),
|
calendarID = e.calendarId.toInt(),
|
||||||
allDay = e.allDay,
|
allDay = e.allDay,
|
||||||
address = e.eventLocation ?: "",
|
address = e.eventLocation ?: "",
|
||||||
selfAttendeeStatus = e.selfAttendeeStatus.toInt()
|
selfAttendeeStatus = e.selfAttendeeStatus.toInt(),
|
||||||
|
availability = e.availability
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -92,28 +105,18 @@ class UpdateCalendarJob : JobIntentService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eventList.isEmpty()) {
|
val sortedEvents = eventList.sortEvents()
|
||||||
|
val filteredEventList = sortedEvents
|
||||||
|
.applyFilters()
|
||||||
|
|
||||||
|
if (filteredEventList.isEmpty()) {
|
||||||
eventRepository.resetNextEventData()
|
eventRepository.resetNextEventData()
|
||||||
eventRepository.clearEvents()
|
eventRepository.clearEvents()
|
||||||
} else {
|
} else {
|
||||||
eventList.sortWith(Comparator { event: Event, event1: Event ->
|
|
||||||
if (event.allDay && event1.allDay) {
|
|
||||||
event.startDate.compareTo(event1.startDate)
|
|
||||||
} else if (event.allDay) {
|
|
||||||
1
|
|
||||||
} else if (event1.allDay) {
|
|
||||||
-1
|
|
||||||
} else {
|
|
||||||
event1.startDate.compareTo(event.startDate)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
eventList.reverse()
|
|
||||||
eventRepository.saveEvents(
|
eventRepository.saveEvents(
|
||||||
eventList
|
sortedEvents
|
||||||
)
|
|
||||||
eventRepository.saveNextEventData(
|
|
||||||
eventList[0]
|
|
||||||
)
|
)
|
||||||
|
eventRepository.saveNextEventData(filteredEventList.first())
|
||||||
}
|
}
|
||||||
} catch (ignored: java.lang.Exception) {
|
} catch (ignored: java.lang.Exception) {
|
||||||
|
|
||||||
|
@ -0,0 +1,143 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.activities
|
||||||
|
|
||||||
|
import android.content.pm.ResolveInfo
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.databinding.DataBindingUtil
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.databinding.ActivityAppNotificationsFilterBinding
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.AppNotificationsViewModel
|
||||||
|
import kotlinx.android.synthetic.main.activity_app_notifications_filter.*
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
|
|
||||||
|
|
||||||
|
class AppNotificationsFilterActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private lateinit var adapter: SlimAdapter
|
||||||
|
private lateinit var viewModel: AppNotificationsViewModel
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
viewModel = ViewModelProvider(this).get(AppNotificationsViewModel::class.java)
|
||||||
|
val binding = DataBindingUtil.setContentView<ActivityAppNotificationsFilterBinding>(this, R.layout.activity_app_notifications_filter)
|
||||||
|
|
||||||
|
list_view.setHasFixedSize(true)
|
||||||
|
val mLayoutManager = LinearLayoutManager(this)
|
||||||
|
list_view.layoutManager = mLayoutManager
|
||||||
|
|
||||||
|
adapter = SlimAdapter.create()
|
||||||
|
adapter
|
||||||
|
.register<ResolveInfo>(R.layout.application_info_layout) { item, injector ->
|
||||||
|
injector
|
||||||
|
.text(R.id.text, item.loadLabel(viewModel.pm))
|
||||||
|
.with<ImageView>(R.id.icon) {
|
||||||
|
Glide
|
||||||
|
.with(this)
|
||||||
|
.load(item.loadIcon(viewModel.pm))
|
||||||
|
.centerCrop()
|
||||||
|
.into(it)
|
||||||
|
}
|
||||||
|
.visible(R.id.checkBox)
|
||||||
|
.clicked(R.id.item) {
|
||||||
|
toggleApp(item)
|
||||||
|
adapter.notifyItemRangeChanged(0, adapter.data.size)
|
||||||
|
}
|
||||||
|
.clicked(R.id.checkBox) {
|
||||||
|
toggleApp(item)
|
||||||
|
adapter.notifyItemRangeChanged(0, adapter.data.size)
|
||||||
|
}
|
||||||
|
.checked(R.id.checkBox, ActiveNotificationsHelper.isAppAccepted(item.activityInfo.packageName))
|
||||||
|
}
|
||||||
|
.attachTo(list_view)
|
||||||
|
|
||||||
|
setupListener()
|
||||||
|
subscribeUi(binding, viewModel)
|
||||||
|
|
||||||
|
search.requestFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var filterJob: Job? = null
|
||||||
|
|
||||||
|
private fun subscribeUi(binding: ActivityAppNotificationsFilterBinding, viewModel: AppNotificationsViewModel) {
|
||||||
|
binding.viewModel = viewModel
|
||||||
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
|
viewModel.appList.observe(this, Observer {
|
||||||
|
updateList(list = it)
|
||||||
|
loader.visibility = View.INVISIBLE
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.searchInput.observe(this, Observer { search ->
|
||||||
|
updateList(search = search)
|
||||||
|
clear_search.isVisible = search.isNotBlank()
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.appNotificationsFilter.observe(this, {
|
||||||
|
updateList()
|
||||||
|
clear_selection.isVisible = Preferences.appNotificationsFilter != ""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateList(list: List<ResolveInfo>? = viewModel.appList.value, search: String? = viewModel.searchInput.value) {
|
||||||
|
loader.visibility = View.VISIBLE
|
||||||
|
filterJob?.cancel()
|
||||||
|
filterJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
if (list != null && list.isNotEmpty()) {
|
||||||
|
delay(200)
|
||||||
|
val filteredList: List<ResolveInfo> = if (search == null || search == "") {
|
||||||
|
list
|
||||||
|
} else {
|
||||||
|
list.filter {
|
||||||
|
it.loadLabel(viewModel.pm).contains(search, true)
|
||||||
|
}
|
||||||
|
}.sortedWith { app1, app2 ->
|
||||||
|
if (ActiveNotificationsHelper.isAppAccepted(app1.activityInfo.packageName) && ActiveNotificationsHelper.isAppAccepted(app2.activityInfo.packageName)) {
|
||||||
|
app1.loadLabel(viewModel.pm).toString().compareTo(app2.loadLabel(viewModel.pm).toString(), ignoreCase = true)
|
||||||
|
} else if (ActiveNotificationsHelper.isAppAccepted(app1.activityInfo.packageName)) {
|
||||||
|
-1
|
||||||
|
} else if (ActiveNotificationsHelper.isAppAccepted(app2.activityInfo.packageName)) {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
app1.loadLabel(viewModel.pm).toString().compareTo(app2.loadLabel(viewModel.pm).toString(), ignoreCase = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
adapter.updateData(filteredList)
|
||||||
|
loader.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupListener() {
|
||||||
|
action_back.setOnClickListener {
|
||||||
|
onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_search.setOnClickListener {
|
||||||
|
viewModel.searchInput.value = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_selection.setOnClickListener {
|
||||||
|
Preferences.appNotificationsFilter = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toggleApp(app: ResolveInfo) {
|
||||||
|
ActiveNotificationsHelper.toggleAppFilter(app.activityInfo.packageName)
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ import android.view.View
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
@ -21,9 +22,15 @@ import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBin
|
|||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.ChooseApplicationViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.ChooseApplicationViewModel
|
||||||
import kotlinx.android.synthetic.main.activity_choose_application.*
|
import kotlinx.android.synthetic.main.activity_choose_application.*
|
||||||
|
import kotlinx.android.synthetic.main.activity_choose_application.action_back
|
||||||
|
import kotlinx.android.synthetic.main.activity_choose_application.clear_search
|
||||||
import kotlinx.android.synthetic.main.activity_choose_application.list_view
|
import kotlinx.android.synthetic.main.activity_choose_application.list_view
|
||||||
|
import kotlinx.android.synthetic.main.activity_choose_application.loader
|
||||||
|
import kotlinx.android.synthetic.main.activity_choose_application.search
|
||||||
|
import kotlinx.android.synthetic.main.activity_music_players_filter.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import net.idik.lib.slimadapter.SlimAdapter
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
|
import net.idik.lib.slimadapter.SlimAdapterEx
|
||||||
|
|
||||||
|
|
||||||
class ChooseApplicationActivity : AppCompatActivity() {
|
class ChooseApplicationActivity : AppCompatActivity() {
|
||||||
@ -41,7 +48,7 @@ class ChooseApplicationActivity : AppCompatActivity() {
|
|||||||
val mLayoutManager = LinearLayoutManager(this)
|
val mLayoutManager = LinearLayoutManager(this)
|
||||||
list_view.layoutManager = mLayoutManager
|
list_view.layoutManager = mLayoutManager
|
||||||
|
|
||||||
adapter = SlimAdapter.create()
|
adapter = SlimAdapterEx.create()
|
||||||
adapter
|
adapter
|
||||||
.register<String>(R.layout.application_info_layout) { _, injector ->
|
.register<String>(R.layout.application_info_layout) { _, injector ->
|
||||||
injector
|
injector
|
||||||
@ -87,6 +94,7 @@ class ChooseApplicationActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun subscribeUi(binding: ActivityChooseApplicationBinding, viewModel: ChooseApplicationViewModel) {
|
private fun subscribeUi(binding: ActivityChooseApplicationBinding, viewModel: ChooseApplicationViewModel) {
|
||||||
binding.viewModel = viewModel
|
binding.viewModel = viewModel
|
||||||
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
viewModel.appList.observe(this, Observer {
|
viewModel.appList.observe(this, Observer {
|
||||||
updateList(list = it)
|
updateList(list = it)
|
||||||
@ -95,6 +103,7 @@ class ChooseApplicationActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
viewModel.searchInput.observe(this, Observer { search ->
|
viewModel.searchInput.observe(this, Observer { search ->
|
||||||
updateList(search = search)
|
updateList(search = search)
|
||||||
|
clear_search.isVisible = search.isNotBlank()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,6 +132,10 @@ class ChooseApplicationActivity : AppCompatActivity() {
|
|||||||
action_back.setOnClickListener {
|
action_back.setOnClickListener {
|
||||||
onBackPressed()
|
onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear_search.setOnClickListener {
|
||||||
|
viewModel.searchInput.value = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveApp(app: ResolveInfo) {
|
private fun saveApp(app: ResolveInfo) {
|
||||||
|
@ -6,12 +6,14 @@ import android.os.Bundle
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.chibatching.kotpref.blockingBulk
|
||||||
import com.chibatching.kotpref.bulk
|
import com.chibatching.kotpref.bulk
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.databinding.ActivityCustomDateBinding
|
import com.tommasoberlose.anotherwidget.databinding.ActivityCustomDateBinding
|
||||||
@ -71,6 +73,7 @@ class CustomDateActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun subscribeUi(binding: ActivityCustomDateBinding, viewModel: CustomDateViewModel) {
|
private fun subscribeUi(binding: ActivityCustomDateBinding, viewModel: CustomDateViewModel) {
|
||||||
binding.viewModel = viewModel
|
binding.viewModel = viewModel
|
||||||
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
viewModel.dateInput.observe(this, Observer { dateFormat ->
|
viewModel.dateInput.observe(this, Observer { dateFormat ->
|
||||||
formatJob?.cancel()
|
formatJob?.cancel()
|
||||||
@ -87,15 +90,18 @@ class CustomDateActivity : AppCompatActivity() {
|
|||||||
ERROR_STRING
|
ERROR_STRING
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
"__"
|
ERROR_STRING
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Preferences.isDateCapitalize) {
|
if (viewModel.isDateCapitalize.value == true) {
|
||||||
text = text.getCapWordString()
|
text = text.getCapWordString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (viewModel.isDateUppercase.value == true) {
|
||||||
|
text = text.toUpperCase(Locale.getDefault())
|
||||||
|
}
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
action_save.isVisible = text != ERROR_STRING
|
|
||||||
loader.visibility = View.INVISIBLE
|
loader.visibility = View.INVISIBLE
|
||||||
date_format_value.text = text
|
date_format_value.text = text
|
||||||
}
|
}
|
||||||
@ -105,8 +111,30 @@ class CustomDateActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
viewModel.isDateCapitalize.observe(this, Observer {
|
viewModel.isDateCapitalize.observe(this, Observer {
|
||||||
viewModel.dateInput.value = viewModel.dateInput.value
|
viewModel.dateInput.value = viewModel.dateInput.value
|
||||||
binding.isdCapitalizeEnabled = it
|
updateCapitalizeUi()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
viewModel.isDateUppercase.observe(this, Observer {
|
||||||
|
viewModel.dateInput.value = viewModel.dateInput.value
|
||||||
|
updateCapitalizeUi()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateCapitalizeUi() {
|
||||||
|
when {
|
||||||
|
viewModel.isDateUppercase.value == true -> {
|
||||||
|
action_capitalize.setImageDrawable(ContextCompat.getDrawable(this@CustomDateActivity, R.drawable.round_publish))
|
||||||
|
action_capitalize.alpha = 1f
|
||||||
|
}
|
||||||
|
viewModel.isDateCapitalize.value == true -> {
|
||||||
|
action_capitalize.setImageDrawable(ContextCompat.getDrawable(this@CustomDateActivity, R.drawable.ic_capitalize))
|
||||||
|
action_capitalize.alpha = 1f
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
action_capitalize.setImageDrawable(ContextCompat.getDrawable(this@CustomDateActivity, R.drawable.round_publish))
|
||||||
|
action_capitalize.alpha = 0.3f
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
@ -114,13 +142,21 @@ class CustomDateActivity : AppCompatActivity() {
|
|||||||
onBackPressed()
|
onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
action_save.setOnClickListener {
|
|
||||||
Preferences.dateFormat = viewModel.dateInput.value ?: ""
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
action_capitalize.setOnClickListener {
|
action_capitalize.setOnClickListener {
|
||||||
Preferences.isDateCapitalize = !Preferences.isDateCapitalize
|
when {
|
||||||
|
viewModel.isDateUppercase.value == true -> {
|
||||||
|
viewModel.isDateCapitalize.value = false
|
||||||
|
viewModel.isDateUppercase.value = false
|
||||||
|
}
|
||||||
|
viewModel.isDateCapitalize.value == true -> {
|
||||||
|
viewModel.isDateCapitalize.value = false
|
||||||
|
viewModel.isDateUppercase.value = true
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
viewModel.isDateCapitalize.value = true
|
||||||
|
viewModel.isDateUppercase.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
action_capitalize.setOnLongClickListener {
|
action_capitalize.setOnLongClickListener {
|
||||||
@ -133,6 +169,15 @@ class CustomDateActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onBackPressed() {
|
||||||
|
Preferences.blockingBulk {
|
||||||
|
dateFormat = viewModel.dateInput.value ?: ""
|
||||||
|
isDateCapitalize = viewModel.isDateCapitalize.value ?: true
|
||||||
|
isDateUppercase = viewModel.isDateUppercase.value ?: false
|
||||||
|
}
|
||||||
|
super.onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val ERROR_STRING = "--"
|
const val ERROR_STRING = "--"
|
||||||
val DATE: Calendar = Calendar.getInstance().apply {
|
val DATE: Calendar = Calendar.getInstance().apply {
|
||||||
|
@ -0,0 +1,251 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.activities
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.Typeface
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.HandlerThread
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.provider.FontRequest
|
||||||
|
import androidx.core.provider.FontsContractCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.databinding.DataBindingUtil
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.chibatching.kotpref.blockingBulk
|
||||||
|
import com.koolio.library.Font
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||||
|
import com.tommasoberlose.anotherwidget.databinding.ActivityCustomFontBinding
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.DateHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.CustomFontViewModel
|
||||||
|
import kotlinx.android.synthetic.main.activity_choose_application.*
|
||||||
|
import kotlinx.android.synthetic.main.activity_choose_application.action_back
|
||||||
|
import kotlinx.android.synthetic.main.activity_choose_application.clear_search
|
||||||
|
import kotlinx.android.synthetic.main.activity_choose_application.list_view
|
||||||
|
import kotlinx.android.synthetic.main.activity_choose_application.loader
|
||||||
|
import kotlinx.android.synthetic.main.activity_choose_application.search
|
||||||
|
import kotlinx.android.synthetic.main.activity_music_players_filter.*
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
|
import net.idik.lib.slimadapter.diff.DefaultDiffCallback
|
||||||
|
|
||||||
|
|
||||||
|
class CustomFontActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private lateinit var adapter: SlimAdapter
|
||||||
|
private lateinit var viewModel: CustomFontViewModel
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
viewModel = ViewModelProvider(this).get(CustomFontViewModel::class.java)
|
||||||
|
val binding = DataBindingUtil.setContentView<ActivityCustomFontBinding>(
|
||||||
|
this,
|
||||||
|
R.layout.activity_custom_font
|
||||||
|
)
|
||||||
|
|
||||||
|
list_view.setHasFixedSize(true)
|
||||||
|
val mLayoutManager = LinearLayoutManager(this)
|
||||||
|
list_view.layoutManager = mLayoutManager
|
||||||
|
|
||||||
|
adapter = SlimAdapter.create()
|
||||||
|
adapter.enableDiff(object: DefaultDiffCallback() {
|
||||||
|
override fun areItemsTheSame(oldItem: Any?, newItem: Any?): Boolean {
|
||||||
|
return oldItem is Font && newItem is Font && oldItem.fontFamily == newItem.fontFamily
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: Any?, newItem: Any?): Boolean {
|
||||||
|
return oldItem is Font && newItem is Font && oldItem.fontFamily == newItem.fontFamily
|
||||||
|
}
|
||||||
|
})
|
||||||
|
adapter
|
||||||
|
.register<String>(R.layout.list_item) { item, injector ->
|
||||||
|
injector
|
||||||
|
.text(R.id.text, item)
|
||||||
|
.with<TextView>(R.id.text) {
|
||||||
|
val googleSans: Typeface = when (Preferences.customFontVariant) {
|
||||||
|
"100" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_thin.ttf")
|
||||||
|
"200" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_light.ttf")
|
||||||
|
"500" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_medium.ttf")
|
||||||
|
"700" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_bold.ttf")
|
||||||
|
"800" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_black.ttf")
|
||||||
|
else -> Typeface.createFromAsset(this.assets, "fonts/google_sans_regular.ttf")
|
||||||
|
}
|
||||||
|
it.typeface = googleSans
|
||||||
|
}
|
||||||
|
|
||||||
|
injector.clicked(R.id.text) {
|
||||||
|
val dialog = BottomSheetMenu<String>(this, header = item)
|
||||||
|
listOf("100", "200", "regular", "500", "700", "800").forEachIndexed { index, s ->
|
||||||
|
dialog.addItem(SettingsStringHelper.getVariantLabel(this, s), s)
|
||||||
|
}
|
||||||
|
dialog.addOnSelectItemListener { value ->
|
||||||
|
saveGoogleSansFont(value)
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.register<Font>(R.layout.list_item) { item, injector ->
|
||||||
|
injector
|
||||||
|
.text(R.id.text, item.fontFamily)
|
||||||
|
.with<TextView>(R.id.text) {
|
||||||
|
val request = FontRequest(
|
||||||
|
"com.google.android.gms.fonts",
|
||||||
|
"com.google.android.gms",
|
||||||
|
item.queryString,
|
||||||
|
R.array.com_google_android_gms_fonts_certs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
val callback = object : FontsContractCompat.FontRequestCallback() {
|
||||||
|
override fun onTypefaceRetrieved(typeface: Typeface) {
|
||||||
|
it.typeface = typeface
|
||||||
|
it.isVisible = true
|
||||||
|
|
||||||
|
it.measure(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTypefaceRequestFailed(reason: Int) {
|
||||||
|
it.isVisible = false
|
||||||
|
it.layoutParams = it.layoutParams.apply {
|
||||||
|
height = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val handlerThread = HandlerThread(item.fontFamily)
|
||||||
|
handlerThread.start()
|
||||||
|
val mHandler = Handler(handlerThread.looper)
|
||||||
|
FontsContractCompat.requestFont(this, request, callback, mHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
injector.clicked(R.id.text) {
|
||||||
|
val dialog = BottomSheetMenu<Int>(this, header = item.fontFamily)
|
||||||
|
if (item.fontVariants.isEmpty()) {
|
||||||
|
dialog.addItem(SettingsStringHelper.getVariantLabel(this, "regular"), -1)
|
||||||
|
} else {
|
||||||
|
item.fontVariants.filter { !it.contains("italic") }
|
||||||
|
.forEachIndexed { index, s ->
|
||||||
|
dialog.addItem(SettingsStringHelper.getVariantLabel(this, s), index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dialog.addOnSelectItemListener { value ->
|
||||||
|
saveFont(item, value)
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.attachTo(list_view)
|
||||||
|
|
||||||
|
setupListener()
|
||||||
|
subscribeUi(binding, viewModel)
|
||||||
|
|
||||||
|
search.requestFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var filterJob: Job? = null
|
||||||
|
|
||||||
|
private fun subscribeUi(binding: ActivityCustomFontBinding, viewModel: CustomFontViewModel) {
|
||||||
|
binding.viewModel = viewModel
|
||||||
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
|
viewModel.fontList.observe(this, Observer {
|
||||||
|
updateList(list = it)
|
||||||
|
loader.visibility = View.INVISIBLE
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.searchInput.observe(this, Observer { search ->
|
||||||
|
updateList(search = search)
|
||||||
|
clear_search.isVisible = search.isNotBlank()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateList(
|
||||||
|
list: ArrayList<Font>? = viewModel.fontList.value,
|
||||||
|
search: String? = viewModel.searchInput.value
|
||||||
|
) {
|
||||||
|
loader.visibility = View.VISIBLE
|
||||||
|
filterJob?.cancel()
|
||||||
|
filterJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
if (list != null && list.isNotEmpty()) {
|
||||||
|
delay(200)
|
||||||
|
val filteredList: List<Any> = if (search == null || search == "") {
|
||||||
|
listOf(getString(R.string.custom_font_subtitle_1)) + list.distinctBy { it.fontFamily }
|
||||||
|
} else {
|
||||||
|
(listOf(getString(R.string.custom_font_subtitle_1)) + list.distinctBy { it.fontFamily }).filter {
|
||||||
|
when (it) {
|
||||||
|
is Font -> {
|
||||||
|
it.fontFamily.contains(search, true)
|
||||||
|
}
|
||||||
|
is String -> {
|
||||||
|
it.contains(search, ignoreCase = true)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.sortedWith { el1, el2 ->
|
||||||
|
if (el1 is Font && el2 is Font) {
|
||||||
|
el1.fontFamily.compareTo(el2.fontFamily)
|
||||||
|
} else if (el1 is Font && el2 is String) {
|
||||||
|
el1.fontFamily.compareTo(el2)
|
||||||
|
} else if (el1 is String && el2 is Font) {
|
||||||
|
el1.compareTo(el2.fontFamily)
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
adapter.updateData(filteredList)
|
||||||
|
loader.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupListener() {
|
||||||
|
action_back.setOnClickListener {
|
||||||
|
onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_search.setOnClickListener {
|
||||||
|
viewModel.searchInput.value = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveFont(font: Font, variantPos: Int? = null) {
|
||||||
|
val resultIntent = Intent()
|
||||||
|
Preferences.blockingBulk {
|
||||||
|
customFont = Constants.CUSTOM_FONT_DOWNLOADED
|
||||||
|
customFontName = font.fontFamily
|
||||||
|
customFontFile = if (variantPos != null && variantPos > -1) font.getQueryString(variantPos) else font.queryString
|
||||||
|
customFontVariant = if (variantPos != null && variantPos > -1) font.fontVariants[variantPos] else "regular"
|
||||||
|
}
|
||||||
|
setResult(Activity.RESULT_OK, resultIntent)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun saveGoogleSansFont(variant: String) {
|
||||||
|
val resultIntent = Intent()
|
||||||
|
Preferences.blockingBulk {
|
||||||
|
customFont = Constants.CUSTOM_FONT_GOOGLE_SANS
|
||||||
|
customFontName = ""
|
||||||
|
customFontFile = ""
|
||||||
|
customFontVariant = variant
|
||||||
|
}
|
||||||
|
setResult(Activity.RESULT_OK, resultIntent)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ import android.view.Window
|
|||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
@ -28,12 +29,18 @@ import com.karumi.dexter.MultiplePermissionsReport
|
|||||||
import com.karumi.dexter.PermissionToken
|
import com.karumi.dexter.PermissionToken
|
||||||
import com.karumi.dexter.listener.PermissionRequest
|
import com.karumi.dexter.listener.PermissionRequest
|
||||||
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
|
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
|
||||||
|
import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
|
||||||
import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding
|
import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding
|
||||||
import com.tommasoberlose.anotherwidget.databinding.ActivityCustomLocationBinding
|
import com.tommasoberlose.anotherwidget.databinding.ActivityCustomLocationBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.ChooseApplicationViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.ChooseApplicationViewModel
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.CustomLocationViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.CustomLocationViewModel
|
||||||
import kotlinx.android.synthetic.main.activity_custom_location.*
|
import kotlinx.android.synthetic.main.activity_custom_location.*
|
||||||
|
import kotlinx.android.synthetic.main.activity_custom_location.action_back
|
||||||
|
import kotlinx.android.synthetic.main.activity_custom_location.clear_search
|
||||||
|
import kotlinx.android.synthetic.main.activity_custom_location.list_view
|
||||||
|
import kotlinx.android.synthetic.main.activity_custom_location.loader
|
||||||
|
import kotlinx.android.synthetic.main.activity_music_players_filter.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import net.idik.lib.slimadapter.SlimAdapter
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
@ -62,8 +69,12 @@ class CustomLocationActivity : AppCompatActivity() {
|
|||||||
injector
|
injector
|
||||||
.text(R.id.text, getString(R.string.custom_location_gps))
|
.text(R.id.text, getString(R.string.custom_location_gps))
|
||||||
.clicked(R.id.text) {
|
.clicked(R.id.text) {
|
||||||
|
MaterialBottomSheetDialog(this, message = getString(R.string.background_location_warning))
|
||||||
|
.setPositiveButton(getString(android.R.string.ok)) {
|
||||||
requirePermission()
|
requirePermission()
|
||||||
}
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.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))
|
||||||
@ -94,6 +105,8 @@ class CustomLocationActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun subscribeUi(binding: ActivityCustomLocationBinding, viewModel: CustomLocationViewModel) {
|
private fun subscribeUi(binding: ActivityCustomLocationBinding, viewModel: CustomLocationViewModel) {
|
||||||
binding.viewModel = viewModel
|
binding.viewModel = viewModel
|
||||||
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
viewModel.addresses.observe(this, Observer {
|
viewModel.addresses.observe(this, Observer {
|
||||||
adapter.updateData(listOf("Default") + it)
|
adapter.updateData(listOf("Default") + it)
|
||||||
loader.visibility = View.INVISIBLE
|
loader.visibility = View.INVISIBLE
|
||||||
@ -120,6 +133,7 @@ class CustomLocationActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
clear_search.isVisible = location.isNotBlank()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,5 +171,9 @@ class CustomLocationActivity : AppCompatActivity() {
|
|||||||
action_back.setOnClickListener {
|
action_back.setOnClickListener {
|
||||||
onBackPressed()
|
onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear_search.setOnClickListener {
|
||||||
|
viewModel.locationInput.value = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,152 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.activities
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.os.Bundle
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
|
import android.content.pm.ResolveInfo
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.databinding.DataBindingUtil
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding
|
||||||
|
import com.tommasoberlose.anotherwidget.databinding.ActivityMusicPlayersFilterBinding
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.ChooseApplicationViewModel
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MusicPlayersFilterViewModel
|
||||||
|
import kotlinx.android.synthetic.main.activity_music_players_filter.*
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
|
import kotlin.Comparator as Comparator1
|
||||||
|
|
||||||
|
|
||||||
|
class MusicPlayersFilterActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private lateinit var adapter: SlimAdapter
|
||||||
|
private lateinit var viewModel: MusicPlayersFilterViewModel
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
viewModel = ViewModelProvider(this).get(MusicPlayersFilterViewModel::class.java)
|
||||||
|
val binding = DataBindingUtil.setContentView<ActivityMusicPlayersFilterBinding>(this, R.layout.activity_music_players_filter)
|
||||||
|
|
||||||
|
list_view.setHasFixedSize(true)
|
||||||
|
val mLayoutManager = LinearLayoutManager(this)
|
||||||
|
list_view.layoutManager = mLayoutManager
|
||||||
|
|
||||||
|
adapter = SlimAdapter.create()
|
||||||
|
adapter
|
||||||
|
.register<ResolveInfo>(R.layout.application_info_layout) { item, injector ->
|
||||||
|
injector
|
||||||
|
.text(R.id.text, item.loadLabel(viewModel.pm))
|
||||||
|
.with<ImageView>(R.id.icon) {
|
||||||
|
Glide
|
||||||
|
.with(this)
|
||||||
|
.load(item.loadIcon(viewModel.pm))
|
||||||
|
.centerCrop()
|
||||||
|
.into(it)
|
||||||
|
}
|
||||||
|
.visible(R.id.checkBox)
|
||||||
|
.clicked(R.id.item) {
|
||||||
|
toggleApp(item)
|
||||||
|
adapter.notifyItemRangeChanged(0, adapter.data.size)
|
||||||
|
}
|
||||||
|
.clicked(R.id.checkBox) {
|
||||||
|
toggleApp(item)
|
||||||
|
adapter.notifyItemRangeChanged(0, adapter.data.size)
|
||||||
|
}
|
||||||
|
.checked(R.id.checkBox, MediaPlayerHelper.isMusicPlayerAccepted(item.activityInfo.packageName))
|
||||||
|
}
|
||||||
|
.attachTo(list_view)
|
||||||
|
|
||||||
|
setupListener()
|
||||||
|
subscribeUi(binding, viewModel)
|
||||||
|
|
||||||
|
search.requestFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var filterJob: Job? = null
|
||||||
|
|
||||||
|
private fun subscribeUi(binding: ActivityMusicPlayersFilterBinding, viewModel: MusicPlayersFilterViewModel) {
|
||||||
|
binding.viewModel = viewModel
|
||||||
|
binding.lifecycleOwner = this
|
||||||
|
|
||||||
|
viewModel.appList.observe(this, Observer {
|
||||||
|
updateList(list = it)
|
||||||
|
loader.visibility = View.INVISIBLE
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.searchInput.observe(this, Observer { search ->
|
||||||
|
updateList(search = search)
|
||||||
|
clear_search.isVisible = search.isNotBlank()
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.musicPlayersFilter.observe(this, {
|
||||||
|
updateList()
|
||||||
|
clear_selection.isVisible = Preferences.musicPlayersFilter != ""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateList(list: List<ResolveInfo>? = viewModel.appList.value, search: String? = viewModel.searchInput.value) {
|
||||||
|
loader.visibility = View.VISIBLE
|
||||||
|
filterJob?.cancel()
|
||||||
|
filterJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
if (list != null && list.isNotEmpty()) {
|
||||||
|
delay(200)
|
||||||
|
val filteredList: List<ResolveInfo> = if (search == null || search == "") {
|
||||||
|
list
|
||||||
|
} else {
|
||||||
|
list.filter {
|
||||||
|
it.loadLabel(viewModel.pm).contains(search, true)
|
||||||
|
}
|
||||||
|
}.sortedWith { app1, app2 ->
|
||||||
|
if (MediaPlayerHelper.isMusicPlayerAccepted(app1.activityInfo.packageName) && MediaPlayerHelper.isMusicPlayerAccepted(app2.activityInfo.packageName)) {
|
||||||
|
app1.loadLabel(viewModel.pm).toString().compareTo(app2.loadLabel(viewModel.pm).toString(), ignoreCase = true)
|
||||||
|
} else if (MediaPlayerHelper.isMusicPlayerAccepted(app1.activityInfo.packageName)) {
|
||||||
|
-1
|
||||||
|
} else if (MediaPlayerHelper.isMusicPlayerAccepted(app2.activityInfo.packageName)) {
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
app1.loadLabel(viewModel.pm).toString().compareTo(app2.loadLabel(viewModel.pm).toString(), ignoreCase = true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
adapter.updateData(filteredList)
|
||||||
|
loader.visibility = View.INVISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupListener() {
|
||||||
|
action_back.setOnClickListener {
|
||||||
|
onBackPressed()
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_search.setOnClickListener {
|
||||||
|
viewModel.searchInput.value = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_selection.setOnClickListener {
|
||||||
|
Preferences.musicPlayersFilter = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toggleApp(app: ResolveInfo) {
|
||||||
|
MediaPlayerHelper.toggleMusicPlayerFilter(app.activityInfo.packageName)
|
||||||
|
}
|
||||||
|
}
|
@ -1,37 +1,191 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.activities
|
package com.tommasoberlose.anotherwidget.ui.activities
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.AlertDialog
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.content.pm.ResolveInfo
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Html
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.core.widget.addTextChangedListener
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.bumptech.glide.Glide
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||||
|
import com.tommasoberlose.anotherwidget.components.BottomSheetWeatherProviderSettings
|
||||||
|
import com.tommasoberlose.anotherwidget.databinding.ActivityChooseApplicationBinding
|
||||||
|
import com.tommasoberlose.anotherwidget.databinding.ActivityWeatherProviderBinding
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.ChooseApplicationViewModel
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.WeatherProviderViewModel
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.collapse
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.expand
|
||||||
import com.tommasoberlose.anotherwidget.utils.openURI
|
import com.tommasoberlose.anotherwidget.utils.openURI
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.reveal
|
||||||
import kotlinx.android.synthetic.main.activity_weather_provider.*
|
import kotlinx.android.synthetic.main.activity_weather_provider.*
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.greenrobot.eventbus.Subscribe
|
||||||
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
|
|
||||||
class WeatherProviderActivity : AppCompatActivity() {
|
class WeatherProviderActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private lateinit var adapter: SlimAdapter
|
||||||
|
private lateinit var viewModel: WeatherProviderViewModel
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_weather_provider)
|
setContentView(R.layout.activity_weather_provider)
|
||||||
|
|
||||||
|
viewModel = ViewModelProvider(this).get(WeatherProviderViewModel::class.java)
|
||||||
|
|
||||||
|
list_view.setHasFixedSize(true)
|
||||||
|
val mLayoutManager = LinearLayoutManager(this)
|
||||||
|
list_view.layoutManager = mLayoutManager
|
||||||
|
|
||||||
|
adapter = SlimAdapter.create()
|
||||||
|
adapter
|
||||||
|
.register<Constants.WeatherProvider>(R.layout.weather_provider_list_item) { provider, injector ->
|
||||||
|
injector
|
||||||
|
.text(R.id.text, WeatherHelper.getProviderName(this, provider))
|
||||||
|
.clicked(R.id.item) {
|
||||||
|
if (Preferences.weatherProvider != provider.value) {
|
||||||
|
Preferences.weatherProviderError = "-"
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
}
|
||||||
|
val oldValue = Preferences.weatherProvider
|
||||||
|
Preferences.weatherProvider = provider.value
|
||||||
|
updateListItem(oldValue)
|
||||||
|
updateListItem()
|
||||||
|
loader.isVisible = true
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
WeatherHelper.updateWeather(this@WeatherProviderActivity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.clicked(R.id.radioButton) {
|
||||||
|
if (Preferences.weatherProvider != provider.value) {
|
||||||
|
Preferences.weatherProviderError = "-"
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
|
}
|
||||||
|
val oldValue = Preferences.weatherProvider
|
||||||
|
Preferences.weatherProvider = provider.value
|
||||||
|
updateListItem(oldValue)
|
||||||
|
updateListItem()
|
||||||
|
loader.isVisible = true
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
WeatherHelper.updateWeather(this@WeatherProviderActivity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.checked(R.id.radioButton, provider.value == Preferences.weatherProvider)
|
||||||
|
.with<TextView>(R.id.text2) {
|
||||||
|
if (WeatherHelper.isKeyRequired(provider)) {
|
||||||
|
it.text = getString(R.string.api_key_required_message)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (provider == Constants.WeatherProvider.WEATHER_GOV) {
|
||||||
|
it.text = getString(R.string.us_only_message)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (provider == Constants.WeatherProvider.YR) {
|
||||||
|
it.text = getString(R.string.celsius_only_message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.clicked(R.id.action_configure) {
|
||||||
|
BottomSheetWeatherProviderSettings(this) {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
loader.isVisible = true
|
||||||
|
WeatherHelper.updateWeather(this@WeatherProviderActivity)
|
||||||
|
}
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
.visibility(R.id.action_configure, if (/*WeatherHelper.isKeyRequired(provider) && */provider.value == Preferences.weatherProvider) View.VISIBLE else View.GONE)
|
||||||
|
.with<TextView>(R.id.provider_error) {
|
||||||
|
if (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-") {
|
||||||
|
it.text = Preferences.weatherProviderError
|
||||||
|
it.isVisible = provider.value == Preferences.weatherProvider
|
||||||
|
} else if (Preferences.weatherProviderLocationError != "") {
|
||||||
|
it.text = Preferences.weatherProviderLocationError
|
||||||
|
it.isVisible = provider.value == Preferences.weatherProvider
|
||||||
|
} else {
|
||||||
|
it.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.image(R.id.action_configure, ContextCompat.getDrawable(this, if (WeatherHelper.isKeyRequired(provider)) R.drawable.round_settings else R.drawable.outline_info_white))
|
||||||
|
}.attachTo(list_view)
|
||||||
|
|
||||||
|
adapter.updateData(
|
||||||
|
Constants.WeatherProvider.values().asList()
|
||||||
|
.filter { it != Constants.WeatherProvider.HERE }
|
||||||
|
.filter { it != Constants.WeatherProvider.ACCUWEATHER }
|
||||||
|
)
|
||||||
|
|
||||||
|
setupListener()
|
||||||
|
subscribeUi(viewModel)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun subscribeUi(viewModel: WeatherProviderViewModel) {
|
||||||
|
viewModel.weatherProviderError.observe(this) {
|
||||||
|
updateListItem()
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.weatherProviderLocationError.observe(this) {
|
||||||
|
updateListItem()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateListItem(provider: Int = Preferences.weatherProvider) {
|
||||||
|
(adapter.data).forEachIndexed { index, item ->
|
||||||
|
if (item is Constants.WeatherProvider && item.value == provider) {
|
||||||
|
adapter.notifyItemChanged(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupListener() {
|
||||||
action_back.setOnClickListener {
|
action_back.setOnClickListener {
|
||||||
onBackPressed()
|
onBackPressed()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
action_save.setOnClickListener {
|
override fun onBackPressed() {
|
||||||
Preferences.weatherProviderApi = api_key.editText?.text.toString()
|
|
||||||
setResult(Activity.RESULT_OK)
|
setResult(Activity.RESULT_OK)
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
action_open_provider.setOnClickListener {
|
override fun onResume() {
|
||||||
openURI("https://home.openweathermap.org/users/sign_up")
|
super.onResume()
|
||||||
|
EventBus.getDefault().register(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
api_key.editText?.setText(Preferences.weatherProviderApi)
|
override fun onPause() {
|
||||||
|
EventBus.getDefault().unregister(this)
|
||||||
|
super.onPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
fun onMessageEvent(ignore: MainFragment.UpdateUiMessageEvent?) {
|
||||||
|
loader.isVisible = Preferences.weatherProviderError == "-"
|
||||||
|
if (Preferences.weatherProviderError == "" && Preferences.weatherProviderLocationError == "") {
|
||||||
|
Snackbar.make(list_view, getString(R.string.settings_weather_provider_api_key_subtitle_all_set), Snackbar.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import android.Manifest
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
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
|
||||||
@ -31,10 +31,8 @@ import com.tommasoberlose.anotherwidget.ui.activities.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.DateHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.CustomDateActivity
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDefaultSet
|
import com.tommasoberlose.anotherwidget.utils.isDefaultSet
|
||||||
import com.tommasoberlose.anotherwidget.utils.toast
|
import com.tommasoberlose.anotherwidget.utils.toast
|
||||||
@ -42,7 +40,6 @@ import kotlinx.android.synthetic.main.fragment_calendar_settings.*
|
|||||||
import kotlinx.android.synthetic.main.fragment_calendar_settings.scrollView
|
import kotlinx.android.synthetic.main.fragment_calendar_settings.scrollView
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.*
|
|
||||||
import kotlin.Comparator
|
import kotlin.Comparator
|
||||||
|
|
||||||
class CalendarTabFragment : Fragment() {
|
class CalendarTabFragment : Fragment() {
|
||||||
@ -77,7 +74,7 @@ class CalendarTabFragment : Fragment() {
|
|||||||
super.onActivityCreated(savedInstanceState)
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
show_all_day_toggle.isChecked = Preferences.calendarAllDay
|
show_all_day_toggle.isChecked = Preferences.calendarAllDay
|
||||||
show_declined_events_toggle.isChecked = Preferences.showDeclinedEvents
|
show_only_busy_events_toggle.isChecked = Preferences.showOnlyBusyEvents
|
||||||
show_diff_time_toggle.isChecked = Preferences.showDiffTime
|
show_diff_time_toggle.isChecked = Preferences.showDiffTime
|
||||||
show_multiple_events_toggle.isChecked = Preferences.showNextEvent
|
show_multiple_events_toggle.isChecked = Preferences.showNextEvent
|
||||||
|
|
||||||
@ -113,12 +110,6 @@ class CalendarTabFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.showDeclinedEvents.observe(viewLifecycleOwner, Observer {
|
|
||||||
maintainScrollPosition {
|
|
||||||
show_declined_events_label?.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
viewModel.secondRowInformation.observe(viewLifecycleOwner, Observer {
|
viewModel.secondRowInformation.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
second_row_info_label?.text = getString(SettingsStringHelper.getSecondRowInfoString(it))
|
second_row_info_label?.text = getString(SettingsStringHelper.getSecondRowInfoString(it))
|
||||||
@ -160,7 +151,7 @@ class CalendarTabFragment : Fragment() {
|
|||||||
viewModel.calendarAppName.observe(viewLifecycleOwner, Observer {
|
viewModel.calendarAppName.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
calendar_app_label?.text = when {
|
calendar_app_label?.text = when {
|
||||||
Preferences.clockAppName != "" -> Preferences.clockAppName
|
Preferences.calendarAppName != "" -> Preferences.calendarAppName
|
||||||
else -> {
|
else -> {
|
||||||
if (IntentHelper.getCalendarIntent(requireContext()).isDefaultSet(requireContext())) {
|
if (IntentHelper.getCalendarIntent(requireContext()).isDefaultSet(requireContext())) {
|
||||||
getString(
|
getString(
|
||||||
@ -258,18 +249,58 @@ class CalendarTabFragment : Fragment() {
|
|||||||
show_all_day_toggle.setOnCheckedChangeListener { _, isChecked ->
|
show_all_day_toggle.setOnCheckedChangeListener { _, isChecked ->
|
||||||
if (Preferences.showEvents) {
|
if (Preferences.showEvents) {
|
||||||
Preferences.calendarAllDay = isChecked
|
Preferences.calendarAllDay = isChecked
|
||||||
|
updateCalendar()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
action_show_declined_events.setOnClickListener {
|
action_change_attendee_filter.setOnClickListener {
|
||||||
if (Preferences.showEvents) {
|
if (Preferences.showEvents) {
|
||||||
show_declined_events_toggle.isChecked = !show_declined_events_toggle.isChecked
|
val selectedValues = emptyList<Int>().toMutableList()
|
||||||
|
if (Preferences.showDeclinedEvents) {
|
||||||
|
selectedValues.add(CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED)
|
||||||
|
}
|
||||||
|
if (Preferences.showInvitedEvents) {
|
||||||
|
selectedValues.add(CalendarContract.Attendees.ATTENDEE_STATUS_INVITED)
|
||||||
|
}
|
||||||
|
if (Preferences.showAcceptedEvents) {
|
||||||
|
selectedValues.add(CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED)
|
||||||
|
}
|
||||||
|
|
||||||
|
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_attendee_status_title), isMultiSelection = true)
|
||||||
|
.setSelectedValues(selectedValues)
|
||||||
|
|
||||||
|
dialog.addItem(
|
||||||
|
getString(R.string.attendee_status_invited),
|
||||||
|
CalendarContract.Attendees.ATTENDEE_STATUS_INVITED
|
||||||
|
)
|
||||||
|
dialog.addItem(
|
||||||
|
getString(R.string.attendee_status_accepted),
|
||||||
|
CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED
|
||||||
|
)
|
||||||
|
dialog.addItem(
|
||||||
|
getString(R.string.attendee_status_declined),
|
||||||
|
CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED
|
||||||
|
)
|
||||||
|
|
||||||
|
dialog.addOnMultipleSelectItemListener { values ->
|
||||||
|
Preferences.showDeclinedEvents = values.contains(CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED)
|
||||||
|
Preferences.showAcceptedEvents = values.contains(CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED)
|
||||||
|
Preferences.showInvitedEvents = values.contains(CalendarContract.Attendees.ATTENDEE_STATUS_INVITED)
|
||||||
|
updateCalendar()
|
||||||
|
}.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
show_declined_events_toggle.setOnCheckedChangeListener { _, isChecked ->
|
action_show_only_busy_events.setOnClickListener {
|
||||||
if (Preferences.showEvents) {
|
if (Preferences.showEvents) {
|
||||||
Preferences.showDeclinedEvents = isChecked
|
show_only_busy_events_toggle.isChecked = !show_only_busy_events_toggle.isChecked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
show_only_busy_events_toggle.setOnCheckedChangeListener { _, isChecked ->
|
||||||
|
if (Preferences.showEvents) {
|
||||||
|
Preferences.showOnlyBusyEvents = isChecked
|
||||||
|
updateCalendar()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ import com.tommasoberlose.anotherwidget.helpers.IntentHelper
|
|||||||
import com.tommasoberlose.anotherwidget.ui.activities.ChooseApplicationActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.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.utils.isDarkTheme
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDefaultSet
|
import com.tommasoberlose.anotherwidget.utils.isDefaultSet
|
||||||
import kotlinx.android.synthetic.main.fragment_clock_settings.*
|
import kotlinx.android.synthetic.main.fragment_clock_settings.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -95,6 +96,7 @@ class ClockTabFragment : Fragment() {
|
|||||||
) {
|
) {
|
||||||
binding.isClockVisible = Preferences.showClock
|
binding.isClockVisible = Preferences.showClock
|
||||||
binding.is24Format = DateFormat.is24HourFormat(requireContext())
|
binding.is24Format = DateFormat.is24HourFormat(requireContext())
|
||||||
|
binding.isDarkModeEnabled = activity?.isDarkTheme() == true
|
||||||
|
|
||||||
viewModel.showBigClockWarning.observe(viewLifecycleOwner, Observer {
|
viewModel.showBigClockWarning.observe(viewLifecycleOwner, Observer {
|
||||||
large_clock_warning?.isVisible = it
|
large_clock_warning?.isVisible = it
|
||||||
@ -127,7 +129,18 @@ class ClockTabFragment : Fragment() {
|
|||||||
clock_text_color_label?.text = getString(R.string.transparent)
|
clock_text_color_label?.text = getString(R.string.transparent)
|
||||||
} else {
|
} else {
|
||||||
clock_text_color_label?.text =
|
clock_text_color_label?.text =
|
||||||
"#%s".format(Integer.toHexString(ColorHelper.getClockFontColor())).toUpperCase()
|
"#%s".format(Integer.toHexString(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.clockTextColorDark.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.clockTextAlphaDark == "00") {
|
||||||
|
clock_text_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
clock_text_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -138,7 +151,18 @@ class ClockTabFragment : Fragment() {
|
|||||||
clock_text_color_label?.text = getString(R.string.transparent)
|
clock_text_color_label?.text = getString(R.string.transparent)
|
||||||
} else {
|
} else {
|
||||||
clock_text_color_label?.text =
|
clock_text_color_label?.text =
|
||||||
"#%s".format(Integer.toHexString(ColorHelper.getClockFontColor())).toUpperCase()
|
"#%s".format(Integer.toHexString(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.clockTextAlphaDark.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.clockTextAlphaDark == "00") {
|
||||||
|
clock_text_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
clock_text_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -217,17 +241,26 @@ class ClockTabFragment : Fragment() {
|
|||||||
BottomSheetColorPicker(requireContext(),
|
BottomSheetColorPicker(requireContext(),
|
||||||
colors = colors,
|
colors = colors,
|
||||||
header = getString(R.string.settings_font_color_title),
|
header = getString(R.string.settings_font_color_title),
|
||||||
getSelected = ColorHelper::getClockFontColorRgb,
|
getSelected = { ColorHelper.getClockFontColorRgb(activity?.isDarkTheme() == true) },
|
||||||
onColorSelected = { color: Int ->
|
onColorSelected = { color: Int ->
|
||||||
val colorString = Integer.toHexString(color)
|
val colorString = Integer.toHexString(color)
|
||||||
|
if (activity?.isDarkTheme() == true) {
|
||||||
|
Preferences.clockTextColorDark =
|
||||||
|
"#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||||
|
} else {
|
||||||
Preferences.clockTextColor =
|
Preferences.clockTextColor =
|
||||||
"#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
"#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||||
|
}
|
||||||
},
|
},
|
||||||
showAlphaSelector = true,
|
showAlphaSelector = true,
|
||||||
alpha = Preferences.clockTextAlpha.toIntValue(),
|
alpha = if (activity?.isDarkTheme() == true) Preferences.clockTextAlphaDark.toIntValue() else Preferences.clockTextAlpha.toIntValue(),
|
||||||
onAlphaChangeListener = { alpha ->
|
onAlphaChangeListener = { alpha ->
|
||||||
|
if (activity?.isDarkTheme() == true) {
|
||||||
|
Preferences.clockTextAlphaDark = alpha.toHexValue()
|
||||||
|
} else {
|
||||||
Preferences.clockTextAlpha = alpha.toHexValue()
|
Preferences.clockTextAlpha = alpha.toHexValue()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,19 +3,29 @@ package com.tommasoberlose.anotherwidget.ui.fragments
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.graphics.Typeface
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.HandlerThread
|
||||||
|
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 android.widget.Toast
|
||||||
|
import androidx.core.provider.FontRequest
|
||||||
|
import androidx.core.provider.FontsContractCompat
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.Observer
|
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.chibatching.kotpref.bulk
|
||||||
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.databinding.FragmentGeneralSettingsBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentGeneralSettingsBinding
|
||||||
|
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.global.RequestCode
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||||
@ -23,10 +33,17 @@ 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.helpers.DateHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.WidgetHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.ChooseApplicationActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.CustomDateActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.CustomDateActivity
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.CustomFontActivity
|
||||||
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.ui.widgets.MainWidget
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||||
|
import kotlinx.android.synthetic.main.fragment_clock_settings.*
|
||||||
import kotlinx.android.synthetic.main.fragment_general_settings.*
|
import kotlinx.android.synthetic.main.fragment_general_settings.*
|
||||||
|
import kotlinx.android.synthetic.main.fragment_general_settings.scrollView
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -60,6 +77,7 @@ class GeneralTabFragment : Fragment() {
|
|||||||
|
|
||||||
binding.lifecycleOwner = this
|
binding.lifecycleOwner = this
|
||||||
binding.viewModel = viewModel
|
binding.viewModel = viewModel
|
||||||
|
binding.isDarkModeEnabled = activity?.isDarkTheme() == true
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
@ -102,7 +120,18 @@ class GeneralTabFragment : Fragment() {
|
|||||||
font_color_label?.text = getString(R.string.transparent)
|
font_color_label?.text = getString(R.string.transparent)
|
||||||
} else {
|
} else {
|
||||||
font_color_label?.text =
|
font_color_label?.text =
|
||||||
"#%s".format(Integer.toHexString(ColorHelper.getFontColor())).toUpperCase()
|
"#%s".format(Integer.toHexString(ColorHelper.getFontColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.textGlobalColorDark.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.textGlobalAlphaDark == "00") {
|
||||||
|
font_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
font_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getFontColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -113,7 +142,18 @@ class GeneralTabFragment : Fragment() {
|
|||||||
font_color_label?.text = getString(R.string.transparent)
|
font_color_label?.text = getString(R.string.transparent)
|
||||||
} else {
|
} else {
|
||||||
font_color_label?.text =
|
font_color_label?.text =
|
||||||
"#%s".format(Integer.toHexString(ColorHelper.getFontColor())).toUpperCase()
|
"#%s".format(Integer.toHexString(ColorHelper.getFontColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.textGlobalAlphaDark.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.textGlobalAlphaDark == "00") {
|
||||||
|
font_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
font_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getFontColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -124,7 +164,18 @@ class GeneralTabFragment : Fragment() {
|
|||||||
secondary_font_color_label?.text = getString(R.string.transparent)
|
secondary_font_color_label?.text = getString(R.string.transparent)
|
||||||
} else {
|
} else {
|
||||||
secondary_font_color_label?.text =
|
secondary_font_color_label?.text =
|
||||||
"#%s".format(Integer.toHexString(ColorHelper.getSecondaryFontColor())).toUpperCase()
|
"#%s".format(Integer.toHexString(ColorHelper.getSecondaryFontColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.textSecondaryColorDark.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.textSecondaryAlphaDark == "00") {
|
||||||
|
secondary_font_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
secondary_font_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getSecondaryFontColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -135,7 +186,29 @@ class GeneralTabFragment : Fragment() {
|
|||||||
secondary_font_color_label?.text = getString(R.string.transparent)
|
secondary_font_color_label?.text = getString(R.string.transparent)
|
||||||
} else {
|
} else {
|
||||||
secondary_font_color_label?.text =
|
secondary_font_color_label?.text =
|
||||||
"#%s".format(Integer.toHexString(ColorHelper.getSecondaryFontColor())).toUpperCase()
|
"#%s".format(Integer.toHexString(ColorHelper.getSecondaryFontColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.textSecondaryAlphaDark.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.textSecondaryAlphaDark == "00") {
|
||||||
|
secondary_font_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
secondary_font_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getSecondaryFontColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.secondRowTopMargin.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
second_row_top_margin_label?.text = when (it) {
|
||||||
|
Constants.SecondRowTopMargin.NONE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_none)
|
||||||
|
Constants.SecondRowTopMargin.SMALL.value -> getString(R.string.settings_clock_bottom_margin_subtitle_small)
|
||||||
|
Constants.SecondRowTopMargin.LARGE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_large)
|
||||||
|
else -> getString(R.string.settings_clock_bottom_margin_subtitle_medium)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -146,7 +219,18 @@ class GeneralTabFragment : Fragment() {
|
|||||||
background_color_label?.text = getString(R.string.transparent)
|
background_color_label?.text = getString(R.string.transparent)
|
||||||
} else {
|
} else {
|
||||||
background_color_label?.text =
|
background_color_label?.text =
|
||||||
"#%s".format(Integer.toHexString(ColorHelper.getBackgroundColor())).toUpperCase()
|
"#%s".format(Integer.toHexString(ColorHelper.getBackgroundColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.backgroundCardColorDark.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.backgroundCardAlphaDark == "00") {
|
||||||
|
background_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
background_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getBackgroundColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -157,14 +241,37 @@ class GeneralTabFragment : Fragment() {
|
|||||||
background_color_label?.text = getString(R.string.transparent)
|
background_color_label?.text = getString(R.string.transparent)
|
||||||
} else {
|
} else {
|
||||||
background_color_label?.text =
|
background_color_label?.text =
|
||||||
"#%s".format(Integer.toHexString(ColorHelper.getBackgroundColor())).toUpperCase()
|
"#%s".format(Integer.toHexString(ColorHelper.getBackgroundColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.backgroundCardAlphaDark.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.backgroundCardAlphaDark == "00") {
|
||||||
|
background_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
background_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getBackgroundColor(activity?.isDarkTheme() == true))).toUpperCase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.textShadow.observe(viewLifecycleOwner, Observer {
|
viewModel.textShadow.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
text_shadow_label?.text = getString(SettingsStringHelper.getTextShadowString(it))
|
if (activity?.isDarkTheme() != true) {
|
||||||
|
text_shadow_label?.text =
|
||||||
|
getString(SettingsStringHelper.getTextShadowString(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.textShadowDark.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (activity?.isDarkTheme() == true) {
|
||||||
|
text_shadow_label?.text =
|
||||||
|
getString(SettingsStringHelper.getTextShadowString(it))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -176,7 +283,29 @@ class GeneralTabFragment : Fragment() {
|
|||||||
|
|
||||||
viewModel.customFont.observe(viewLifecycleOwner, Observer {
|
viewModel.customFont.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
custom_font_label?.text = getString(SettingsStringHelper.getCustomFontLabel(it))
|
custom_font_label?.text = SettingsStringHelper.getCustomFontLabel(requireContext(), it)
|
||||||
|
MainWidget.updateWidget(requireContext())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.customFontFile.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
custom_font_label?.text = SettingsStringHelper.getCustomFontLabel(requireContext(), Preferences.customFont)
|
||||||
|
MainWidget.updateWidget(requireContext())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.customFontName.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
custom_font_label?.text = SettingsStringHelper.getCustomFontLabel(requireContext(), Preferences.customFont)
|
||||||
|
MainWidget.updateWidget(requireContext())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.customFontVariant.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
custom_font_label?.text = SettingsStringHelper.getCustomFontLabel(requireContext(), Preferences.customFont)
|
||||||
|
MainWidget.updateWidget(requireContext())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -213,16 +342,24 @@ class GeneralTabFragment : Fragment() {
|
|||||||
BottomSheetColorPicker(requireContext(),
|
BottomSheetColorPicker(requireContext(),
|
||||||
colors = colors,
|
colors = colors,
|
||||||
header = getString(R.string.settings_font_color_title),
|
header = getString(R.string.settings_font_color_title),
|
||||||
getSelected = ColorHelper::getFontColorRgb,
|
getSelected = { ColorHelper.getFontColorRgb(activity?.isDarkTheme() == true) },
|
||||||
onColorSelected = { color: Int ->
|
onColorSelected = { color: Int ->
|
||||||
val colorString = Integer.toHexString(color)
|
val colorString = Integer.toHexString(color)
|
||||||
|
if (activity?.isDarkTheme() == true) {
|
||||||
|
Preferences.textGlobalColorDark = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||||
|
} else {
|
||||||
Preferences.textGlobalColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
Preferences.textGlobalColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||||
|
}
|
||||||
},
|
},
|
||||||
showAlphaSelector = true,
|
showAlphaSelector = true,
|
||||||
alpha = Preferences.textGlobalAlpha.toIntValue(),
|
alpha = if (activity?.isDarkTheme() == true) Preferences.textGlobalAlphaDark.toIntValue() else Preferences.textGlobalAlpha.toIntValue(),
|
||||||
onAlphaChangeListener = { alpha ->
|
onAlphaChangeListener = { alpha ->
|
||||||
|
if (activity?.isDarkTheme() == true) {
|
||||||
|
Preferences.textGlobalAlphaDark = alpha.toHexValue()
|
||||||
|
} else {
|
||||||
Preferences.textGlobalAlpha = alpha.toHexValue()
|
Preferences.textGlobalAlpha = alpha.toHexValue()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,19 +367,55 @@ class GeneralTabFragment : Fragment() {
|
|||||||
BottomSheetColorPicker(requireContext(),
|
BottomSheetColorPicker(requireContext(),
|
||||||
colors = colors,
|
colors = colors,
|
||||||
header = getString(R.string.settings_secondary_font_color_title),
|
header = getString(R.string.settings_secondary_font_color_title),
|
||||||
getSelected = ColorHelper::getSecondaryFontColorRgb,
|
getSelected = { ColorHelper.getSecondaryFontColorRgb(activity?.isDarkTheme() == true) },
|
||||||
onColorSelected = { color: Int ->
|
onColorSelected = { color: Int ->
|
||||||
val colorString = Integer.toHexString(color)
|
val colorString = Integer.toHexString(color)
|
||||||
Preferences.textSecondaryColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
if (activity?.isDarkTheme() == true) {
|
||||||
|
Preferences.textSecondaryColorDark =
|
||||||
|
"#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||||
|
} else {
|
||||||
|
Preferences.textSecondaryColor =
|
||||||
|
"#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||||
|
}
|
||||||
},
|
},
|
||||||
showAlphaSelector = true,
|
showAlphaSelector = true,
|
||||||
alpha = Preferences.textSecondaryAlpha.toIntValue(),
|
alpha = if (activity?.isDarkTheme() == true) Preferences.textSecondaryAlphaDark.toIntValue() else Preferences.textSecondaryAlpha.toIntValue(),
|
||||||
onAlphaChangeListener = { alpha ->
|
onAlphaChangeListener = { alpha ->
|
||||||
|
if (activity?.isDarkTheme() == true) {
|
||||||
|
Preferences.textSecondaryAlphaDark = alpha.toHexValue()
|
||||||
|
} else {
|
||||||
Preferences.textSecondaryAlpha = alpha.toHexValue()
|
Preferences.textSecondaryAlpha = alpha.toHexValue()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action_second_row_top_margin_size.setOnClickListener {
|
||||||
|
BottomSheetMenu<Int>(
|
||||||
|
requireContext(),
|
||||||
|
header = getString(R.string.settings_secondary_row_top_margin_title)
|
||||||
|
).setSelectedValue(Preferences.secondRowTopMargin)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_clock_bottom_margin_subtitle_none),
|
||||||
|
Constants.SecondRowTopMargin.NONE.value
|
||||||
|
)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_clock_bottom_margin_subtitle_small),
|
||||||
|
Constants.SecondRowTopMargin.SMALL.value
|
||||||
|
)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_clock_bottom_margin_subtitle_medium),
|
||||||
|
Constants.SecondRowTopMargin.MEDIUM.value
|
||||||
|
)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_clock_bottom_margin_subtitle_large),
|
||||||
|
Constants.SecondRowTopMargin.LARGE.value
|
||||||
|
)
|
||||||
|
.addOnSelectItemListener { value ->
|
||||||
|
Preferences.secondRowTopMargin = value
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
|
||||||
action_date_format.setOnClickListener {
|
action_date_format.setOnClickListener {
|
||||||
val now = Calendar.getInstance()
|
val now = Calendar.getInstance()
|
||||||
val dialog = BottomSheetMenu<String>(requireContext(), header = getString(R.string.settings_date_format_title)).setSelectedValue(Preferences.dateFormat)
|
val dialog = BottomSheetMenu<String>(requireContext(), header = getString(R.string.settings_date_format_title)).setSelectedValue(Preferences.dateFormat)
|
||||||
@ -254,11 +427,21 @@ class GeneralTabFragment : Fragment() {
|
|||||||
dialog.addItem(getString(R.string.custom_date_format), "-")
|
dialog.addItem(getString(R.string.custom_date_format), "-")
|
||||||
|
|
||||||
dialog.addOnSelectItemListener { value ->
|
dialog.addOnSelectItemListener { value ->
|
||||||
if (value == "-") {
|
when (value) {
|
||||||
|
"-" -> {
|
||||||
startActivity(Intent(requireContext(), CustomDateActivity::class.java))
|
startActivity(Intent(requireContext(), CustomDateActivity::class.java))
|
||||||
} else {
|
}
|
||||||
|
"" -> {
|
||||||
|
Preferences.blockingBulk {
|
||||||
|
isDateCapitalize = false
|
||||||
|
isDateUppercase = false
|
||||||
|
}
|
||||||
Preferences.dateFormat = value
|
Preferences.dateFormat = value
|
||||||
}
|
}
|
||||||
|
else -> {
|
||||||
|
Preferences.dateFormat = value
|
||||||
|
}
|
||||||
|
}
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,49 +449,70 @@ class GeneralTabFragment : Fragment() {
|
|||||||
BottomSheetColorPicker(requireContext(),
|
BottomSheetColorPicker(requireContext(),
|
||||||
colors = colors,
|
colors = colors,
|
||||||
header = getString(R.string.settings_background_color_title),
|
header = getString(R.string.settings_background_color_title),
|
||||||
getSelected = { ColorHelper.getBackgroundColorRgb() },
|
getSelected = { ColorHelper.getBackgroundColorRgb(activity?.isDarkTheme() == true) },
|
||||||
onColorSelected = { color: Int ->
|
onColorSelected = { color: Int ->
|
||||||
val colorString = Integer.toHexString(color)
|
val colorString = Integer.toHexString(color)
|
||||||
Preferences.backgroundCardColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
if (activity?.isDarkTheme() == true) {
|
||||||
|
Preferences.backgroundCardColorDark =
|
||||||
|
"#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||||
|
} else {
|
||||||
|
Preferences.backgroundCardColor =
|
||||||
|
"#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||||
|
}
|
||||||
},
|
},
|
||||||
showAlphaSelector = true,
|
showAlphaSelector = true,
|
||||||
alpha = Preferences.backgroundCardAlpha.toIntValue(),
|
alpha = if (activity?.isDarkTheme() == true) Preferences.backgroundCardAlphaDark.toIntValue() else Preferences.backgroundCardAlpha.toIntValue(),
|
||||||
onAlphaChangeListener = { alpha ->
|
onAlphaChangeListener = { alpha ->
|
||||||
|
if (activity?.isDarkTheme() == true) {
|
||||||
|
Preferences.backgroundCardAlphaDark = alpha.toHexValue()
|
||||||
|
} else {
|
||||||
Preferences.backgroundCardAlpha = alpha.toHexValue()
|
Preferences.backgroundCardAlpha = alpha.toHexValue()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
action_text_shadow.setOnClickListener {
|
action_text_shadow.setOnClickListener {
|
||||||
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.title_text_shadow)).setSelectedValue(Preferences.textShadow)
|
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.title_text_shadow)).setSelectedValue(if (activity?.isDarkTheme() == true) Preferences.textShadowDark else Preferences.textShadow)
|
||||||
(2 downTo 0).forEach {
|
(2 downTo 0).forEach {
|
||||||
dialog.addItem(getString(SettingsStringHelper.getTextShadowString(it)), it)
|
dialog.addItem(getString(SettingsStringHelper.getTextShadowString(it)), it)
|
||||||
}
|
}
|
||||||
dialog.addOnSelectItemListener { value ->
|
dialog.addOnSelectItemListener { value ->
|
||||||
|
if (activity?.isDarkTheme() == true) {
|
||||||
|
Preferences.textShadowDark = value
|
||||||
|
} else {
|
||||||
Preferences.textShadow = value
|
Preferences.textShadow = value
|
||||||
|
}
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
action_custom_font.setOnClickListener {
|
action_custom_font.setOnClickListener {
|
||||||
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_custom_font_title)).setSelectedValue(Preferences.customFont)
|
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_custom_font_title)).setSelectedValue(Preferences.customFont)
|
||||||
(0..1).forEach {
|
dialog.addItem(SettingsStringHelper.getCustomFontLabel(requireContext(), 0), 0)
|
||||||
dialog.addItem(getString(SettingsStringHelper.getCustomFontLabel(it)), it)
|
|
||||||
|
if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) {
|
||||||
|
dialog.addItem(SettingsStringHelper.getCustomFontLabel(requireContext(), Constants.CUSTOM_FONT_GOOGLE_SANS), Constants.CUSTOM_FONT_GOOGLE_SANS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Preferences.customFontFile != "") {
|
||||||
|
dialog.addItem(SettingsStringHelper.getCustomFontLabel(requireContext(), Preferences.customFont), Constants.CUSTOM_FONT_DOWNLOADED)
|
||||||
|
}
|
||||||
|
dialog.addItem(getString(R.string.action_custom_font_to_search), Constants.CUSTOM_FONT_DOWNLOAD_NEW)
|
||||||
dialog.addOnSelectItemListener { value ->
|
dialog.addOnSelectItemListener { value ->
|
||||||
Preferences.customFont = value
|
if (value == Constants.CUSTOM_FONT_DOWNLOAD_NEW) {
|
||||||
}.show()
|
startActivityForResult(
|
||||||
|
Intent(requireContext(), CustomFontActivity::class.java),
|
||||||
/*
|
RequestCode.CUSTOM_FONT_CHOOSER_REQUEST_CODE.code
|
||||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
)
|
||||||
intent.type = "* / *" TO FIX WITHOUT SPACE
|
} else if (value != Constants.CUSTOM_FONT_DOWNLOADED) {
|
||||||
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
Preferences.bulk {
|
||||||
|
customFont = value
|
||||||
try {
|
customFontFile = ""
|
||||||
startActivityForResult(Intent.createChooser(intent, "Select a File to Upload"), Constants.CUSTOM_FONT_CHOOSER_REQUEST_CODE)
|
customFontName = ""
|
||||||
} catch (ex: android.content.ActivityNotFoundException) {
|
customFontVariant = ""
|
||||||
Toast.makeText(this, "Please install a File Manager.", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
}
|
||||||
*/
|
}
|
||||||
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
action_show_dividers.setOnClickListener {
|
action_show_dividers.setOnClickListener {
|
||||||
@ -320,25 +524,6 @@ class GeneralTabFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
|
||||||
when (requestCode) {
|
|
||||||
RequestCode.CUSTOM_FONT_CHOOSER_REQUEST_CODE.code -> {
|
|
||||||
/*val uri = data.data
|
|
||||||
Log.d("AW", "File Uri: " + uri.toString())
|
|
||||||
val path = Util.getPath(this, uri)
|
|
||||||
Log.d("AW", "File Path: " + path)
|
|
||||||
SP.edit()
|
|
||||||
.putString(Constants.PREF_CUSTOM_FONT_FILE, path)
|
|
||||||
.commit()
|
|
||||||
sendBroadcast(Intent(Constants.ACTION_TIME_UPDATE))
|
|
||||||
updateSettings()*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun maintainScrollPosition(callback: () -> Unit) {
|
private fun maintainScrollPosition(callback: () -> Unit) {
|
||||||
scrollView.isScrollable = false
|
scrollView.isScrollable = false
|
||||||
callback.invoke()
|
callback.invoke()
|
||||||
|
@ -7,49 +7,51 @@ import android.content.BroadcastReceiver
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.content.pm.PackageManager
|
import android.graphics.Canvas
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
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 android.widget.ImageView
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
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.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
||||||
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
||||||
import com.google.android.gms.auth.api.signin.GoogleSignInOptions
|
|
||||||
import com.google.android.gms.common.api.ApiException
|
import com.google.android.gms.common.api.ApiException
|
||||||
import com.karumi.dexter.Dexter
|
import com.google.android.material.card.MaterialCardView
|
||||||
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.components.BottomSheetMenu
|
|
||||||
import com.tommasoberlose.anotherwidget.components.CustomNotesDialog
|
import com.tommasoberlose.anotherwidget.components.CustomNotesDialog
|
||||||
import com.tommasoberlose.anotherwidget.components.GlanceProviderSortMenu
|
import com.tommasoberlose.anotherwidget.components.GlanceSettingsDialog
|
||||||
import com.tommasoberlose.anotherwidget.databinding.FragmentGlanceSettingsBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentGlanceSettingsBinding
|
||||||
|
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.AlarmHelper
|
import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
|
||||||
|
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.receivers.ActivityDetectionReceiver
|
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
|
||||||
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver.Companion.FITNESS_OPTIONS
|
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.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkIfFitInstalled
|
import com.tommasoberlose.anotherwidget.utils.convertDpToPixel
|
||||||
import com.tommasoberlose.anotherwidget.utils.toast
|
|
||||||
import kotlinx.android.synthetic.main.fragment_calendar_settings.*
|
|
||||||
import kotlinx.android.synthetic.main.fragment_glance_settings.*
|
import kotlinx.android.synthetic.main.fragment_glance_settings.*
|
||||||
import kotlinx.android.synthetic.main.fragment_glance_settings.scrollView
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class GlanceTabFragment : Fragment() {
|
class GlanceTabFragment : Fragment() {
|
||||||
@ -58,6 +60,8 @@ class GlanceTabFragment : Fragment() {
|
|||||||
fun newInstance() = GlanceTabFragment()
|
fun newInstance() = GlanceTabFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var dialog: GlanceSettingsDialog? = null
|
||||||
|
private lateinit var adapter: SlimAdapter
|
||||||
private lateinit var viewModel: MainViewModel
|
private lateinit var viewModel: MainViewModel
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@ -66,11 +70,14 @@ class GlanceTabFragment : Fragment() {
|
|||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?,
|
||||||
): View {
|
): View {
|
||||||
|
|
||||||
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
||||||
val binding = DataBindingUtil.inflate<FragmentGlanceSettingsBinding>(inflater, R.layout.fragment_glance_settings, container, false)
|
val binding = DataBindingUtil.inflate<FragmentGlanceSettingsBinding>(inflater,
|
||||||
|
R.layout.fragment_glance_settings,
|
||||||
|
container,
|
||||||
|
false)
|
||||||
|
|
||||||
subscribeUi(binding, viewModel)
|
subscribeUi(binding, viewModel)
|
||||||
|
|
||||||
@ -83,60 +90,247 @@ class GlanceTabFragment : Fragment() {
|
|||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
super.onActivityCreated(savedInstanceState)
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
action_show_steps.isVisible = requireContext().checkIfFitInstalled()
|
// List
|
||||||
|
providers_list.setHasFixedSize(true)
|
||||||
|
val mLayoutManager = LinearLayoutManager(context)
|
||||||
|
providers_list.layoutManager = mLayoutManager
|
||||||
|
|
||||||
|
adapter = SlimAdapter.create()
|
||||||
|
adapter
|
||||||
|
.register<GlanceProvider>(R.layout.glance_provider_item) { item, injector ->
|
||||||
|
val provider = Constants.GlanceProviderId.from(item.id)!!
|
||||||
|
injector
|
||||||
|
.text(R.id.title, item.title)
|
||||||
|
.with<ImageView>(R.id.icon) {
|
||||||
|
it.setImageDrawable(ContextCompat.getDrawable(requireContext(), item.icon))
|
||||||
|
}
|
||||||
|
.clicked(R.id.item) {
|
||||||
|
if (Preferences.showGlance) {
|
||||||
|
if (provider == Constants.GlanceProviderId.CUSTOM_INFO) {
|
||||||
|
CustomNotesDialog(requireContext()).show()
|
||||||
|
} else {
|
||||||
|
dialog = GlanceSettingsDialog(requireActivity(), provider) {
|
||||||
|
adapter.notifyItemRangeChanged(0, adapter.data.size)
|
||||||
|
}
|
||||||
|
dialog?.setOnDismissListener {
|
||||||
|
dialog = null
|
||||||
|
}
|
||||||
|
dialog?.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
when (provider) {
|
||||||
|
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||||
|
when {
|
||||||
|
ActiveNotificationsHelper.checkNotificationAccess(requireContext()) -> {
|
||||||
|
MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
|
||||||
|
injector.visibility(R.id.error_icon, View.GONE)
|
||||||
|
injector.visibility(R.id.info_icon, View.VISIBLE)
|
||||||
|
injector.text(R.id.label,
|
||||||
|
if (Preferences.showMusic) getString(R.string.settings_visible) else getString(
|
||||||
|
R.string.settings_not_visible))
|
||||||
|
}
|
||||||
|
Preferences.showMusic -> {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
injector.visibility(R.id.error_icon, View.GONE)
|
||||||
|
injector.visibility(R.id.info_icon, View.VISIBLE)
|
||||||
|
injector.text(R.id.label, getString(R.string.settings_not_visible))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
||||||
|
injector.text(R.id.label,
|
||||||
|
if (Preferences.showNextAlarm && !AlarmHelper.isAlarmProbablyWrong(
|
||||||
|
requireContext())
|
||||||
|
) getString(R.string.settings_visible) else getString(
|
||||||
|
R.string.settings_not_visible))
|
||||||
|
injector.visibility(R.id.error_icon,
|
||||||
|
if (Preferences.showNextAlarm && AlarmHelper.isAlarmProbablyWrong(
|
||||||
|
requireContext())
|
||||||
|
) View.VISIBLE else View.GONE)
|
||||||
|
injector.visibility(R.id.info_icon,
|
||||||
|
if (!(Preferences.showNextAlarm && AlarmHelper.isAlarmProbablyWrong(
|
||||||
|
requireContext()))
|
||||||
|
) View.VISIBLE else View.GONE)
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
||||||
|
injector.text(R.id.label,
|
||||||
|
if (Preferences.showBatteryCharging) 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)
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.NOTIFICATIONS -> {
|
||||||
|
when {
|
||||||
|
ActiveNotificationsHelper.checkNotificationAccess(requireContext()) -> {
|
||||||
|
injector.visibility(R.id.error_icon, View.GONE)
|
||||||
|
injector.visibility(R.id.info_icon, View.VISIBLE)
|
||||||
|
injector.text(R.id.label,
|
||||||
|
if (Preferences.showNotifications) getString(
|
||||||
|
R.string.settings_visible) else getString(R.string.settings_not_visible))
|
||||||
|
}
|
||||||
|
Preferences.showNotifications -> {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
injector.visibility(R.id.error_icon, View.GONE)
|
||||||
|
injector.visibility(R.id.info_icon, View.VISIBLE)
|
||||||
|
injector.text(R.id.label, getString(R.string.settings_not_visible))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.GREETINGS -> {
|
||||||
|
injector.text(R.id.label,
|
||||||
|
if (Preferences.showGreetings) 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)
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
||||||
|
injector.text(R.id.label,
|
||||||
|
if (Preferences.customNotes != "") 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)
|
||||||
|
}
|
||||||
|
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 || activity?.checkGrantedPermission(
|
||||||
|
Manifest.permission.ACTIVITY_RECOGNITION) == true)
|
||||||
|
) {
|
||||||
|
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)
|
||||||
|
} 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))
|
||||||
|
} 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.attachTo(providers_list)
|
||||||
|
|
||||||
|
val mIth = ItemTouchHelper(
|
||||||
|
object : ItemTouchHelper.SimpleCallback(
|
||||||
|
ItemTouchHelper.UP or ItemTouchHelper.DOWN,
|
||||||
|
0
|
||||||
|
) {
|
||||||
|
|
||||||
|
val list = GlanceProviderHelper.getGlanceProviders(requireContext())
|
||||||
|
|
||||||
|
override fun onMove(
|
||||||
|
recyclerView: RecyclerView,
|
||||||
|
viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder,
|
||||||
|
): Boolean {
|
||||||
|
val fromPos = viewHolder.adapterPosition
|
||||||
|
val toPos = target.adapterPosition
|
||||||
|
// move item in `fromPos` to `toPos` in adapter.
|
||||||
|
adapter.notifyItemMoved(fromPos, toPos)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isItemViewSwipeEnabled(): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMoved(
|
||||||
|
recyclerView: RecyclerView,
|
||||||
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
|
fromPos: Int,
|
||||||
|
target: RecyclerView.ViewHolder,
|
||||||
|
toPos: Int,
|
||||||
|
x: Int,
|
||||||
|
y: Int
|
||||||
|
) {
|
||||||
|
with(list[fromPos]) {
|
||||||
|
list[fromPos] = list[toPos]
|
||||||
|
list[toPos] = this
|
||||||
|
}
|
||||||
|
GlanceProviderHelper.saveGlanceProviderOrder(list)
|
||||||
|
super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onChildDraw(
|
||||||
|
c: Canvas,
|
||||||
|
recyclerView: RecyclerView,
|
||||||
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
|
dX: Float,
|
||||||
|
dY: Float,
|
||||||
|
actionState: Int,
|
||||||
|
isCurrentlyActive: Boolean,
|
||||||
|
) {
|
||||||
|
val view = viewHolder.itemView as MaterialCardView
|
||||||
|
if (isCurrentlyActive) {
|
||||||
|
ViewCompat.setElevation(view, 2f.convertDpToPixel(requireContext()))
|
||||||
|
view.setCardBackgroundColor(ContextCompat.getColor(requireContext(),
|
||||||
|
R.color.colorPrimary))
|
||||||
|
} else {
|
||||||
|
ViewCompat.setElevation(view, 0f)
|
||||||
|
view.setCardBackgroundColor(ContextCompat.getColor(requireContext(),
|
||||||
|
R.color.colorPrimaryDark))
|
||||||
|
}
|
||||||
|
|
||||||
|
val topEdge = if ((view.top == 0 && dY < 0) || ((view.top + view.height >= recyclerView.height - 32f.convertDpToPixel(requireContext())) && dY > 0)) 0f else dY
|
||||||
|
|
||||||
|
super.onChildDraw(c,
|
||||||
|
recyclerView,
|
||||||
|
viewHolder,
|
||||||
|
dX,
|
||||||
|
topEdge,
|
||||||
|
actionState,
|
||||||
|
isCurrentlyActive)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSwiped(
|
||||||
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
|
direction: Int,
|
||||||
|
) {
|
||||||
|
// remove from adapter
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
mIth.attachToRecyclerView(providers_list)
|
||||||
|
adapter.updateData(
|
||||||
|
GlanceProviderHelper.getGlanceProviders(requireContext())
|
||||||
|
.mapNotNull { GlanceProviderHelper.getGlanceProviderById(requireContext(), it) }
|
||||||
|
)
|
||||||
|
providers_list.isNestedScrollingEnabled = false
|
||||||
|
|
||||||
setupListener()
|
setupListener()
|
||||||
updateNextAlarmWarningUi()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun subscribeUi(
|
private fun subscribeUi(
|
||||||
binding: FragmentGlanceSettingsBinding,
|
binding: FragmentGlanceSettingsBinding,
|
||||||
viewModel: MainViewModel
|
viewModel: MainViewModel,
|
||||||
) {
|
) {
|
||||||
binding.isGlanceVisible = Preferences.showGlance
|
binding.isGlanceVisible = Preferences.showGlance
|
||||||
|
|
||||||
viewModel.showGlance.observe(viewLifecycleOwner, Observer {
|
viewModel.showGlance.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.isGlanceVisible = it
|
binding.isGlanceVisible = it
|
||||||
show_glance_label.text = if (it) getString(R.string.description_show_glance_visible) else getString(R.string.description_show_glance_not_visible)
|
show_glance_label.text =
|
||||||
|
if (it) getString(R.string.description_show_glance_visible) else getString(
|
||||||
|
R.string.description_show_glance_not_visible)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.showMusic.observe(viewLifecycleOwner, Observer {
|
|
||||||
maintainScrollPosition {
|
|
||||||
checkNotificationPermission()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
viewModel.showNextAlarm.observe(viewLifecycleOwner, Observer {
|
|
||||||
maintainScrollPosition {
|
|
||||||
updateNextAlarmWarningUi()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
viewModel.showBatteryCharging.observe(viewLifecycleOwner, Observer {
|
|
||||||
maintainScrollPosition {
|
|
||||||
show_low_battery_level_warning_label?.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
viewModel.showDailySteps.observe(viewLifecycleOwner, Observer {
|
|
||||||
maintainScrollPosition {
|
|
||||||
show_steps_label?.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
|
||||||
}
|
|
||||||
checkFitnessPermission()
|
|
||||||
})
|
|
||||||
|
|
||||||
viewModel.customInfo.observe(viewLifecycleOwner, Observer {
|
|
||||||
maintainScrollPosition {
|
|
||||||
show_custom_notes_label?.text = if (it == "") getString(R.string.settings_not_visible) else it
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
|
|
||||||
action_show_glance.setOnClickListener {
|
action_show_glance.setOnClickListener {
|
||||||
Preferences.showGlance = !Preferences.showGlance
|
Preferences.showGlance = !Preferences.showGlance
|
||||||
}
|
}
|
||||||
@ -144,128 +338,21 @@ class GlanceTabFragment : Fragment() {
|
|||||||
show_glance_switch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
show_glance_switch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
||||||
Preferences.showGlance = enabled
|
Preferences.showGlance = enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
action_sort_glance_providers.setOnClickListener {
|
|
||||||
GlanceProviderSortMenu(requireContext())
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
action_show_music.setOnClickListener {
|
|
||||||
if (Preferences.showGlance) {
|
|
||||||
BottomSheetMenu<Boolean>(
|
|
||||||
requireContext(),
|
|
||||||
header = getString(R.string.settings_show_music_title)
|
|
||||||
).setSelectedValue(Preferences.showMusic)
|
|
||||||
.addItem(getString(R.string.settings_visible), true)
|
|
||||||
.addItem(getString(R.string.settings_not_visible), false)
|
|
||||||
.addOnSelectItemListener { value ->
|
|
||||||
Preferences.showMusic = value
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
action_show_next_alarm.setOnClickListener {
|
|
||||||
if (Preferences.showGlance) {
|
|
||||||
BottomSheetMenu<Boolean>(
|
|
||||||
requireContext(),
|
|
||||||
header = getString(R.string.settings_show_next_alarm_title)
|
|
||||||
).setSelectedValue(Preferences.showNextAlarm)
|
|
||||||
.addItem(getString(R.string.settings_visible), true)
|
|
||||||
.addItem(getString(R.string.settings_not_visible), false)
|
|
||||||
.addOnSelectItemListener { value ->
|
|
||||||
Preferences.showNextAlarm = value
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
action_show_next_alarm.setOnLongClickListener {
|
|
||||||
with(requireContext().getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
|
||||||
val alarm = nextAlarmClock
|
|
||||||
if (alarm != null && alarm.showIntent != null) {
|
|
||||||
val pm = requireContext().packageManager as PackageManager
|
|
||||||
val appNameOrPackage = try {
|
|
||||||
pm.getApplicationLabel(pm.getApplicationInfo(alarm.showIntent?.creatorPackage ?: "", 0))
|
|
||||||
} catch (e: Exception) {
|
|
||||||
alarm.showIntent?.creatorPackage ?: ""
|
|
||||||
}
|
|
||||||
activity?.toast(getString(R.string.next_alarm_warning).format(appNameOrPackage), long = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
action_show_low_battery_level_warning.setOnClickListener {
|
|
||||||
if (Preferences.showGlance) {
|
|
||||||
BottomSheetMenu<Boolean>(
|
|
||||||
requireContext(),
|
|
||||||
header = getString(R.string.settings_low_battery_level_title)
|
|
||||||
).setSelectedValue(Preferences.showBatteryCharging)
|
|
||||||
.addItem(getString(R.string.settings_visible), true)
|
|
||||||
.addItem(getString(R.string.settings_not_visible), false)
|
|
||||||
.addOnSelectItemListener { value ->
|
|
||||||
Preferences.showBatteryCharging = value
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
action_show_steps.setOnClickListener {
|
|
||||||
if (Preferences.showGlance) {
|
|
||||||
BottomSheetMenu<Boolean>(
|
|
||||||
requireContext(),
|
|
||||||
header = getString(R.string.settings_daily_steps_title)
|
|
||||||
).setSelectedValue(Preferences.showDailySteps)
|
|
||||||
.addItem(getString(R.string.settings_visible), true)
|
|
||||||
.addItem(getString(R.string.settings_not_visible), false)
|
|
||||||
.addOnSelectItemListener { value ->
|
|
||||||
if (value) {
|
|
||||||
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(requireContext())
|
|
||||||
if (!GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
|
|
||||||
val mGoogleSignInClient = GoogleSignIn.getClient(requireActivity(), GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).addExtension(FITNESS_OPTIONS).build())
|
|
||||||
startActivityForResult(mGoogleSignInClient.signInIntent, 2)
|
|
||||||
} else {
|
|
||||||
Preferences.showDailySteps = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Preferences.showDailySteps = false
|
|
||||||
}
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
action_show_custom_notes.setOnClickListener {
|
|
||||||
if (Preferences.showGlance) {
|
|
||||||
CustomNotesDialog(requireContext()).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateNextAlarmWarningUi() {
|
|
||||||
with(requireContext().getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
|
||||||
val alarm = nextAlarmClock
|
|
||||||
if (AlarmHelper.isAlarmProbablyWrong(requireContext()) && alarm != null && alarm.showIntent != null) {
|
|
||||||
val pm = requireContext().packageManager as PackageManager
|
|
||||||
val appNameOrPackage = try {
|
|
||||||
pm.getApplicationLabel(pm.getApplicationInfo(alarm.showIntent?.creatorPackage ?: "", 0))
|
|
||||||
} catch (e: Exception) {
|
|
||||||
alarm.showIntent?.creatorPackage ?: ""
|
|
||||||
}
|
|
||||||
show_next_alarm_warning.text = getString(R.string.next_alarm_warning).format(appNameOrPackage)
|
|
||||||
} else {
|
|
||||||
show_next_alarm_label?.text = if (Preferences.showNextAlarm) getString(R.string.settings_visible) else getString(
|
|
||||||
R.string.settings_not_visible)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val nextAlarmChangeBroadcastReceiver = object : BroadcastReceiver() {
|
private val nextAlarmChangeBroadcastReceiver = object : BroadcastReceiver() {
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
updateNextAlarmWarningUi()
|
adapter.notifyItemRangeChanged(0, adapter.data.size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
activity?.registerReceiver(nextAlarmChangeBroadcastReceiver, IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED))
|
activity?.registerReceiver(nextAlarmChangeBroadcastReceiver,
|
||||||
|
IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED))
|
||||||
|
if (dialog != null) {
|
||||||
|
dialog?.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
@ -273,62 +360,27 @@ class GlanceTabFragment : Fragment() {
|
|||||||
super.onStop()
|
super.onStop()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkNotificationPermission() {
|
|
||||||
if (NotificationManagerCompat.getEnabledListenerPackages(requireContext()).contains(requireContext().packageName)) {
|
|
||||||
notification_permission_alert?.isVisible = false
|
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
|
|
||||||
show_music_label?.text = if (Preferences.showMusic) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
|
||||||
} else if (Preferences.showMusic) {
|
|
||||||
notification_permission_alert?.isVisible = true
|
|
||||||
show_music_label?.text = getString(R.string.settings_request_notification_access)
|
|
||||||
notification_permission_alert?.setOnClickListener {
|
|
||||||
activity?.startActivity(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
show_music_label?.text = getString(R.string.settings_not_visible)
|
|
||||||
notification_permission_alert?.isVisible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkFitnessPermission() {
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || activity?.checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION) == true) {
|
|
||||||
fitness_permission_alert?.isVisible = false
|
|
||||||
if (Preferences.showDailySteps) {
|
|
||||||
ActivityDetectionReceiver.registerFence(requireContext())
|
|
||||||
} else {
|
|
||||||
ActivityDetectionReceiver.unregisterFence(requireContext())
|
|
||||||
}
|
|
||||||
show_steps_label?.text = if (Preferences.showDailySteps) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
|
||||||
} else if (Preferences.showDailySteps) {
|
|
||||||
ActivityDetectionReceiver.unregisterFence(requireContext())
|
|
||||||
fitness_permission_alert?.isVisible = true
|
|
||||||
show_steps_label?.text = getString(R.string.settings_request_fitness_access)
|
|
||||||
fitness_permission_alert?.setOnClickListener {
|
|
||||||
requireFitnessPermission()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ActivityDetectionReceiver.unregisterFence(requireContext())
|
|
||||||
show_steps_label?.text = getString(R.string.settings_not_visible)
|
|
||||||
fitness_permission_alert?.isVisible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityResult(
|
override fun onActivityResult(
|
||||||
requestCode: Int,
|
requestCode: Int,
|
||||||
resultCode: Int,
|
resultCode: Int,
|
||||||
data: Intent?
|
data: Intent?,
|
||||||
) {
|
) {
|
||||||
when (requestCode) {
|
when (requestCode) {
|
||||||
1 -> {
|
1 -> {
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
checkFitnessPermission()
|
adapter.notifyItemRangeChanged(0, adapter.data.size)
|
||||||
} else {
|
} else {
|
||||||
Preferences.showDailySteps = false
|
Preferences.showDailySteps = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dialog != null) {
|
||||||
|
dialog?.show()
|
||||||
}
|
}
|
||||||
2-> {
|
}
|
||||||
|
2 -> {
|
||||||
try {
|
try {
|
||||||
val account: GoogleSignInAccount? = GoogleSignIn.getSignedInAccountFromIntent(data).getResult(ApiException::class.java)
|
val account: GoogleSignInAccount? = GoogleSignIn.getSignedInAccountFromIntent(
|
||||||
|
data).getResult(ApiException::class.java)
|
||||||
if (!GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
|
if (!GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
|
||||||
GoogleSignIn.requestPermissions(
|
GoogleSignIn.requestPermissions(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
@ -336,40 +388,18 @@ class GlanceTabFragment : Fragment() {
|
|||||||
account,
|
account,
|
||||||
FITNESS_OPTIONS)
|
FITNESS_OPTIONS)
|
||||||
} else {
|
} else {
|
||||||
checkFitnessPermission()
|
adapter.notifyItemRangeChanged(0, adapter.data.size)
|
||||||
}
|
}
|
||||||
} catch (e: ApiException) {
|
} catch (e: ApiException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
Preferences.showDailySteps = false
|
Preferences.showDailySteps = false
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun requireFitnessPermission() {
|
if (dialog != null) {
|
||||||
Dexter.withContext(requireContext())
|
dialog?.show()
|
||||||
.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?) {
|
|
||||||
report?.let {
|
|
||||||
if (report.areAllPermissionsGranted()){
|
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun maintainScrollPosition(callback: () -> Unit) {
|
private fun maintainScrollPosition(callback: () -> Unit) {
|
||||||
@ -383,6 +413,9 @@ class GlanceTabFragment : Fragment() {
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
checkNotificationPermission()
|
adapter.notifyItemRangeChanged(0, adapter.data.size)
|
||||||
|
if (dialog != null) {
|
||||||
|
dialog?.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,6 @@ package com.tommasoberlose.anotherwidget.ui.fragments
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.appwidget.AppWidgetManager
|
|
||||||
import android.appwidget.AppWidgetProviderInfo
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
@ -11,7 +9,6 @@ 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.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -33,16 +30,14 @@ import com.tommasoberlose.anotherwidget.R
|
|||||||
import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
|
import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
|
||||||
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.BitmapHelper
|
import com.tommasoberlose.anotherwidget.helpers.*
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter
|
import com.tommasoberlose.anotherwidget.ui.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.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.*
|
||||||
import com.tommasoberlose.anotherwidget.utils.getCurrentWallpaper
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
|
||||||
import kotlinx.android.synthetic.main.fragment_app_main.*
|
import kotlinx.android.synthetic.main.fragment_app_main.*
|
||||||
import kotlinx.android.synthetic.main.the_widget_sans.*
|
import kotlinx.android.synthetic.main.the_widget_sans.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
@ -62,8 +57,8 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
enterTransition = MaterialSharedAxis.create(MaterialSharedAxis.X, true)
|
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||||
reenterTransition = MaterialSharedAxis.create(MaterialSharedAxis.X, false)
|
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
@ -76,7 +71,6 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
super.onActivityCreated(savedInstanceState)
|
super.onActivityCreated(savedInstanceState)
|
||||||
subscribeUi(viewModel)
|
|
||||||
|
|
||||||
// Viewpager
|
// Viewpager
|
||||||
pager.adapter = ViewPagerAdapter(requireActivity())
|
pager.adapter = ViewPagerAdapter(requireActivity())
|
||||||
@ -93,17 +87,20 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
}.attach()
|
}.attach()
|
||||||
|
|
||||||
// Init clock
|
// Init clock
|
||||||
time.setTextColor(ColorHelper.getClockFontColor())
|
if (Preferences.showClock) {
|
||||||
time.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(requireContext()))
|
time.setTextColor(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true))
|
||||||
time_am_pm.setTextColor(ColorHelper.getClockFontColor())
|
time.setTextSize(TypedValue.COMPLEX_UNIT_SP,
|
||||||
time_am_pm.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2)
|
Preferences.clockTextSize.toPixel(requireContext()))
|
||||||
|
time_am_pm.setTextColor(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true))
|
||||||
|
time_am_pm.setTextSize(TypedValue.COMPLEX_UNIT_SP,
|
||||||
|
Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2)
|
||||||
|
}
|
||||||
time_container.isVisible = Preferences.showClock
|
time_container.isVisible = Preferences.showClock
|
||||||
|
|
||||||
preview.layoutParams = preview.layoutParams.apply {
|
preview.layoutParams = preview.layoutParams.apply {
|
||||||
height = PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(requireContext()) else 0
|
height = PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(requireContext()) else 0
|
||||||
}
|
}
|
||||||
subscribeUi(viewModel)
|
subscribeUi(viewModel)
|
||||||
updateUI()
|
|
||||||
|
|
||||||
// Warnings
|
// Warnings
|
||||||
if (getString(R.string.xiaomi_manufacturer).equals(Build.MANUFACTURER, ignoreCase = true) && Preferences.showXiaomiWarning) {
|
if (getString(R.string.xiaomi_manufacturer).equals(Build.MANUFACTURER, ignoreCase = true) && Preferences.showXiaomiWarning) {
|
||||||
@ -134,7 +131,7 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
preview?.setCardBackgroundColor(
|
preview?.setCardBackgroundColor(
|
||||||
ContextCompat.getColor(
|
ContextCompat.getColor(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
if (ColorHelper.getFontColor()
|
if (ColorHelper.getFontColor(activity?.isDarkTheme() == true)
|
||||||
.isColorDark()
|
.isColorDark()
|
||||||
) android.R.color.white else R.color.colorAccent
|
) android.R.color.white else R.color.colorAccent
|
||||||
)
|
)
|
||||||
@ -143,11 +140,12 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
BitmapHelper.getTintedDrawable(
|
BitmapHelper.getTintedDrawable(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
R.drawable.card_background,
|
R.drawable.card_background,
|
||||||
ColorHelper.getBackgroundColor()
|
ColorHelper.getBackgroundColor(activity?.isDarkTheme() == true)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
WidgetHelper.runWithCustomTypeface(requireContext()) { typeface ->
|
||||||
uiJob = lifecycleScope.launch(Dispatchers.IO) {
|
uiJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||||
val generatedView = MainWidget.generateWidgetView(requireContext())
|
val generatedView = MainWidget.generateWidgetView(requireContext(), typeface)
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
generatedView.measure(0, 0)
|
generatedView.measure(0, 0)
|
||||||
@ -165,8 +163,8 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
// Clock
|
// Clock
|
||||||
time?.setTextColor(ColorHelper.getClockFontColor())
|
time?.setTextColor(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true))
|
||||||
time_am_pm?.setTextColor(ColorHelper.getClockFontColor())
|
time_am_pm?.setTextColor(ColorHelper.getClockFontColor(activity?.isDarkTheme() == true))
|
||||||
time?.setTextSize(
|
time?.setTextSize(
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
Preferences.clockTextSize.toPixel(requireContext())
|
Preferences.clockTextSize.toPixel(requireContext())
|
||||||
@ -266,7 +264,8 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
}.start()
|
}.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
widget_loader?.animate()?.scaleX(0f)?.scaleY(0f)?.alpha(0f)?.setDuration(200L)?.start()
|
widget_loader?.animate()?.scaleX(0f)?.scaleY(0f)?.alpha(0f)
|
||||||
|
?.setDuration(200L)?.start()
|
||||||
bitmap_container?.apply {
|
bitmap_container?.apply {
|
||||||
setImageBitmap(bitmap)
|
setImageBitmap(bitmap)
|
||||||
scaleX = 0.9f
|
scaleX = 0.9f
|
||||||
@ -275,6 +274,7 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
widget?.animate()?.alpha(1f)?.start()
|
widget?.animate()?.alpha(1f)?.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (preview != null) {
|
if (preview != null) {
|
||||||
ValueAnimator.ofInt(
|
ValueAnimator.ofInt(
|
||||||
@ -348,14 +348,24 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
tabs?.getTabAt(2)?.orCreateBadge?.apply {
|
tabs?.getTabAt(2)?.orCreateBadge?.apply {
|
||||||
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
||||||
badgeGravity = BadgeDrawable.TOP_END
|
badgeGravity = BadgeDrawable.TOP_END
|
||||||
}?.isVisible = Preferences.showWeather && (Preferences.weatherProviderApi == "" || (Preferences.customLocationAdd == "" && activity?.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION) != true))
|
}?.isVisible = if (Preferences.showWeather) {
|
||||||
|
(WeatherHelper.isKeyRequired() && WeatherHelper.getApiKey() == "")
|
||||||
|
|| (Preferences.customLocationAdd == "" && activity?.checkGrantedPermission(
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
|
||||||
|
) != true)
|
||||||
|
|| (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-")
|
||||||
|
|| (Preferences.weatherProviderLocationError != "")
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Glance error indicator
|
||||||
// Music error indicator
|
|
||||||
tabs?.getTabAt(4)?.orCreateBadge?.apply {
|
tabs?.getTabAt(4)?.orCreateBadge?.apply {
|
||||||
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
||||||
badgeGravity = BadgeDrawable.TOP_END
|
badgeGravity = BadgeDrawable.TOP_END
|
||||||
}?.isVisible = Preferences.showMusic && !NotificationManagerCompat.getEnabledListenerPackages(requireContext()).contains(requireContext().packageName)
|
}?.isVisible = ((Preferences.showMusic || Preferences.showNotifications) && !ActiveNotificationsHelper.checkNotificationAccess(requireContext())) ||
|
||||||
|
(Preferences.showDailySteps && !(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || requireActivity().checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION))) ||
|
||||||
|
(AlarmHelper.isAlarmProbablyWrong(requireContext()))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
@ -372,7 +382,7 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
|||||||
super.onPause()
|
super.onPause()
|
||||||
}
|
}
|
||||||
|
|
||||||
var delayJob: Job? = null
|
private var delayJob: Job? = null
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(preferences: SharedPreferences, p1: String) {
|
override fun onSharedPreferenceChanged(preferences: SharedPreferences, p1: String) {
|
||||||
delayJob?.cancel()
|
delayJob?.cancel()
|
||||||
|
@ -26,6 +26,7 @@ import com.tommasoberlose.anotherwidget.R
|
|||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||||
import com.tommasoberlose.anotherwidget.databinding.FragmentSettingsBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentSettingsBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.SupportDevActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.SupportDevActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
@ -50,8 +51,8 @@ class SettingsFragment : Fragment() {
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
enterTransition = MaterialSharedAxis.create(MaterialSharedAxis.X, true)
|
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
|
||||||
returnTransition = MaterialSharedAxis.create(MaterialSharedAxis.X, false)
|
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
@ -131,9 +132,6 @@ class SettingsFragment : Fragment() {
|
|||||||
Preferences.showPreview = isChecked
|
Preferences.showPreview = isChecked
|
||||||
}
|
}
|
||||||
|
|
||||||
action_show_wallpaper.setOnClickListener {
|
|
||||||
}
|
|
||||||
|
|
||||||
action_show_wallpaper.setOnClickListener {
|
action_show_wallpaper.setOnClickListener {
|
||||||
show_wallpaper_toggle.isChecked = !show_wallpaper_toggle.isChecked
|
show_wallpaper_toggle.isChecked = !show_wallpaper_toggle.isChecked
|
||||||
}
|
}
|
||||||
@ -184,14 +182,21 @@ class SettingsFragment : Fragment() {
|
|||||||
activity?.openURI("https://github.com/tommasoberlose/another-widget/issues")
|
activity?.openURI("https://github.com/tommasoberlose/another-widget/issues")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action_privacy_policy.setOnClickListener {
|
||||||
|
activity?.openURI("https://github.com/tommasoberlose/another-widget/blob/master/privacy-policy.md")
|
||||||
|
}
|
||||||
|
|
||||||
action_help_dev.setOnClickListener {
|
action_help_dev.setOnClickListener {
|
||||||
startActivity(Intent(requireContext(), SupportDevActivity::class.java))
|
startActivity(Intent(requireContext(), SupportDevActivity::class.java))
|
||||||
}
|
}
|
||||||
|
|
||||||
action_refresh_widget.setOnClickListener {
|
action_refresh_widget.setOnClickListener {
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
WeatherHelper.updateWeather(requireContext())
|
WeatherHelper.updateWeather(requireContext())
|
||||||
|
}
|
||||||
CalendarHelper.updateEventList(requireContext())
|
CalendarHelper.updateEventList(requireContext())
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
|
MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
|
||||||
|
ActiveNotificationsHelper.clearLastNotification(requireContext())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import com.karumi.dexter.listener.multi.MultiplePermissionsListener
|
|||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||||
import com.tommasoberlose.anotherwidget.components.IconPackSelector
|
import com.tommasoberlose.anotherwidget.components.IconPackSelector
|
||||||
|
import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
|
||||||
import com.tommasoberlose.anotherwidget.databinding.FragmentWeatherSettingsBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentWeatherSettingsBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
@ -41,6 +42,8 @@ import com.tommasoberlose.anotherwidget.ui.activities.WeatherProviderActivity
|
|||||||
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.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.collapse
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.expand
|
||||||
import kotlinx.android.synthetic.main.fragment_weather_settings.*
|
import kotlinx.android.synthetic.main.fragment_weather_settings.*
|
||||||
import kotlinx.android.synthetic.main.fragment_weather_settings.scrollView
|
import kotlinx.android.synthetic.main.fragment_weather_settings.scrollView
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@ -86,11 +89,6 @@ class WeatherTabFragment : Fragment() {
|
|||||||
) {
|
) {
|
||||||
binding.isWeatherVisible = Preferences.showWeather
|
binding.isWeatherVisible = Preferences.showWeather
|
||||||
|
|
||||||
viewModel.showWeatherWarning.observe(viewLifecycleOwner, Observer {
|
|
||||||
weather_warning?.isVisible = it
|
|
||||||
checkLocationPermission()
|
|
||||||
})
|
|
||||||
|
|
||||||
viewModel.showWeather.observe(viewLifecycleOwner, Observer {
|
viewModel.showWeather.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
show_weather_label?.text =
|
show_weather_label?.text =
|
||||||
@ -99,17 +97,27 @@ class WeatherTabFragment : Fragment() {
|
|||||||
binding.isWeatherVisible = it
|
binding.isWeatherVisible = it
|
||||||
}
|
}
|
||||||
checkLocationPermission()
|
checkLocationPermission()
|
||||||
|
checkWeatherProviderConfig()
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.weatherProviderApi.observe(viewLifecycleOwner, Observer {
|
viewModel.weatherProvider.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
|
label_weather_provider.text = WeatherHelper.getProviderName(requireContext(), Constants.WeatherProvider.fromInt(it)!!)
|
||||||
checkWeatherProviderConfig()
|
checkWeatherProviderConfig()
|
||||||
}
|
}
|
||||||
checkLocationPermission()
|
})
|
||||||
|
|
||||||
|
viewModel.weatherProviderError.observe(viewLifecycleOwner, Observer {
|
||||||
|
checkWeatherProviderConfig()
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.weatherProviderLocationError.observe(viewLifecycleOwner, Observer {
|
||||||
|
checkWeatherProviderConfig()
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.customLocationAdd.observe(viewLifecycleOwner, Observer {
|
viewModel.customLocationAdd.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
|
background_location_warning.isVisible = it == ""
|
||||||
label_custom_location?.text =
|
label_custom_location?.text =
|
||||||
if (it == "") getString(R.string.custom_location_gps) else it
|
if (it == "") getString(R.string.custom_location_gps) else it
|
||||||
}
|
}
|
||||||
@ -160,30 +168,40 @@ class WeatherTabFragment : Fragment() {
|
|||||||
|
|
||||||
if (activity?.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION) == true) {
|
if (activity?.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION) == true) {
|
||||||
location_permission_alert?.isVisible = false
|
location_permission_alert?.isVisible = false
|
||||||
|
background_location_warning.isVisible = Preferences.customLocationAdd == ""
|
||||||
WeatherReceiver.setUpdates(requireContext())
|
WeatherReceiver.setUpdates(requireContext())
|
||||||
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
|
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
|
||||||
location_permission_alert?.isVisible = true
|
location_permission_alert?.isVisible = true
|
||||||
|
background_location_warning.isVisible = true
|
||||||
location_permission_alert?.setOnClickListener {
|
location_permission_alert?.setOnClickListener {
|
||||||
|
MaterialBottomSheetDialog(requireContext(), message = getString(R.string.background_location_warning))
|
||||||
|
.setPositiveButton(getString(android.R.string.ok)) {
|
||||||
requirePermission()
|
requirePermission()
|
||||||
}
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
location_permission_alert?.isVisible = false
|
location_permission_alert?.isVisible = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkWeatherProviderConfig() {
|
private fun checkWeatherProviderConfig() {
|
||||||
label_weather_provider_api_key?.text =
|
if (Preferences.showWeather && Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-" && !location_permission_alert.isVisible) {
|
||||||
if (Preferences.weatherProviderApi == "") getString(R.string.settings_weather_provider_api_key_subtitle_not_set) else getString(
|
weather_provider_error.expand()
|
||||||
R.string.settings_weather_provider_api_key_subtitle_all_set
|
} else {
|
||||||
)
|
weather_provider_error.collapse()
|
||||||
label_weather_provider_api_key?.setTextColor(ContextCompat.getColor(requireContext(), if (Preferences.weatherProviderApi == "" && Preferences.showWeather) R.color.errorColorText else R.color.colorSecondaryText))
|
}
|
||||||
|
weather_provider_error?.text = Preferences.weatherProviderError
|
||||||
|
|
||||||
|
if (Preferences.showWeather && Preferences.weatherProviderLocationError != "" && !location_permission_alert.isVisible) {
|
||||||
|
weather_provider_location_error.expand()
|
||||||
|
} else {
|
||||||
|
weather_provider_location_error.collapse()
|
||||||
|
}
|
||||||
|
weather_provider_location_error?.text = Preferences.weatherProviderLocationError
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
action_hide_weather_warning.setOnClickListener {
|
|
||||||
Preferences.showWeatherWarning = false
|
|
||||||
}
|
|
||||||
|
|
||||||
action_show_weather.setOnClickListener {
|
action_show_weather.setOnClickListener {
|
||||||
Preferences.showWeather = !Preferences.showWeather
|
Preferences.showWeather = !Preferences.showWeather
|
||||||
}
|
}
|
||||||
@ -192,7 +210,7 @@ class WeatherTabFragment : Fragment() {
|
|||||||
Preferences.showWeather = enabled
|
Preferences.showWeather = enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
action_weather_provider_api_key.setOnClickListener {
|
action_weather_provider.setOnClickListener {
|
||||||
if (Preferences.showWeather) {
|
if (Preferences.showWeather) {
|
||||||
startActivityForResult(
|
startActivityForResult(
|
||||||
Intent(requireContext(), WeatherProviderActivity::class.java),
|
Intent(requireContext(), WeatherProviderActivity::class.java),
|
||||||
@ -216,6 +234,11 @@ class WeatherTabFragment : Fragment() {
|
|||||||
.addItem(getString(R.string.fahrenheit), "F")
|
.addItem(getString(R.string.fahrenheit), "F")
|
||||||
.addItem(getString(R.string.celsius), "C")
|
.addItem(getString(R.string.celsius), "C")
|
||||||
.addOnSelectItemListener { value ->
|
.addOnSelectItemListener { value ->
|
||||||
|
if (value != Preferences.weatherTempUnit) {
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
WeatherHelper.updateWeather(requireContext())
|
||||||
|
}
|
||||||
|
}
|
||||||
Preferences.weatherTempUnit = value
|
Preferences.weatherTempUnit = value
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
@ -266,7 +289,7 @@ class WeatherTabFragment : Fragment() {
|
|||||||
MainWidget.updateWidget(requireContext())
|
MainWidget.updateWidget(requireContext())
|
||||||
}
|
}
|
||||||
RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> {
|
RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> {
|
||||||
WeatherReceiver.setOneTimeUpdate(requireContext())
|
checkLocationPermission()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.viewmodels
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.ResolveInfo
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.chibatching.kotpref.livedata.asLiveData
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
|
||||||
|
class AppNotificationsViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
|
||||||
|
val pm: PackageManager by lazy { application.packageManager }
|
||||||
|
val appList: MutableLiveData<List<ResolveInfo>> = MutableLiveData()
|
||||||
|
val searchInput: MutableLiveData<String> = MutableLiveData("")
|
||||||
|
var appNotificationsFilter = Preferences.asLiveData(Preferences::appNotificationsFilter)
|
||||||
|
|
||||||
|
init {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
val mainIntent = Intent(Intent.ACTION_MAIN, null).apply {
|
||||||
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
|
}
|
||||||
|
|
||||||
|
val app = application.packageManager.queryIntentActivities(mainIntent, 0)
|
||||||
|
val sortedApp = app.sortedWith(Comparator { app1: ResolveInfo, app2: ResolveInfo ->
|
||||||
|
app1.loadLabel(pm).toString().compareTo(app2.loadLabel(pm).toString())
|
||||||
|
})
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
appList.postValue(sortedApp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,5 +8,6 @@ import com.tommasoberlose.anotherwidget.global.Preferences
|
|||||||
|
|
||||||
class CustomDateViewModel(application: Application) : AndroidViewModel(application) {
|
class CustomDateViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
val dateInput: MutableLiveData<String> = MutableLiveData(if (Preferences.dateFormat == "") "EEEE, MMM dd" else Preferences.dateFormat)
|
val dateInput: MutableLiveData<String> = MutableLiveData(if (Preferences.dateFormat == "") "EEEE, MMM dd" else Preferences.dateFormat)
|
||||||
val isDateCapitalize = Preferences.asLiveData(Preferences::isDateCapitalize)
|
val isDateCapitalize = MutableLiveData<Boolean>(Preferences.isDateCapitalize)
|
||||||
|
val isDateUppercase = MutableLiveData<Boolean>(Preferences.isDateUppercase)
|
||||||
}
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.viewmodels
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.ResolveInfo
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.koolio.library.DownloadableFontList
|
||||||
|
import com.koolio.library.Font
|
||||||
|
import com.koolio.library.FontList
|
||||||
|
import com.tommasoberlose.anotherwidget.BuildConfig
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class CustomFontViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
|
||||||
|
val fontList: MutableLiveData<ArrayList<Font>> = MutableLiveData()
|
||||||
|
val searchInput: MutableLiveData<String> = MutableLiveData("")
|
||||||
|
|
||||||
|
init {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
|
||||||
|
|
||||||
|
val fontListCallback: DownloadableFontList.FontListCallback =
|
||||||
|
object : DownloadableFontList.FontListCallback {
|
||||||
|
override fun onFontListRetrieved(downloadedList: FontList?) {
|
||||||
|
fontList.postValue(downloadedList?.fontArrayList)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTypefaceRequestFailed(reason: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DownloadableFontList.requestDownloadableFontList(fontListCallback, BuildConfig.GOOGLE_API_KEY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,12 +13,23 @@ class MainViewModel : ViewModel() {
|
|||||||
val textSecondaryAlpha = Preferences.asLiveData(Preferences::textSecondaryAlpha)
|
val textSecondaryAlpha = Preferences.asLiveData(Preferences::textSecondaryAlpha)
|
||||||
val backgroundCardColor = Preferences.asLiveData(Preferences::backgroundCardColor)
|
val backgroundCardColor = Preferences.asLiveData(Preferences::backgroundCardColor)
|
||||||
val backgroundCardAlpha = Preferences.asLiveData(Preferences::backgroundCardAlpha)
|
val backgroundCardAlpha = Preferences.asLiveData(Preferences::backgroundCardAlpha)
|
||||||
|
val textGlobalColorDark = Preferences.asLiveData(Preferences::textGlobalColorDark)
|
||||||
|
val textGlobalAlphaDark = Preferences.asLiveData(Preferences::textGlobalAlphaDark)
|
||||||
|
val textSecondaryColorDark = Preferences.asLiveData(Preferences::textSecondaryColorDark)
|
||||||
|
val textSecondaryAlphaDark = Preferences.asLiveData(Preferences::textSecondaryAlphaDark)
|
||||||
|
val backgroundCardColorDark = Preferences.asLiveData(Preferences::backgroundCardColorDark)
|
||||||
|
val backgroundCardAlphaDark = Preferences.asLiveData(Preferences::backgroundCardAlphaDark)
|
||||||
val textMainSize = Preferences.asLiveData(Preferences::textMainSize)
|
val textMainSize = Preferences.asLiveData(Preferences::textMainSize)
|
||||||
val textSecondSize = Preferences.asLiveData(Preferences::textSecondSize)
|
val textSecondSize = Preferences.asLiveData(Preferences::textSecondSize)
|
||||||
val textShadow = Preferences.asLiveData(Preferences::textShadow)
|
val textShadow = Preferences.asLiveData(Preferences::textShadow)
|
||||||
|
val textShadowDark = Preferences.asLiveData(Preferences::textShadowDark)
|
||||||
val customFont = Preferences.asLiveData(Preferences::customFont)
|
val customFont = Preferences.asLiveData(Preferences::customFont)
|
||||||
|
val customFontFile = Preferences.asLiveData(Preferences::customFontFile)
|
||||||
|
val customFontName = Preferences.asLiveData(Preferences::customFontName)
|
||||||
|
val customFontVariant = Preferences.asLiveData(Preferences::customFontVariant)
|
||||||
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)
|
||||||
|
|
||||||
// Calendar Settings
|
// Calendar Settings
|
||||||
val showEvents = Preferences.asLiveData(Preferences::showEvents)
|
val showEvents = Preferences.asLiveData(Preferences::showEvents)
|
||||||
@ -30,12 +41,15 @@ class MainViewModel : ViewModel() {
|
|||||||
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)
|
||||||
|
val showOnlyBusyEvents = Preferences.asLiveData(Preferences::showOnlyBusyEvents)
|
||||||
|
|
||||||
// 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 clockTextColor = Preferences.asLiveData(Preferences::clockTextColor)
|
val clockTextColor = Preferences.asLiveData(Preferences::clockTextColor)
|
||||||
val clockTextAlpha = Preferences.asLiveData(Preferences::clockTextAlpha)
|
val clockTextAlpha = Preferences.asLiveData(Preferences::clockTextAlpha)
|
||||||
|
val clockTextColorDark = Preferences.asLiveData(Preferences::clockTextColorDark)
|
||||||
|
val clockTextAlphaDark = Preferences.asLiveData(Preferences::clockTextAlphaDark)
|
||||||
val showAMPMIndicator = Preferences.asLiveData(Preferences::showAMPMIndicator)
|
val showAMPMIndicator = Preferences.asLiveData(Preferences::showAMPMIndicator)
|
||||||
|
|
||||||
val clockAppName = Preferences.asLiveData(Preferences::clockAppName)
|
val clockAppName = Preferences.asLiveData(Preferences::clockAppName)
|
||||||
@ -50,12 +64,15 @@ class MainViewModel : ViewModel() {
|
|||||||
val weatherRefreshPeriod = Preferences.asLiveData(Preferences::weatherRefreshPeriod)
|
val weatherRefreshPeriod = Preferences.asLiveData(Preferences::weatherRefreshPeriod)
|
||||||
|
|
||||||
val weatherAppName = Preferences.asLiveData(Preferences::weatherAppName)
|
val weatherAppName = Preferences.asLiveData(Preferences::weatherAppName)
|
||||||
val weatherProviderApi = Preferences.asLiveData(Preferences::weatherProviderApi)
|
val weatherProviderApi = Preferences.asLiveData(Preferences::weatherProviderApiOpen)
|
||||||
|
|
||||||
val customLocationAdd = Preferences.asLiveData(Preferences::customLocationAdd)
|
val customLocationAdd = Preferences.asLiveData(Preferences::customLocationAdd)
|
||||||
|
|
||||||
val showWeatherWarning = Preferences.asLiveData(Preferences::showWeatherWarning)
|
val showWeatherWarning = Preferences.asLiveData(Preferences::showWeatherWarning)
|
||||||
val weatherIconPack = Preferences.asLiveData(Preferences::weatherIconPack)
|
val weatherIconPack = Preferences.asLiveData(Preferences::weatherIconPack)
|
||||||
|
val weatherProvider = Preferences.asLiveData(Preferences::weatherProvider)
|
||||||
|
val weatherProviderError = Preferences.asLiveData(Preferences::weatherProviderError)
|
||||||
|
val weatherProviderLocationError = Preferences.asLiveData(Preferences::weatherProviderLocationError)
|
||||||
|
|
||||||
// Glance
|
// Glance
|
||||||
val showGlance = Preferences.asLiveData(Preferences::showGlance)
|
val showGlance = Preferences.asLiveData(Preferences::showGlance)
|
||||||
@ -64,6 +81,7 @@ class MainViewModel : ViewModel() {
|
|||||||
val showBatteryCharging = Preferences.asLiveData(Preferences::showBatteryCharging)
|
val showBatteryCharging = Preferences.asLiveData(Preferences::showBatteryCharging)
|
||||||
val showDailySteps = Preferences.asLiveData(Preferences::showDailySteps)
|
val showDailySteps = Preferences.asLiveData(Preferences::showDailySteps)
|
||||||
val customInfo = Preferences.asLiveData(Preferences::customNotes)
|
val customInfo = Preferences.asLiveData(Preferences::customNotes)
|
||||||
|
val musicPlayersFilter = Preferences.asLiveData(Preferences::musicPlayersFilter)
|
||||||
|
|
||||||
// Advanced Settings
|
// Advanced Settings
|
||||||
val darkThemePreference = Preferences.asLiveData(Preferences::darkThemePreference)
|
val darkThemePreference = Preferences.asLiveData(Preferences::darkThemePreference)
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.viewmodels
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.ResolveInfo
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.lifecycle.*
|
||||||
|
import com.chibatching.kotpref.livedata.asLiveData
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
class MusicPlayersFilterViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
|
||||||
|
val pm: PackageManager by lazy { application.packageManager }
|
||||||
|
val appList: MutableLiveData<List<ResolveInfo>> = MutableLiveData()
|
||||||
|
val searchInput: MutableLiveData<String> = MutableLiveData("")
|
||||||
|
var musicPlayersFilter = Preferences.asLiveData(Preferences::musicPlayersFilter)
|
||||||
|
|
||||||
|
init {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
val mainIntent = Intent(Intent.ACTION_MAIN, null).apply {
|
||||||
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
|
}
|
||||||
|
|
||||||
|
val app = application.packageManager.queryIntentActivities(mainIntent, 0)
|
||||||
|
val sortedApp = app.sortedWith(Comparator { app1: ResolveInfo, app2: ResolveInfo ->
|
||||||
|
app1.loadLabel(pm).toString().compareTo(app2.loadLabel(pm).toString())
|
||||||
|
})
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
appList.postValue(sortedApp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.viewmodels
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.chibatching.kotpref.livedata.asLiveData
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
|
||||||
|
class WeatherProviderViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
|
||||||
|
val weatherProvider = Preferences.asLiveData(Preferences::weatherProvider)
|
||||||
|
val weatherProviderError = Preferences.asLiveData(Preferences::weatherProviderError)
|
||||||
|
val weatherProviderLocationError = Preferences.asLiveData(Preferences::weatherProviderLocationError)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -7,6 +7,7 @@ import android.appwidget.AppWidgetProvider
|
|||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.IntentSender
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
@ -17,22 +18,23 @@ import android.util.TypedValue
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.RemoteViews
|
import android.widget.RemoteViews
|
||||||
import android.widget.TextClock
|
|
||||||
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 com.google.gson.Gson
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
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.*
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ImageHelper.applyShadow
|
||||||
import com.tommasoberlose.anotherwidget.receivers.*
|
import com.tommasoberlose.anotherwidget.receivers.*
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
import com.tommasoberlose.anotherwidget.utils.getCapWordString
|
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||||
import kotlinx.android.synthetic.main.the_widget.view.*
|
import kotlinx.android.synthetic.main.the_widget.view.*
|
||||||
import java.lang.Exception
|
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
@ -91,10 +93,14 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
val height = displayMetrics.heightPixels
|
val height = displayMetrics.heightPixels
|
||||||
|
|
||||||
val dimensions = WidgetHelper.WidgetSizeProvider(context, appWidgetManager).getWidgetsSize(appWidgetId)
|
val dimensions = WidgetHelper.WidgetSizeProvider(context, appWidgetManager).getWidgetsSize(appWidgetId)
|
||||||
generateWidgetView(context, appWidgetId, appWidgetManager, min(dimensions.first - 8.toPixel(context), min(width, height) - 16.toPixel(context)))
|
|
||||||
|
WidgetHelper.runWithCustomTypeface(context) {
|
||||||
|
generateWidgetView(context, appWidgetId, appWidgetManager, min(dimensions.first - 8.toPixel(context), min(width, height) - 16.toPixel(context)), it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int) {
|
private fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int, typeface: Typeface? = null) {
|
||||||
|
|
||||||
var views = RemoteViews(context.packageName, R.layout.the_widget_sans)
|
var views = RemoteViews(context.packageName, R.layout.the_widget_sans)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -102,12 +108,12 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
views.setInt(
|
views.setInt(
|
||||||
R.id.widget_shape_background,
|
R.id.widget_shape_background,
|
||||||
"setColorFilter",
|
"setColorFilter",
|
||||||
ColorHelper.getBackgroundColorRgb()
|
ColorHelper.getBackgroundColorRgb(context.isDarkTheme())
|
||||||
)
|
)
|
||||||
views.setInt(
|
views.setInt(
|
||||||
R.id.widget_shape_background,
|
R.id.widget_shape_background,
|
||||||
"setImageAlpha",
|
"setImageAlpha",
|
||||||
ColorHelper.getBackgroundAlpha()
|
ColorHelper.getBackgroundAlpha(context.isDarkTheme())
|
||||||
)
|
)
|
||||||
val refreshIntent = PendingIntent.getActivity(
|
val refreshIntent = PendingIntent.getActivity(
|
||||||
context,
|
context,
|
||||||
@ -126,7 +132,8 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
|
|
||||||
// Setup listener
|
// Setup listener
|
||||||
try {
|
try {
|
||||||
val generatedView = generateWidgetView(context)
|
|
||||||
|
val generatedView = generateWidgetView(context, typeface)
|
||||||
views.setImageViewBitmap(
|
views.setImageViewBitmap(
|
||||||
R.id.bitmap_container,
|
R.id.bitmap_container,
|
||||||
BitmapHelper.getBitmapFromView(generatedView, width = w)
|
BitmapHelper.getBitmapFromView(generatedView, width = w)
|
||||||
@ -264,7 +271,21 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
|
|
||||||
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
|
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
|
||||||
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
||||||
|
|
||||||
|
views.setViewVisibility(
|
||||||
|
R.id.second_row_top_margin_small_sans,
|
||||||
|
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.value) View.VISIBLE else View.GONE
|
||||||
|
)
|
||||||
|
views.setViewVisibility(
|
||||||
|
R.id.second_row_top_margin_medium_sans,
|
||||||
|
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.value) View.VISIBLE else View.GONE
|
||||||
|
)
|
||||||
|
views.setViewVisibility(
|
||||||
|
R.id.second_row_top_margin_large_sans,
|
||||||
|
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.value) View.VISIBLE else View.GONE
|
||||||
|
)
|
||||||
} else if (GlanceProviderHelper.showGlanceProviders(context) && v.calendar_layout.isVisible) {
|
} else if (GlanceProviderHelper.showGlanceProviders(context) && v.calendar_layout.isVisible) {
|
||||||
|
var showSomething = false
|
||||||
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(context)) {
|
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(context)) {
|
||||||
when (provider) {
|
when (provider) {
|
||||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||||
@ -276,6 +297,7 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
)
|
)
|
||||||
views.setOnClickPendingIntent(R.id.second_row_rect, musicIntent)
|
views.setOnClickPendingIntent(R.id.second_row_rect, musicIntent)
|
||||||
|
showSomething = true
|
||||||
break@loop
|
break@loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -288,6 +310,7 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
)
|
)
|
||||||
views.setOnClickPendingIntent(R.id.second_row_rect, alarmIntent)
|
views.setOnClickPendingIntent(R.id.second_row_rect, alarmIntent)
|
||||||
|
showSomething = true
|
||||||
break@loop
|
break@loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -302,6 +325,7 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
)
|
)
|
||||||
views.setOnClickPendingIntent(R.id.second_row_rect, batteryIntent)
|
views.setOnClickPendingIntent(R.id.second_row_rect, batteryIntent)
|
||||||
|
showSomething = true
|
||||||
break@loop
|
break@loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -320,12 +344,45 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
)
|
)
|
||||||
views.setOnClickPendingIntent(R.id.second_row_rect, fitIntent)
|
views.setOnClickPendingIntent(R.id.second_row_rect, fitIntent)
|
||||||
|
showSomething = true
|
||||||
|
break@loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.NOTIFICATIONS -> {
|
||||||
|
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
|
||||||
|
try {
|
||||||
|
if (Preferences.lastNotificationIcon != 0) {
|
||||||
|
val remotePackageContext = context.createPackageContext(Preferences.lastNotificationPackage, 0)
|
||||||
|
ContextCompat.getDrawable(
|
||||||
|
remotePackageContext,
|
||||||
|
Preferences.lastNotificationIcon)
|
||||||
|
}
|
||||||
|
val notificationIntent = PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
widgetID,
|
||||||
|
IntentHelper.getNotificationIntent(context),
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
views.setOnClickPendingIntent(
|
||||||
|
R.id.second_row_rect,
|
||||||
|
notificationIntent
|
||||||
|
)
|
||||||
|
showSomething = true
|
||||||
|
break@loop
|
||||||
|
} catch (ex: Exception) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.GREETINGS -> {
|
||||||
|
if (Preferences.showGreetings && GreetingsHelper.showGreetings() && GreetingsHelper.getRandomString(context).isNotBlank()) {
|
||||||
|
showSomething = true
|
||||||
break@loop
|
break@loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (showSomething) {
|
||||||
views.setImageViewBitmap(
|
views.setImageViewBitmap(
|
||||||
R.id.next_event_rect,
|
R.id.next_event_rect,
|
||||||
BitmapHelper.getBitmapFromView(v.next_event, draw = false)
|
BitmapHelper.getBitmapFromView(v.next_event, draw = false)
|
||||||
@ -340,6 +397,21 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
|
views.setViewVisibility(R.id.empty_layout_rect, View.GONE)
|
||||||
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
||||||
views.setOnClickPendingIntent(R.id.next_event_rect, calPIntent)
|
views.setOnClickPendingIntent(R.id.next_event_rect, calPIntent)
|
||||||
|
|
||||||
|
|
||||||
|
views.setViewVisibility(
|
||||||
|
R.id.second_row_top_margin_small_sans,
|
||||||
|
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.value) View.VISIBLE else View.GONE
|
||||||
|
)
|
||||||
|
views.setViewVisibility(
|
||||||
|
R.id.second_row_top_margin_medium_sans,
|
||||||
|
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.value) View.VISIBLE else View.GONE
|
||||||
|
)
|
||||||
|
views.setViewVisibility(
|
||||||
|
R.id.second_row_top_margin_large_sans,
|
||||||
|
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.value) View.VISIBLE else View.GONE
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
ex.printStackTrace()
|
ex.printStackTrace()
|
||||||
@ -408,8 +480,8 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
views.setViewVisibility(R.id.clock_bottom_margin_medium, 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.clock_bottom_margin_large, View.GONE)
|
||||||
} else {
|
} else {
|
||||||
views.setTextColor(R.id.time, ColorHelper.getClockFontColor())
|
views.setTextColor(R.id.time, ColorHelper.getClockFontColor(context.isDarkTheme()))
|
||||||
views.setTextColor(R.id.time_am_pm, ColorHelper.getClockFontColor())
|
views.setTextColor(R.id.time_am_pm, ColorHelper.getClockFontColor(context.isDarkTheme()))
|
||||||
views.setTextViewTextSize(
|
views.setTextViewTextSize(
|
||||||
R.id.time,
|
R.id.time,
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
@ -458,10 +530,12 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
|
|
||||||
|
|
||||||
// Generates the widget bitmap from the view
|
// Generates the widget bitmap from the view
|
||||||
fun generateWidgetView(context: Context): View {
|
fun generateWidgetView(context: Context, typeface: Typeface? = null): View {
|
||||||
val eventRepository = EventRepository(context)
|
val eventRepository = EventRepository(context)
|
||||||
val v = View.inflate(context, R.layout.the_widget, null)
|
val v = View.inflate(context, R.layout.the_widget, null)
|
||||||
|
|
||||||
|
v.loader.isVisible = false
|
||||||
|
|
||||||
val now = Calendar.getInstance().apply {
|
val now = Calendar.getInstance().apply {
|
||||||
set(Calendar.SECOND, 0)
|
set(Calendar.SECOND, 0)
|
||||||
set(Calendar.MILLISECOND, 0)
|
set(Calendar.MILLISECOND, 0)
|
||||||
@ -480,8 +554,10 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
|
|
||||||
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
|
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
|
||||||
// Multiple counter
|
// Multiple counter
|
||||||
v.action_next.isVisible = Preferences.showNextEvent && eventRepository.getEventsCount() > 1
|
v.action_next.isVisible =
|
||||||
v.action_previous.isVisible = Preferences.showNextEvent && eventRepository.getEventsCount() > 1
|
Preferences.showNextEvent && eventRepository.getEventsCount() > 1
|
||||||
|
v.action_previous.isVisible =
|
||||||
|
Preferences.showNextEvent && eventRepository.getEventsCount() > 1
|
||||||
|
|
||||||
v.next_event.text = nextEvent.title
|
v.next_event.text = nextEvent.title
|
||||||
|
|
||||||
@ -494,7 +570,11 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
)
|
)
|
||||||
.toLowerCase(Locale.getDefault())
|
.toLowerCase(Locale.getDefault())
|
||||||
} else {
|
} else {
|
||||||
SettingsStringHelper.getAllDayEventDifferenceText(context, now.timeInMillis, nextEvent.startDate).toLowerCase(Locale.getDefault())
|
SettingsStringHelper.getAllDayEventDifferenceText(
|
||||||
|
context,
|
||||||
|
now.timeInMillis,
|
||||||
|
nextEvent.startDate
|
||||||
|
).toLowerCase(Locale.getDefault())
|
||||||
}
|
}
|
||||||
v.next_event_difference_time.visibility = View.VISIBLE
|
v.next_event_difference_time.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
@ -502,15 +582,30 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
|
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
|
||||||
v.second_row_icon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.round_place))
|
v.second_row_icon.setImageDrawable(
|
||||||
|
ContextCompat.getDrawable(
|
||||||
|
context,
|
||||||
|
R.drawable.round_place
|
||||||
|
)
|
||||||
|
)
|
||||||
v.next_event_date.text = nextEvent.address
|
v.next_event_date.text = nextEvent.address
|
||||||
} else {
|
} else {
|
||||||
v.second_row_icon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.round_today))
|
v.second_row_icon.setImageDrawable(
|
||||||
|
ContextCompat.getDrawable(
|
||||||
|
context,
|
||||||
|
R.drawable.round_today
|
||||||
|
)
|
||||||
|
)
|
||||||
if (!nextEvent.allDay) {
|
if (!nextEvent.allDay) {
|
||||||
val startHour = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()).format(nextEvent.startDate)
|
val startHour =
|
||||||
val endHour = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()).format(nextEvent.endDate)
|
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)
|
var dayDiff =
|
||||||
|
TimeUnit.MILLISECONDS.toDays(nextEvent.endDate - nextEvent.startDate)
|
||||||
|
|
||||||
val startCal = Calendar.getInstance()
|
val startCal = Calendar.getInstance()
|
||||||
startCal.timeInMillis = nextEvent.startDate
|
startCal.timeInMillis = nextEvent.startDate
|
||||||
@ -520,27 +615,59 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
|
|
||||||
if (startCal.get(Calendar.HOUR_OF_DAY) > endCal.get(Calendar.HOUR_OF_DAY)) {
|
if (startCal.get(Calendar.HOUR_OF_DAY) > endCal.get(Calendar.HOUR_OF_DAY)) {
|
||||||
dayDiff++
|
dayDiff++
|
||||||
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(Calendar.MINUTE) >= endCal.get(Calendar.MINUTE)) {
|
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(
|
||||||
|
Calendar.MINUTE
|
||||||
|
) > endCal.get(Calendar.MINUTE)
|
||||||
|
) {
|
||||||
dayDiff++
|
dayDiff++
|
||||||
}
|
}
|
||||||
var multipleDay = ""
|
var multipleDay = ""
|
||||||
if (dayDiff > 0) {
|
if (dayDiff > 0) {
|
||||||
multipleDay = String.format(" (+%s%s)", dayDiff, context.getString(R.string.day_char))
|
multipleDay = String.format(
|
||||||
|
" (+%s%s)",
|
||||||
|
dayDiff,
|
||||||
|
context.getString(R.string.day_char)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextEvent.startDate != nextEvent.endDate) {
|
||||||
|
v.next_event_date.text =
|
||||||
|
String.format("%s - %s%s", startHour, endHour, multipleDay)
|
||||||
|
} else {
|
||||||
|
v.next_event_date.text =
|
||||||
|
String.format("%s", startHour)
|
||||||
}
|
}
|
||||||
v.next_event_date.text = String.format("%s - %s%s", startHour, endHour, multipleDay)
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
val flags: Int = DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
val flags: Int =
|
||||||
v.next_event_date.text = DateUtils.formatDateTime(context, nextEvent.startDate, flags)
|
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
||||||
|
val start = Calendar.getInstance().apply { timeInMillis = nextEvent.startDate }
|
||||||
|
|
||||||
|
v.next_event_date.text = if (now.get(Calendar.DAY_OF_YEAR) == start.get(Calendar.DAY_OF_YEAR)) {
|
||||||
|
DateUtils.formatDateTime(context, nextEvent.startDate, flags)
|
||||||
|
} else if (now.get(Calendar.DAY_OF_YEAR) > start.get(Calendar.DAY_OF_YEAR) || now.get(Calendar.YEAR) > start.get(Calendar.YEAR)) {
|
||||||
|
DateUtils.formatDateTime(context, now.timeInMillis, flags)
|
||||||
|
} else {
|
||||||
|
DateUtils.formatDateTime(context, nextEvent.startDate, flags)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v.empty_layout.visibility = View.GONE
|
v.empty_layout.visibility = View.GONE
|
||||||
v.calendar_layout.visibility = View.VISIBLE
|
v.calendar_layout.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
v.second_row_top_margin_small.visibility =
|
||||||
|
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.value) View.VISIBLE else View.GONE
|
||||||
|
v.second_row_top_margin_medium.visibility =
|
||||||
|
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.value) View.VISIBLE else View.GONE
|
||||||
|
v.second_row_top_margin_large.visibility =
|
||||||
|
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.value) View.VISIBLE else View.GONE
|
||||||
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
|
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
|
||||||
v.second_row_icon.isVisible = true
|
v.second_row_icon.isVisible = true
|
||||||
var showSomething = false
|
var showSomething = false
|
||||||
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(context)) {
|
loop@ for (provider: Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(
|
||||||
|
context
|
||||||
|
)) {
|
||||||
when (provider) {
|
when (provider) {
|
||||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||||
if (MediaPlayerHelper.isSomeonePlaying(context)) {
|
if (MediaPlayerHelper.isSomeonePlaying(context)) {
|
||||||
@ -574,10 +701,11 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
if (Preferences.isCharging) {
|
if (Preferences.isCharging) {
|
||||||
v.second_row_icon.isVisible = false
|
v.second_row_icon.isVisible = false
|
||||||
val batteryLevel = BatteryHelper.getBatteryLevel(context)
|
val batteryLevel = BatteryHelper.getBatteryLevel(context)
|
||||||
if (batteryLevel == 100) {
|
if (batteryLevel != 100) {
|
||||||
v.next_event_date.text = "%s - %d%%".format(context.getString(R.string.charging), batteryLevel)
|
|
||||||
} else {
|
|
||||||
v.next_event_date.text = context.getString(R.string.charging)
|
v.next_event_date.text = context.getString(R.string.charging)
|
||||||
|
} else {
|
||||||
|
v.next_event_date.text =
|
||||||
|
context.getString(R.string.charged)
|
||||||
}
|
}
|
||||||
showSomething = true
|
showSomething = true
|
||||||
break@loop
|
break@loop
|
||||||
@ -594,7 +722,6 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
if (Preferences.customNotes.isNotEmpty()) {
|
if (Preferences.customNotes.isNotEmpty()) {
|
||||||
v.second_row_icon.isVisible = false
|
v.second_row_icon.isVisible = false
|
||||||
v.next_event_date.text = Preferences.customNotes
|
v.next_event_date.text = Preferences.customNotes
|
||||||
v.next_event_date.gravity
|
|
||||||
v.next_event_date.maxLines = 2
|
v.next_event_date.maxLines = 2
|
||||||
showSomething = true
|
showSomething = true
|
||||||
break@loop
|
break@loop
|
||||||
@ -603,7 +730,37 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||||
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
|
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
|
||||||
v.second_row_icon.isVisible = false
|
v.second_row_icon.isVisible = false
|
||||||
v.next_event_date.text = context.getString(R.string.daily_steps_counter).format(Preferences.googleFitSteps)
|
v.next_event_date.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)
|
||||||
|
v.second_row_icon.isVisible = true
|
||||||
|
v.second_row_icon.setImageDrawable(icon)
|
||||||
|
} else {
|
||||||
|
v.second_row_icon.isVisible = false
|
||||||
|
}
|
||||||
|
v.next_event_date.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()) {
|
||||||
|
v.next_event_date.text = greetingsText
|
||||||
|
v.next_event_date.maxLines = 2
|
||||||
|
v.second_row_icon.isVisible = false
|
||||||
showSomething = true
|
showSomething = true
|
||||||
break@loop
|
break@loop
|
||||||
}
|
}
|
||||||
@ -615,6 +772,13 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
v.next_event.text = DateHelper.getDateText(context, now)
|
v.next_event.text = DateHelper.getDateText(context, now)
|
||||||
v.empty_layout.visibility = View.GONE
|
v.empty_layout.visibility = View.GONE
|
||||||
v.calendar_layout.visibility = View.VISIBLE
|
v.calendar_layout.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
v.second_row_top_margin_small.visibility =
|
||||||
|
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.value) View.VISIBLE else View.GONE
|
||||||
|
v.second_row_top_margin_medium.visibility =
|
||||||
|
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.value) View.VISIBLE else View.GONE
|
||||||
|
v.second_row_top_margin_large.visibility =
|
||||||
|
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.value) View.VISIBLE else View.GONE
|
||||||
} else {
|
} else {
|
||||||
v.second_row_icon.isVisible = false
|
v.second_row_icon.isVisible = false
|
||||||
}
|
}
|
||||||
@ -622,28 +786,49 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
|
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.divider3, v.special_temp).forEach {
|
listOf<TextView>(
|
||||||
it.setTextColor(ColorHelper.getFontColor())
|
v.empty_date,
|
||||||
|
v.divider1,
|
||||||
|
v.temp,
|
||||||
|
v.next_event,
|
||||||
|
v.next_event_difference_time,
|
||||||
|
v.divider3,
|
||||||
|
v.special_temp
|
||||||
|
).forEach {
|
||||||
|
it.setTextColor(ColorHelper.getFontColor(context.applicationContext.isDarkTheme()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.value) {
|
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.value) {
|
||||||
listOf<ImageView>(v.action_next, v.action_previous)
|
listOf<ImageView>(v.action_next, v.action_previous)
|
||||||
} else {
|
} else {
|
||||||
listOf<ImageView>(v.action_next, v.action_previous, v.empty_weather_icon, v.special_weather_icon)
|
listOf<ImageView>(
|
||||||
|
v.action_next,
|
||||||
|
v.action_previous,
|
||||||
|
v.empty_weather_icon,
|
||||||
|
v.special_weather_icon
|
||||||
|
)
|
||||||
}.forEach {
|
}.forEach {
|
||||||
it.setColorFilter(ColorHelper.getFontColor())
|
it.setColorFilter(ColorHelper.getFontColorRgb(context.applicationContext.isDarkTheme()))
|
||||||
|
it.alpha =
|
||||||
|
(if (context.isDarkTheme()) Preferences.textGlobalAlphaDark.toIntValue()
|
||||||
|
.toFloat() else Preferences.textGlobalAlpha.toIntValue()
|
||||||
|
.toFloat()) / 100
|
||||||
}
|
}
|
||||||
|
|
||||||
listOf<TextView>(v.next_event_date, v.divider2, v.calendar_temp).forEach {
|
listOf<TextView>(v.next_event_date, v.divider2, v.calendar_temp).forEach {
|
||||||
it.setTextColor(ColorHelper.getSecondaryFontColor())
|
it.setTextColor(ColorHelper.getSecondaryFontColor(context.applicationContext.isDarkTheme()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.value) {
|
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.value) {
|
||||||
listOf<ImageView>(v.second_row_icon)
|
listOf<ImageView>(v.second_row_icon, v.second_row_icon_shadow)
|
||||||
} else {
|
} else {
|
||||||
listOf<ImageView>(v.second_row_icon, v.weather_icon)
|
listOf<ImageView>(v.second_row_icon, v.weather_icon, v.second_row_icon_shadow)
|
||||||
}.forEach {
|
}.forEach {
|
||||||
it.setColorFilter(ColorHelper.getSecondaryFontColor())
|
it.setColorFilter(ColorHelper.getSecondaryFontColorRgb(context.applicationContext.isDarkTheme()))
|
||||||
|
it.alpha =
|
||||||
|
(if (context.isDarkTheme()) Preferences.textSecondaryAlphaDark.toIntValue()
|
||||||
|
.toFloat() else Preferences.textSecondaryAlpha.toIntValue()
|
||||||
|
.toFloat()) / 100
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text Size
|
// Text Size
|
||||||
@ -678,39 +863,119 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
v.action_previous.scaleX = Preferences.textMainSize / 28f
|
v.action_previous.scaleX = Preferences.textMainSize / 28f
|
||||||
v.action_previous.scaleY = Preferences.textMainSize / 28f
|
v.action_previous.scaleY = Preferences.textMainSize / 28f
|
||||||
|
|
||||||
v.special_weather_icon.scaleX = Preferences.textMainSize / 20f
|
v.special_weather_icon.scaleX = Preferences.textMainSize / 18f
|
||||||
v.special_weather_icon.scaleY = Preferences.textMainSize / 20f
|
v.special_weather_icon.scaleY = Preferences.textMainSize / 18f
|
||||||
|
|
||||||
|
|
||||||
// Shadows
|
// Shadows
|
||||||
val shadowRadius = when (Preferences.textShadow) {
|
val shadowRadius =
|
||||||
|
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
||||||
0 -> 0f
|
0 -> 0f
|
||||||
1 -> 5f
|
1 -> 5f
|
||||||
2 -> 5f
|
2 -> 5f
|
||||||
else -> 5f
|
else -> 5f
|
||||||
}
|
}
|
||||||
val shadowColor = when (Preferences.textShadow) {
|
val shadowColor =
|
||||||
|
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
||||||
0 -> Color.TRANSPARENT
|
0 -> Color.TRANSPARENT
|
||||||
1 -> R.color.black_50
|
1 -> R.color.black_50
|
||||||
2 -> Color.BLACK
|
2 -> Color.BLACK
|
||||||
else -> R.color.black_50
|
else -> R.color.black_50
|
||||||
}
|
}
|
||||||
val shadowDy = when (Preferences.textShadow) {
|
val shadowDy =
|
||||||
|
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
||||||
0 -> 0f
|
0 -> 0f
|
||||||
1 -> 0f
|
1 -> 0f
|
||||||
2 -> 1f
|
2 -> 1f
|
||||||
else -> 0f
|
else -> 0f
|
||||||
}
|
}
|
||||||
|
|
||||||
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.next_event_date, v.divider2, v.calendar_temp, v.divider3, v.special_temp).forEach {
|
listOf<TextView>(
|
||||||
|
v.empty_date,
|
||||||
|
v.divider1,
|
||||||
|
v.temp,
|
||||||
|
v.next_event,
|
||||||
|
v.next_event_difference_time,
|
||||||
|
v.next_event_date,
|
||||||
|
v.divider2,
|
||||||
|
v.calendar_temp,
|
||||||
|
v.divider3,
|
||||||
|
v.special_temp
|
||||||
|
).forEach {
|
||||||
it.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
|
it.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Icons shadow
|
||||||
|
|
||||||
|
listOf(
|
||||||
|
Pair(v.second_row_icon, v.second_row_icon_shadow),
|
||||||
|
).forEach {
|
||||||
|
if ((if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) == 0) {
|
||||||
|
it.second.isVisible = false
|
||||||
|
} else {
|
||||||
|
it.second.isVisible = it.first.isVisible
|
||||||
|
it.second.scaleX = it.first.scaleX
|
||||||
|
it.second.scaleY = it.first.scaleY
|
||||||
|
it.second.applyShadow(it.first)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
listOf(
|
||||||
|
Pair(v.action_next, v.action_next_shadow),
|
||||||
|
Pair(v.action_previous, v.action_previous_shadow),
|
||||||
|
).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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v.action_previous.scaleX = v.action_previous.scaleX * -1
|
||||||
|
v.action_previous_shadow.scaleX = v.action_previous_shadow.scaleX * -1
|
||||||
|
|
||||||
// Custom Font
|
// Custom Font
|
||||||
if (Preferences.customFont == Constants.CUSTOM_FONT_PRODUCT_SANS) {
|
if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) {
|
||||||
val productSans: Typeface = Typeface.createFromAsset(context.assets, "fonts/product_sans_regular.ttf")
|
val googleSans: Typeface = when (Preferences.customFontVariant) {
|
||||||
listOf<TextView>(v.empty_date, v.divider1, v.temp, v.next_event, v.next_event_difference_time, v.next_event_date, v.divider2, v.calendar_temp, v.divider3, v.special_temp).forEach {
|
"100" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_thin.ttf")
|
||||||
it.typeface = productSans
|
"200" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_light.ttf")
|
||||||
|
"500" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_medium.ttf")
|
||||||
|
"700" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_bold.ttf")
|
||||||
|
"800" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_black.ttf")
|
||||||
|
else -> Typeface.createFromAsset(context.assets, "fonts/google_sans_regular.ttf")
|
||||||
|
}
|
||||||
|
|
||||||
|
listOf<TextView>(
|
||||||
|
v.empty_date,
|
||||||
|
v.divider1,
|
||||||
|
v.temp,
|
||||||
|
v.next_event,
|
||||||
|
v.next_event_difference_time,
|
||||||
|
v.next_event_date,
|
||||||
|
v.divider2,
|
||||||
|
v.calendar_temp,
|
||||||
|
v.divider3,
|
||||||
|
v.special_temp
|
||||||
|
).forEach {
|
||||||
|
it.typeface = googleSans
|
||||||
|
}
|
||||||
|
} else if (Preferences.customFont == Constants.CUSTOM_FONT_DOWNLOADED && typeface != null) {
|
||||||
|
listOf<TextView>(
|
||||||
|
v.empty_date,
|
||||||
|
v.divider1,
|
||||||
|
v.temp,
|
||||||
|
v.next_event,
|
||||||
|
v.next_event_difference_time,
|
||||||
|
v.next_event_date,
|
||||||
|
v.divider2,
|
||||||
|
v.calendar_temp,
|
||||||
|
v.divider3,
|
||||||
|
v.special_temp
|
||||||
|
).forEach {
|
||||||
|
it.typeface = typeface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -719,7 +984,12 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
v.weather.visibility = View.VISIBLE
|
v.weather.visibility = View.VISIBLE
|
||||||
v.calendar_weather.visibility = View.VISIBLE
|
v.calendar_weather.visibility = View.VISIBLE
|
||||||
v.special_weather.visibility = View.VISIBLE
|
v.special_weather.visibility = View.VISIBLE
|
||||||
val currentTemp = String.format(Locale.getDefault(), "%d °%s", Preferences.weatherTemp.roundToInt(), Preferences.weatherRealTempUnit)
|
val currentTemp = String.format(
|
||||||
|
Locale.getDefault(),
|
||||||
|
"%d °%s",
|
||||||
|
Preferences.weatherTemp.roundToInt(),
|
||||||
|
Preferences.weatherRealTempUnit
|
||||||
|
)
|
||||||
|
|
||||||
val icon: String = Preferences.weatherIcon
|
val icon: String = Preferences.weatherIcon
|
||||||
if (icon == "") {
|
if (icon == "") {
|
||||||
@ -727,9 +997,9 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
v.empty_weather_icon.visibility = View.GONE
|
v.empty_weather_icon.visibility = View.GONE
|
||||||
v.special_weather_icon.visibility = View.GONE
|
v.special_weather_icon.visibility = View.GONE
|
||||||
} else {
|
} else {
|
||||||
v.weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(icon))
|
v.weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon))
|
||||||
v.empty_weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(icon))
|
v.empty_weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon))
|
||||||
v.special_weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(icon))
|
v.special_weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon))
|
||||||
v.weather_icon.visibility = View.VISIBLE
|
v.weather_icon.visibility = View.VISIBLE
|
||||||
v.empty_weather_icon.visibility = View.VISIBLE
|
v.empty_weather_icon.visibility = View.VISIBLE
|
||||||
v.special_weather_icon.visibility = View.VISIBLE
|
v.special_weather_icon.visibility = View.VISIBLE
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
package com.tommasoberlose.anotherwidget.utils
|
package com.tommasoberlose.anotherwidget.utils
|
||||||
|
|
||||||
|
import android.animation.*
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewAnimationUtils
|
import android.view.ViewAnimationUtils
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import android.animation.Animator
|
|
||||||
import android.animation.AnimatorListenerAdapter
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.WallpaperManager
|
import android.app.WallpaperManager
|
||||||
import android.content.*
|
import android.content.*
|
||||||
@ -23,10 +22,20 @@ 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.ViewPropertyAnimator
|
||||||
import android.view.animation.Animation
|
import android.view.animation.Animation
|
||||||
import android.view.animation.Transformation
|
import android.view.animation.Transformation
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.RelativeLayout
|
||||||
|
import androidx.core.animation.addListener
|
||||||
|
import androidx.core.animation.doOnEnd
|
||||||
|
import androidx.core.animation.doOnStart
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||||
|
import kotlinx.android.synthetic.main.fragment_app_main.*
|
||||||
|
import kotlinx.android.synthetic.main.the_widget_sans.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
@ -68,55 +77,72 @@ fun View.reveal(initialX: Int? = null, initialY: Int? = null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun View.expand() {
|
fun View.expand(duration: Long = 500L) {
|
||||||
if (visibility != View.VISIBLE) {
|
clearAnimation()
|
||||||
measure(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
try {
|
||||||
val targetHeight = measuredHeight
|
val animator = (tag as ValueAnimator)
|
||||||
|
animator.removeAllListeners()
|
||||||
|
animator.cancel()
|
||||||
|
} catch (ex: java.lang.Exception) {}
|
||||||
|
|
||||||
layoutParams.height = 0
|
layoutParams = layoutParams.apply {
|
||||||
visibility = View.VISIBLE
|
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||||
val a = object : Animation() {
|
|
||||||
protected override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
|
|
||||||
layoutParams.height = if (interpolatedTime == 1f)
|
|
||||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
else
|
|
||||||
(targetHeight * interpolatedTime).toInt()
|
|
||||||
translationY = 0f
|
|
||||||
requestLayout()
|
|
||||||
}
|
}
|
||||||
|
measure(0, 0)
|
||||||
|
|
||||||
override fun willChangeBounds(): Boolean {
|
val initialHeight = measuredHeight
|
||||||
return true
|
val anim = ValueAnimator.ofFloat(
|
||||||
|
alpha,
|
||||||
|
1f
|
||||||
|
).apply {
|
||||||
|
this.duration = duration
|
||||||
|
addUpdateListener {
|
||||||
|
val animatedValue = animatedValue as Float
|
||||||
|
layoutParams = layoutParams.apply {
|
||||||
|
height = (initialHeight * animatedValue).toInt()
|
||||||
}
|
}
|
||||||
|
translationY = (initialHeight * animatedValue - initialHeight)
|
||||||
|
alpha = animatedValue
|
||||||
}
|
}
|
||||||
|
addListener(
|
||||||
a.duration = 500L
|
onStart = {
|
||||||
startAnimation(a)
|
isVisible = true
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
tag = anim
|
||||||
|
anim.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun View.collapse() {
|
fun View.collapse(duration: Long = 500L) {
|
||||||
if (visibility != View.GONE) {
|
clearAnimation()
|
||||||
|
try {
|
||||||
|
val animator = (tag as ValueAnimator)
|
||||||
|
animator.removeAllListeners()
|
||||||
|
animator.cancel()
|
||||||
|
} catch (ex: java.lang.Exception) {}
|
||||||
val initialHeight = measuredHeight
|
val initialHeight = measuredHeight
|
||||||
|
val anim = ValueAnimator.ofFloat(
|
||||||
val a = object : Animation() {
|
alpha,
|
||||||
protected override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
|
0f
|
||||||
if (interpolatedTime == 1f) {
|
).apply {
|
||||||
visibility = View.GONE
|
this.duration = duration
|
||||||
} else {
|
addUpdateListener {
|
||||||
layoutParams.height = initialHeight - (initialHeight * interpolatedTime).toInt()
|
val animatedValue = animatedValue as Float
|
||||||
requestLayout()
|
layoutParams = layoutParams.apply {
|
||||||
|
height = (initialHeight * animatedValue).toInt()
|
||||||
}
|
}
|
||||||
|
translationY = (initialHeight * animatedValue - initialHeight)
|
||||||
|
alpha = animatedValue
|
||||||
}
|
}
|
||||||
|
addListener(
|
||||||
override fun willChangeBounds(): Boolean {
|
onEnd = {
|
||||||
return true
|
isVisible = false
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
tag = anim
|
||||||
a.duration = 500L //(initialHeight / v.context.resources.displayMetrics.density).toLong()
|
anim.start()
|
||||||
startAnimation(a)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Context.openURI(url: String) {
|
fun Context.openURI(url: String) {
|
||||||
@ -143,11 +169,11 @@ fun Context.isTablet(): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun String.md5(): String {
|
fun String.md5(): String {
|
||||||
val MD5 = "MD5"
|
val mD5 = "MD5"
|
||||||
try {
|
try {
|
||||||
// Create MD5 Hash
|
// Create MD5 Hash
|
||||||
val digest = java.security.MessageDigest
|
val digest = java.security.MessageDigest
|
||||||
.getInstance(MD5)
|
.getInstance(mD5)
|
||||||
digest.update(toByteArray())
|
digest.update(toByteArray())
|
||||||
val messageDigest = digest.digest()
|
val messageDigest = digest.digest()
|
||||||
|
|
||||||
@ -172,7 +198,7 @@ fun String.isValidEmail(): Boolean
|
|||||||
= this.isNotEmpty() &&
|
= this.isNotEmpty() &&
|
||||||
Patterns.EMAIL_ADDRESS.matcher(this).matches()
|
Patterns.EMAIL_ADDRESS.matcher(this).matches()
|
||||||
|
|
||||||
fun Activity.isDarkTheme(): Boolean {
|
fun Context.isDarkTheme(): Boolean {
|
||||||
return 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BIN
app/src/main/res/drawable-hdpi/ic_capitalize.png
Normal file
BIN
app/src/main/res/drawable-hdpi/ic_capitalize.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 471 B |
BIN
app/src/main/res/drawable-hdpi/outline_info_white.png
Normal file
BIN
app/src/main/res/drawable-hdpi/outline_info_white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 518 B |
BIN
app/src/main/res/drawable-hdpi/outline_info_white_18.png
Normal file
BIN
app/src/main/res/drawable-hdpi/outline_info_white_18.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 449 B |
BIN
app/src/main/res/drawable-hdpi/outline_info_white_36.png
Normal file
BIN
app/src/main/res/drawable-hdpi/outline_info_white_36.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 751 B |
BIN
app/src/main/res/drawable-hdpi/outline_info_white_48.png
Normal file
BIN
app/src/main/res/drawable-hdpi/outline_info_white_48.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 953 B |
BIN
app/src/main/res/drawable-hdpi/round_api_white_18.png
Normal file
BIN
app/src/main/res/drawable-hdpi/round_api_white_18.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 329 B |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user