Compare commits
76 Commits
v2.0.5-bet
...
v2.0.9
Author | SHA1 | Date | |
---|---|---|---|
4c27d1dd9b | |||
eba5575ee2 | |||
aff7e407ca | |||
f7fc31d968 | |||
90b588603d | |||
5d9bd11abb | |||
01005ec443 | |||
eaf6400e8b | |||
30339c7375 | |||
87da284be4 | |||
573c6d03e5 | |||
79e87b0648 | |||
9e9a91690e | |||
5f699af509 | |||
aae40b9dd3 | |||
cebd679856 | |||
06443ddddb | |||
233761a169 | |||
b81461f725 | |||
26b1948b70 | |||
af64818dff | |||
b04b103634 | |||
1dc050e77f | |||
ff171d4022 | |||
d91471d1ee | |||
ac381c8542 | |||
ba5a860e75 | |||
09bc9df22f | |||
385806413e | |||
7d2ea5a4d8 | |||
ce9f5a6e45 | |||
8f0f6bc868 | |||
34d8fa4b59 | |||
9401b89036 | |||
842c0d764f | |||
1754b4045b | |||
f28596c194 | |||
7f41a92a91 | |||
9a63b9bde2 | |||
26428b65da | |||
97d1caeabc | |||
f013be5a7a | |||
4cc55edb15 | |||
d08ad6171e | |||
9e2eacef73 | |||
f8f8a8f051 | |||
60531061d7 | |||
654ec3fe66 | |||
40c9253159 | |||
d86d2cadd4 | |||
cb6c2c7764 | |||
6a4cfdf22b | |||
0b9e9e081e | |||
15884bd9b2 | |||
0adf192965 | |||
d72ba08960 | |||
1848951a74 | |||
5ca06e817e | |||
37cb43dc80 | |||
ea372dd76d | |||
7076311e94 | |||
2e684e0902 | |||
e2503decd2 | |||
f13cee24d5 | |||
f5c4ee7eb0 | |||
4feb72381d | |||
bea0803c3a | |||
dd450443c8 | |||
6279846cea | |||
364d8b2307 | |||
e990b229c8 | |||
c97127e3ab | |||
9d72c168b6 | |||
614d001df8 | |||
890101b2b3 | |||
a4b37ad5ad |
32
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: tommasoberlose
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Smartphone (please complete the following information):**
|
||||||
|
- Device: [e.g. OnePlus 6]
|
||||||
|
- OS Version: [e.g. Android 9.0]
|
||||||
|
- App Version (that you can find inside the advanced settings) [e.g. v2.0.5 (71)]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: tommasoberlose
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
5
.gitignore
vendored
@ -1,9 +1,10 @@
|
|||||||
*.iml
|
*.iml
|
||||||
.gradle
|
.gradle
|
||||||
/local.properties
|
/local.properties
|
||||||
/.idea/workspace.xml
|
/.idea/*
|
||||||
/.idea/libraries
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/build
|
/build
|
||||||
/captures
|
/captures
|
||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
|
/tasksintegration/build
|
||||||
|
/app/google-services.json
|
||||||
|
BIN
.idea/caches/build_file_checksums.ser
generated
1
.idea/gradle.xml
generated
@ -11,7 +11,6 @@
|
|||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
<option value="$PROJECT_DIR$/tasksintegration" />
|
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
<option name="resolveModulePerSourceSet" value="false" />
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
|
1
.idea/modules.xml
generated
@ -4,7 +4,6 @@
|
|||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/Another Widget.iml" filepath="$PROJECT_DIR$/Another Widget.iml" group="Another Widget" />
|
<module fileurl="file://$PROJECT_DIR$/Another Widget.iml" filepath="$PROJECT_DIR$/Another Widget.iml" group="Another Widget" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" group="Another Widget/app" />
|
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" group="Another Widget/app" />
|
||||||
<module fileurl="file://$PROJECT_DIR$/tasksintegration/tasksintegration.iml" filepath="$PROJECT_DIR$/tasksintegration/tasksintegration.iml" group="Another Widget/tasksintegration" />
|
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
52
.idea/navEditor.xml
generated
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="navEditor-manualLayoutAlgorithm2">
|
||||||
|
<option name="myPositions">
|
||||||
|
<map>
|
||||||
|
<entry key="nav_graph.xml">
|
||||||
|
<value>
|
||||||
|
<LayoutPositions>
|
||||||
|
<option name="myPositions">
|
||||||
|
<map>
|
||||||
|
<entry key="appMainFragment">
|
||||||
|
<value>
|
||||||
|
<LayoutPositions>
|
||||||
|
<option name="myPosition">
|
||||||
|
<Point>
|
||||||
|
<option name="x" value="242" />
|
||||||
|
<option name="y" value="352" />
|
||||||
|
</Point>
|
||||||
|
</option>
|
||||||
|
<option name="myPositions">
|
||||||
|
<map>
|
||||||
|
<entry key="action_appMainFragment_to_appSettingsFragment">
|
||||||
|
<value>
|
||||||
|
<LayoutPositions />
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</LayoutPositions>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="appSettingsFragment">
|
||||||
|
<value>
|
||||||
|
<LayoutPositions>
|
||||||
|
<option name="myPosition">
|
||||||
|
<Point>
|
||||||
|
<option name="x" value="532" />
|
||||||
|
<option name="y" value="353" />
|
||||||
|
</Point>
|
||||||
|
</option>
|
||||||
|
</LayoutPositions>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</LayoutPositions>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020 Tommaso Berlose
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
27
README.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
<img src="hero.png"/>
|
||||||
|
|
||||||
|
Another Widget
|
||||||
|
========
|
||||||
|
|
||||||
|
Another Widget intelligently summarizes the information you need most.
|
||||||
|
Watch the next events, the weather, and the information you want in an intuitive and elegant way. (Nope, reminders cannot be displayed because it's not allowed.)
|
||||||
|
|
||||||
|
While respecting the design of the application, there is a great opportunity to customize the information displayed and widget components.
|
||||||
|
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.
|
||||||
|
<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>
|
||||||
|
|
||||||
|
|
||||||
|
Help with translations
|
||||||
|
-------
|
||||||
|
|
||||||
|
Hey! You could view the file strings.xml ([here](https://github.com/tommasoberlose/another-widget/blob/master/app/src/main/res/values/strings.xml)) that contains the English version of the app strings.
|
||||||
|
You have to copy the file, create a copy of it inside the folder values-[LANGUAGE-SUFFIX] with the translated strings and create a pull request to submit your changes.
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
Copyright (C) 2017-2020 Tommaso Berlose (http://tommasoberlose.com)
|
||||||
|
|
||||||
|
Another Widget binaries and source code can be used according to the [MIT Licence](LICENSE).
|
@ -18,8 +18,8 @@ android {
|
|||||||
applicationId "com.tommasoberlose.anotherwidget"
|
applicationId "com.tommasoberlose.anotherwidget"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 59
|
versionCode 96
|
||||||
versionName "2.0.5"
|
versionName "2.0.9"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
@ -52,22 +52,19 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewBinding.enabled = true
|
viewBinding.enabled = true
|
||||||
|
|
||||||
dynamicFeatures = [":tasksintegration"]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
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.appcompat:appcompat:1.1.0'
|
|
||||||
implementation 'androidx.core:core-ktx:1.2.0'
|
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
|
||||||
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'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
implementation 'com.google.android.material:material:1.2.0-alpha06'
|
implementation 'com.google.android.material:material:1.2.0-alpha06'
|
||||||
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'
|
||||||
@ -78,6 +75,8 @@ 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"
|
||||||
|
|
||||||
// EventBus
|
// EventBus
|
||||||
implementation 'org.greenrobot:eventbus:3.1.1'
|
implementation 'org.greenrobot:eventbus:3.1.1'
|
||||||
|
|
||||||
@ -89,9 +88,16 @@ dependencies {
|
|||||||
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.9.9'
|
||||||
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'
|
||||||
|
|
||||||
|
//Glide
|
||||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||||
kapt 'com.github.bumptech.glide:compiler:4.11.0'
|
kapt 'com.github.bumptech.glide:compiler:4.11.0'
|
||||||
|
|
||||||
|
// Fitness
|
||||||
|
implementation 'com.google.android.gms:play-services-fitness:18.0.0'
|
||||||
|
implementation 'com.google.android.gms:play-services-auth:18.0.0'
|
||||||
|
|
||||||
//Weather
|
//Weather
|
||||||
implementation 'com.github.KwabenBerko:OpenWeatherMap-Android-Library:2.0.2'
|
implementation 'com.github.KwabenBerko:OpenWeatherMap-Android-Library:2.0.2'
|
||||||
implementation 'com.google.android.gms:play-services-location:17.0.0'
|
implementation 'com.google.android.gms:play-services-location:17.0.0'
|
||||||
@ -104,9 +110,7 @@ dependencies {
|
|||||||
implementation "androidx.core:core-ktx:1.2.0"
|
implementation "androidx.core:core-ktx:1.2.0"
|
||||||
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'
|
||||||
// Recommended: Add the Firebase SDK for Google Analytics.
|
|
||||||
implementation 'com.google.firebase:firebase-analytics:17.4.0'
|
|
||||||
|
|
||||||
// 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.0.0'
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
{
|
|
||||||
"project_info": {
|
|
||||||
"project_number": "791844924473",
|
|
||||||
"firebase_url": "https://anotherwidget-182008.firebaseio.com",
|
|
||||||
"project_id": "anotherwidget-182008",
|
|
||||||
"storage_bucket": "anotherwidget-182008.appspot.com"
|
|
||||||
},
|
|
||||||
"client": [
|
|
||||||
{
|
|
||||||
"client_info": {
|
|
||||||
"mobilesdk_app_id": "1:791844924473:android:0ad4f6e3890f1ad320b1e8",
|
|
||||||
"android_client_info": {
|
|
||||||
"package_name": "com.tommasoberlose.anotherwidget"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"oauth_client": [
|
|
||||||
{
|
|
||||||
"client_id": "791844924473-73dh46rorjq8vm97dgbn6can2dcpqlf0.apps.googleusercontent.com",
|
|
||||||
"client_type": 3
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"api_key": [
|
|
||||||
{
|
|
||||||
"current_key": "AIzaSyAeJRXstqnzebibxmm3FRM98nbwE_kC8tA"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"services": {
|
|
||||||
"appinvite_service": {
|
|
||||||
"other_platform_oauth_client": [
|
|
||||||
{
|
|
||||||
"client_id": "791844924473-73dh46rorjq8vm97dgbn6can2dcpqlf0.apps.googleusercontent.com",
|
|
||||||
"client_type": 3
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"configuration_version": "1"
|
|
||||||
}
|
|
@ -1,13 +1,19 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="com.tommasoberlose.anotherwidget">
|
package="com.tommasoberlose.anotherwidget">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="com.android.vending.BILLING" />
|
<uses-permission android:name="com.android.vending.BILLING" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
|
||||||
|
<uses-permission android:name="android.gms.permission.ACTIVITY_RECOGNITION"/>
|
||||||
|
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
|
||||||
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
@ -16,19 +22,21 @@
|
|||||||
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:theme="@style/AppTheme">
|
android:theme="@style/AppTheme"
|
||||||
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" android:theme="@style/AppTheme.Main">
|
tools:ignore="LockedOrientationActivity">
|
||||||
|
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" android:theme="@style/AppTheme.Main" android:screenOrientation="portrait">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".ui.activities.ChooseApplicationActivity" android:launchMode="singleInstance" />
|
<activity android:name=".ui.activities.ChooseApplicationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.CustomLocationActivity" android:launchMode="singleInstance" />
|
<activity android:name=".ui.activities.CustomLocationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.WeatherProviderActivity" android:launchMode="singleInstance" />
|
<activity android:name=".ui.activities.WeatherProviderActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.SupportDevActivity" android:launchMode="singleInstance" />
|
<activity android:name=".ui.activities.SupportDevActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.CustomDateActivity" android:launchMode="singleInstance" />
|
<activity android:name=".ui.activities.CustomDateActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
|
<activity android:name=".ui.activities.IntegrationsActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
||||||
|
|
||||||
|
|
||||||
<receiver android:name=".ui.widgets.MainWidget">
|
<receiver android:name=".ui.widgets.MainWidget">
|
||||||
@ -62,11 +70,14 @@
|
|||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_CALENDAR_UPDATE" />
|
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_CALENDAR_UPDATE" />
|
||||||
|
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_TIME_UPDATE" />
|
||||||
<action android:name="com.sec.android.widgetapp.APPWIDGET_RESIZE" />
|
<action android:name="com.sec.android.widgetapp.APPWIDGET_RESIZE" />
|
||||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||||
<action android:name="android.app.action.NEXT_ALARM_CLOCK_CHANGED" />
|
<action android:name="android.app.action.NEXT_ALARM_CLOCK_CHANGED" />
|
||||||
<action android:name="android.intent.action.DATE_CHANGED" />
|
<action android:name="android.intent.action.DATE_CHANGED" />
|
||||||
<action android:name="android.intent.action.TIME_SET" />
|
<action android:name="android.intent.action.TIME_SET" />
|
||||||
|
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
|
||||||
|
<action android:name="android.intent.action.LOCALE_CHANGED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver
|
<receiver
|
||||||
@ -74,11 +85,13 @@
|
|||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
|
||||||
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_WEATHER_UPDATE" />
|
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_WEATHER_UPDATE" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
<action android:name="android.intent.action.TIME_SET" />
|
<action android:name="android.intent.action.TIME_SET" />
|
||||||
|
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
|
||||||
|
<action android:name="android.intent.action.LOCALE_CHANGED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
@ -91,8 +104,47 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name=".receivers.CrashlyticsReceiver"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.tommasoberlose.anotherwidget.action.ACTION_REPORT_CRASH" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
<service android:name=".services.EventListenerJob" android:permission="android.permission.BIND_JOB_SERVICE" />
|
<service android:name=".services.EventListenerJob" android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||||
|
|
||||||
|
<service android:name=".services.BatteryListenerJob" android:permission="android.permission.BIND_JOB_SERVICE" />
|
||||||
|
|
||||||
|
<service android:name=".receivers.MusicNotificationListener"
|
||||||
|
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.service.notification.NotificationListenerService" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<receiver android:name=".receivers.BatteryLevelReceiver"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
|
||||||
|
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
|
||||||
|
<action android:name="android.intent.action.BATTERY_LOW"/>
|
||||||
|
<action android:name="android.intent.action.BATTERY_OKAY"/>
|
||||||
|
<action android:name="android.intent.action.BATTERY_CHANGED"/>
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<receiver android:name=".receivers.ActivityDetectionReceiver"
|
||||||
|
android:exported="false"
|
||||||
|
android:permission="com.google.android.gms.permission.ACTIVITY_RECOGNITION">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="com.mypackage.ACTION_PROCESS_ACTIVITY_TRANSITIONS" />
|
||||||
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
@ -1,6 +1,7 @@
|
|||||||
package com.tommasoberlose.anotherwidget
|
package com.tommasoberlose.anotherwidget
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.util.Log
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import com.chibatching.kotpref.Kotpref
|
import com.chibatching.kotpref.Kotpref
|
||||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
@ -34,7 +35,7 @@ class AWApplication : Application() {
|
|||||||
private fun calibrateVersions() {
|
private fun calibrateVersions() {
|
||||||
// 2.0 Tolerance
|
// 2.0 Tolerance
|
||||||
if (Preferences.clockTextSize > 50f) {
|
if (Preferences.clockTextSize > 50f) {
|
||||||
Preferences.clockTextSize = 46f
|
Preferences.clockTextSize = 32f
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Preferences.textMainSize > 36f) {
|
if (Preferences.textMainSize > 36f) {
|
||||||
|
@ -8,80 +8,132 @@ import android.text.TextWatcher
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.GridLayout
|
import android.widget.GridLayout
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.SeekBar
|
||||||
import androidx.annotation.ColorInt
|
import androidx.annotation.ColorInt
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.widget.addTextChangedListener
|
import androidx.core.widget.addTextChangedListener
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||||
import com.tommasoberlose.anotherwidget.utils.expand
|
import com.tommasoberlose.anotherwidget.utils.expand
|
||||||
import com.tommasoberlose.anotherwidget.utils.reveal
|
import com.tommasoberlose.anotherwidget.utils.reveal
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||||
|
import com.warkiz.widget.IndicatorSeekBar
|
||||||
|
import com.warkiz.widget.OnSeekChangeListener
|
||||||
|
import com.warkiz.widget.SeekParams
|
||||||
import kotlinx.android.synthetic.main.bottom_sheet_menu_hor.*
|
import kotlinx.android.synthetic.main.bottom_sheet_menu_hor.*
|
||||||
import kotlinx.android.synthetic.main.bottom_sheet_menu_hor.view.*
|
import kotlinx.android.synthetic.main.bottom_sheet_menu_hor.view.*
|
||||||
import kotlinx.android.synthetic.main.bottom_sheet_menu_hor.view.color_loader
|
import kotlinx.android.synthetic.main.bottom_sheet_menu_hor.view.color_loader
|
||||||
import kotlinx.android.synthetic.main.color_picker_menu_item.view.*
|
import kotlinx.android.synthetic.main.color_picker_menu_item.view.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
import java.util.prefs.Preferences
|
import java.util.prefs.Preferences
|
||||||
|
|
||||||
class BottomSheetColorPicker(
|
class BottomSheetColorPicker(
|
||||||
context: Context,
|
context: Context,
|
||||||
private val colors: IntArray = intArrayOf(),
|
private val colors: IntArray = intArrayOf(),
|
||||||
private val selected: Int? = null,
|
private val getSelected: (() -> Int)? = null,
|
||||||
private val header: String? = null,
|
private val header: String? = null,
|
||||||
private val onColorSelected: ((selectedValue: Int) -> Unit)? = null
|
private val onColorSelected: ((selectedValue: Int) -> Unit)? = null,
|
||||||
|
private val showAlphaSelector: Boolean = false,
|
||||||
|
private val alpha: Int = 0,
|
||||||
|
private val onAlphaChangeListener: ((alpha: Int) -> Unit)? = null
|
||||||
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||||
|
|
||||||
private val loadingJob: Job? = null
|
private var loadingJobs: ArrayList<Job> = ArrayList()
|
||||||
|
private lateinit var adapter: SlimAdapter
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {
|
||||||
val view = View.inflate(context, R.layout.bottom_sheet_menu_hor, null)
|
val view = View.inflate(context, R.layout.bottom_sheet_menu_hor, null)
|
||||||
|
|
||||||
|
window?.setDimAmount(0f)
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
view.header.isVisible = header != null
|
view.header.isVisible = header != null
|
||||||
view.header_text.text = header ?: ""
|
view.header_text.text = header ?: ""
|
||||||
|
|
||||||
val itemViews: ArrayList<View> = ArrayList()
|
// Alpha
|
||||||
|
view.alpha_selector_container.isVisible = showAlphaSelector
|
||||||
|
view.alpha_selector.setProgress(alpha.toFloat())
|
||||||
|
view.text_alpha.text = "%s: %s%%".format(context.getString(R.string.alpha), alpha)
|
||||||
|
view.alpha_selector.onSeekChangeListener = object : OnSeekChangeListener {
|
||||||
|
override fun onSeeking(seekParams: SeekParams?) {
|
||||||
|
seekParams?.let {
|
||||||
|
view.text_alpha.text = "%s: %s%%".format(context.getString(R.string.alpha), it.progress)
|
||||||
|
onAlphaChangeListener?.invoke(it.progress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override fun onStartTrackingTouch(seekBar: IndicatorSeekBar?) {
|
||||||
|
}
|
||||||
|
override fun onStopTrackingTouch(seekBar: IndicatorSeekBar?) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
// List
|
||||||
for (@ColorInt color: Int in colors) {
|
|
||||||
val itemView = View.inflate(context, R.layout.color_picker_menu_item, null)
|
adapter = SlimAdapter.create()
|
||||||
itemView.color.setCardBackgroundColor(ColorStateList.valueOf(color))
|
|
||||||
itemView.check.setColorFilter(ContextCompat.getColor(context,
|
loadingJobs.add(GlobalScope.launch(Dispatchers.IO) {
|
||||||
if (color.isColorDark()) android.R.color.white else android.R.color.black
|
val listView = View.inflate(context, R.layout.bottom_sheet_menu_list, null) as RecyclerView
|
||||||
), android.graphics.PorterDuff.Mode.MULTIPLY)
|
listView.setHasFixedSize(true)
|
||||||
itemView.check.isVisible = selected == color
|
val mLayoutManager = GridLayoutManager(context, 6)
|
||||||
itemView.color.setOnClickListener {
|
listView.layoutManager = mLayoutManager
|
||||||
onColorSelected?.invoke(color)
|
|
||||||
this@BottomSheetColorPicker.dismiss()
|
adapter
|
||||||
|
.register<Int>(R.layout.color_picker_menu_item) { item, injector ->
|
||||||
|
injector
|
||||||
|
.with<MaterialCardView>(R.id.color) {
|
||||||
|
it.setCardBackgroundColor(ColorStateList.valueOf(item))
|
||||||
}
|
}
|
||||||
itemViews.add(itemView)
|
.with<AppCompatImageView>(R.id.check) {
|
||||||
|
if (getSelected?.invoke() == item) {
|
||||||
|
it.setColorFilter(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
context,
|
||||||
|
if (item.isColorDark()) android.R.color.white else android.R.color.black
|
||||||
|
),
|
||||||
|
android.graphics.PorterDuff.Mode.MULTIPLY
|
||||||
|
)
|
||||||
|
it.isVisible = true
|
||||||
|
} else {
|
||||||
|
it.isVisible = false
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.clicked(R.id.color) {
|
||||||
|
adapter.notifyItemChanged(adapter.data.indexOf(getSelected?.invoke()))
|
||||||
|
onColorSelected?.invoke(item)
|
||||||
|
val position = adapter.data.indexOf(item)
|
||||||
|
adapter.notifyItemChanged(position)
|
||||||
|
(listView.layoutManager as GridLayoutManager).scrollToPositionWithOffset(position,0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.attachTo(listView)
|
||||||
|
|
||||||
|
adapter.updateData(colors.toList())
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
itemViews.forEach {
|
view.color_loader.isVisible = false
|
||||||
view.menu.addView(it, GridLayout.LayoutParams(
|
view.list_container.addView(listView)
|
||||||
GridLayout.spec(GridLayout.UNDEFINED, 1f),
|
|
||||||
GridLayout.spec(GridLayout.UNDEFINED, 1f)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
color_loader.isVisible = false
|
|
||||||
view.menu.isVisible = true
|
|
||||||
this@BottomSheetColorPicker.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
this@BottomSheetColorPicker.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
view.list_container.isVisible = true
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
// Menu
|
|
||||||
|
|
||||||
setContentView(view)
|
setContentView(view)
|
||||||
super.show()
|
super.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
loadingJob?.cancel()
|
loadingJobs.forEach { it.cancel() }
|
||||||
super.onStop()
|
super.onStop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,11 @@
|
|||||||
package com.tommasoberlose.anotherwidget.components
|
package com.tommasoberlose.anotherwidget.components
|
||||||
|
|
||||||
import android.app.Dialog
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.annotation.MenuRes
|
|
||||||
import androidx.appcompat.widget.AppCompatTextView
|
|
||||||
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
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import com.google.android.material.card.MaterialCardView
|
|
||||||
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.*
|
||||||
@ -21,7 +15,7 @@ import kotlinx.android.synthetic.main.bottom_sheet_menu_item.view.*
|
|||||||
* theme which sets a rounded background to the dialog
|
* theme which sets a rounded background to the dialog
|
||||||
* and doesn't dim the navigation bar
|
* and doesn't dim the navigation bar
|
||||||
*/
|
*/
|
||||||
open class BottomSheetMenu<T>(context: Context, private val header: String? = null, private val isMultiSelection: Boolean = false) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
open class BottomSheetMenu<T>(context: Context, private val header: String? = null, private val message: String? = null, private val isMessageWarning: Boolean = false, private val isMultiSelection: Boolean = false) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||||
|
|
||||||
private val items: ArrayList<MenuItem<T>> = ArrayList()
|
private val items: ArrayList<MenuItem<T>> = ArrayList()
|
||||||
private var selectedRes: ArrayList<T> = ArrayList()
|
private var selectedRes: ArrayList<T> = ArrayList()
|
||||||
@ -60,6 +54,10 @@ open class BottomSheetMenu<T>(context: Context, private val header: String? = nu
|
|||||||
view.header.isVisible = header != null
|
view.header.isVisible = header != null
|
||||||
view.header_text.text = header ?: ""
|
view.header_text.text = header ?: ""
|
||||||
|
|
||||||
|
view.warning_text.isVisible = message != null
|
||||||
|
view.warning_text.text = message ?: ""
|
||||||
|
view.warning_text.setTextColor(ContextCompat.getColor(context, if (isMessageWarning) R.color.warningColorText else R.color.colorSecondaryText))
|
||||||
|
|
||||||
// Menu
|
// Menu
|
||||||
for (item in items) {
|
for (item in items) {
|
||||||
if (item.value != null) {
|
if (item.value != null) {
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.components
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.View
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import kotlinx.android.synthetic.main.custom_notes_dialog_layout.view.*
|
||||||
|
|
||||||
|
class CustomNotesDialog(context: Context) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
val view = View.inflate(context, R.layout.custom_notes_dialog_layout, null)
|
||||||
|
view.notes.setText(Preferences.customNotes)
|
||||||
|
|
||||||
|
view.action_positive.setOnClickListener {
|
||||||
|
Preferences.customNotes = view.notes.text.toString()
|
||||||
|
this.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
view.notes.requestFocus()
|
||||||
|
|
||||||
|
setContentView(view)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
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,63 @@
|
|||||||
|
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 kotlinx.android.synthetic.main.bottom_sheet_dialog.view.*
|
||||||
|
|
||||||
|
typealias DialogCallback = () -> Unit
|
||||||
|
|
||||||
|
class MaterialBottomSheetDialog(
|
||||||
|
context: Context,
|
||||||
|
private val title: String? = "",
|
||||||
|
private val message: String? = ""
|
||||||
|
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||||
|
|
||||||
|
private var positiveButtonLabel: String? = null
|
||||||
|
private var negativeButtonLabel: String? = null
|
||||||
|
private var positiveCallback: DialogCallback? = null
|
||||||
|
private var negativeCallback: DialogCallback? = null
|
||||||
|
|
||||||
|
fun setPositiveButton(label: String? = context.getString(android.R.string.ok), callback: DialogCallback? = null): MaterialBottomSheetDialog {
|
||||||
|
positiveButtonLabel = label
|
||||||
|
positiveCallback = callback
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setNegativeButton(label: String? = context.getString(android.R.string.cancel), callback: DialogCallback? = null): MaterialBottomSheetDialog {
|
||||||
|
negativeButtonLabel = label
|
||||||
|
negativeCallback = callback
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun show() {
|
||||||
|
val view = View.inflate(context, R.layout.bottom_sheet_dialog, null)
|
||||||
|
|
||||||
|
// Header
|
||||||
|
view.message.isVisible = title != null
|
||||||
|
view.title.text = title ?: ""
|
||||||
|
|
||||||
|
view.message.isVisible = message != null
|
||||||
|
view.message.text = message ?: ""
|
||||||
|
|
||||||
|
view.action_positive.isVisible = positiveButtonLabel != null
|
||||||
|
view.action_positive.text = positiveButtonLabel ?: ""
|
||||||
|
view.action_positive.setOnClickListener {
|
||||||
|
positiveCallback?.invoke()
|
||||||
|
this.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
view.action_negative.isVisible = negativeButtonLabel != null
|
||||||
|
view.action_negative.text = negativeButtonLabel ?: ""
|
||||||
|
view.action_negative.setOnClickListener {
|
||||||
|
negativeCallback?.invoke()
|
||||||
|
this.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
setContentView(view)
|
||||||
|
super.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package com.tommasoberlose.anotherwidget.db
|
package com.tommasoberlose.anotherwidget.db
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
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.models.Event
|
import com.tommasoberlose.anotherwidget.models.Event
|
||||||
@ -8,22 +9,26 @@ 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 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: ArrayList<Event>) {
|
||||||
realm.executeTransactionAsync { realm ->
|
realm.executeTransaction { realm ->
|
||||||
realm.where(Event::class.java).findAll().deleteAllFromRealm()
|
realm.where(Event::class.java).findAll().deleteAllFromRealm()
|
||||||
realm.copyToRealm(eventList)
|
realm.copyToRealm(eventList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resetNextEventData() {
|
fun clearEvents() {
|
||||||
realm.executeTransactionAsync {
|
realm.executeTransaction { realm ->
|
||||||
it.where(Event::class.java).findAll().deleteAllFromRealm()
|
realm.where(Event::class.java).findAll().deleteAllFromRealm()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun resetNextEventData() {
|
||||||
Preferences.bulk {
|
Preferences.bulk {
|
||||||
remove(Preferences::nextEventId)
|
remove(Preferences::nextEventId)
|
||||||
remove(Preferences::nextEventName)
|
remove(Preferences::nextEventName)
|
||||||
@ -33,26 +38,66 @@ class EventRepository(val context: Context) {
|
|||||||
remove(Preferences::nextEventEndDate)
|
remove(Preferences::nextEventEndDate)
|
||||||
remove(Preferences::nextEventCalendarId)
|
remove(Preferences::nextEventCalendarId)
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWidget.updateWidget(context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveNextEventData(event: Event) {
|
fun saveNextEventData(event: Event) {
|
||||||
Preferences.nextEventId = event.id
|
Preferences.nextEventId = event.eventID
|
||||||
MainWidget.updateWidget(context)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNextEvent(): Event? = realm.where(Event::class.java).equalTo("id", Preferences.nextEventId).findFirst() ?: realm.where(Event::class.java).findFirst()
|
fun getNextEvent(): Event? {
|
||||||
|
val nextEvent = getEventByEventId(Preferences.nextEventId)
|
||||||
|
val now = Calendar.getInstance().timeInMillis
|
||||||
|
val limit = Calendar.getInstance().apply {
|
||||||
|
timeInMillis = now
|
||||||
|
when (Preferences.showUntil) {
|
||||||
|
0 -> add(Calendar.HOUR, 3)
|
||||||
|
1 -> add(Calendar.HOUR, 6)
|
||||||
|
2 -> add(Calendar.HOUR, 12)
|
||||||
|
3 -> add(Calendar.DAY_OF_MONTH, 1)
|
||||||
|
4 -> add(Calendar.DAY_OF_MONTH, 3)
|
||||||
|
5 -> add(Calendar.DAY_OF_MONTH, 7)
|
||||||
|
6 -> add(Calendar.MINUTE, 30)
|
||||||
|
7 -> add(Calendar.HOUR, 1)
|
||||||
|
else -> add(Calendar.HOUR, 6)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val event = if (nextEvent != null && nextEvent.endDate > now && nextEvent.startDate < limit.timeInMillis) {
|
||||||
|
nextEvent
|
||||||
|
} else {
|
||||||
|
val events = getEvents()
|
||||||
|
if (events.isNotEmpty()) {
|
||||||
|
val newNextEvent = events.first()
|
||||||
|
Preferences.nextEventId = newNextEvent!!.eventID
|
||||||
|
newNextEvent
|
||||||
|
} else {
|
||||||
|
resetNextEventData()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return try {
|
||||||
|
realm.copyFromRealm(event!!)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getEventByEventId(id: Long): Event? {
|
||||||
|
val event = realm.where(Event::class.java).equalTo("eventID", id).findFirst()
|
||||||
|
return try {
|
||||||
|
realm.copyFromRealm(event!!)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun goToNextEvent() {
|
fun goToNextEvent() {
|
||||||
val eventList = realm.where(Event::class.java).findAll()
|
val eventList = getEvents()
|
||||||
|
|
||||||
if (eventList.isNotEmpty()) {
|
if (eventList.isNotEmpty()) {
|
||||||
val index = eventList.indexOfFirst { it.id == Preferences.nextEventId }
|
val index = eventList.indexOfFirst { it.eventID == Preferences.nextEventId }
|
||||||
if (index > -1 && index < eventList.size - 1) {
|
if (index > -1 && index < eventList.size - 1) {
|
||||||
Preferences.nextEventId = eventList[index + 1]!!.id
|
Preferences.nextEventId = eventList[index + 1]!!.eventID
|
||||||
} else {
|
} else {
|
||||||
Preferences.nextEventId = eventList.first()!!.id
|
Preferences.nextEventId = eventList.first()!!.eventID
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
resetNextEventData()
|
resetNextEventData()
|
||||||
@ -62,14 +107,13 @@ class EventRepository(val context: Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun goToPreviousEvent() {
|
fun goToPreviousEvent() {
|
||||||
val eventList = realm.where(Event::class.java).findAll()
|
val eventList = getEvents()
|
||||||
|
|
||||||
if (eventList.isNotEmpty()) {
|
if (eventList.isNotEmpty()) {
|
||||||
val index = eventList.indexOfFirst { it.id == Preferences.nextEventId }
|
val index = eventList.indexOfFirst { it.eventID == Preferences.nextEventId }
|
||||||
if (index > 0) {
|
if (index > 0) {
|
||||||
Preferences.nextEventId = eventList[index - 1]!!.id
|
Preferences.nextEventId = eventList[index - 1]!!.eventID
|
||||||
} else {
|
} else {
|
||||||
Preferences.nextEventId = eventList.last()!!.id
|
Preferences.nextEventId = eventList.last()!!.eventID
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
resetNextEventData()
|
resetNextEventData()
|
||||||
@ -78,7 +122,35 @@ class EventRepository(val context: Context) {
|
|||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEvents(): RealmResults<Event> = realm.where(Event::class.java).findAll()
|
fun getFutureEvents(): RealmResults<Event> {
|
||||||
|
val now = Calendar.getInstance().timeInMillis
|
||||||
fun getEventsCount(): Int = realm.where(Event::class.java).findAll().size
|
realm.refresh()
|
||||||
|
return realm.where(Event::class.java).greaterThan("endDate", now).findAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getEvents(): RealmResults<Event> {
|
||||||
|
val now = Calendar.getInstance().timeInMillis
|
||||||
|
val limit = Calendar.getInstance().apply {
|
||||||
|
timeInMillis = now
|
||||||
|
when (Preferences.showUntil) {
|
||||||
|
0 -> add(Calendar.HOUR, 3)
|
||||||
|
1 -> add(Calendar.HOUR, 6)
|
||||||
|
2 -> add(Calendar.HOUR, 12)
|
||||||
|
3 -> add(Calendar.DAY_OF_MONTH, 1)
|
||||||
|
4 -> add(Calendar.DAY_OF_MONTH, 3)
|
||||||
|
5 -> add(Calendar.DAY_OF_MONTH, 7)
|
||||||
|
6 -> add(Calendar.MINUTE, 30)
|
||||||
|
7 -> add(Calendar.HOUR, 1)
|
||||||
|
else -> add(Calendar.HOUR, 6)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
realm.refresh()
|
||||||
|
return realm.where(Event::class.java).greaterThan("endDate", now).lessThanOrEqualTo("startDate", limit.timeInMillis).findAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getEventsCount(): Int = getEvents().size
|
||||||
|
|
||||||
|
fun close() {
|
||||||
|
realm.close()
|
||||||
|
}
|
||||||
}
|
}
|
@ -4,10 +4,11 @@ object Actions {
|
|||||||
const val ACTION_EXTRA_OPEN_WEATHER_PROVIDER = "ACTION_EXTRA_OPEN_WEATHER_PROVIDER"
|
const val ACTION_EXTRA_OPEN_WEATHER_PROVIDER = "ACTION_EXTRA_OPEN_WEATHER_PROVIDER"
|
||||||
const val ACTION_EXTRA_DISABLE_GPS_NOTIFICATION = "ACTION_EXTRA_DISABLE_GPS_NOTIFICATION"
|
const val ACTION_EXTRA_DISABLE_GPS_NOTIFICATION = "ACTION_EXTRA_DISABLE_GPS_NOTIFICATION"
|
||||||
|
|
||||||
const val ACTION_TIME_UPDATE = "com.tommasoberlose.anotherwidget.action.ACTION_TIME_UPDATE"
|
const val ACTION_TIME_UPDATE = "com.tommasoberlose.anotherwidget.action.TIME_UPDATE"
|
||||||
const val ACTION_CALENDAR_UPDATE = "com.tommasoberlose.anotherwidget.action.ACTION_CALENDAR_UPDATE"
|
const val ACTION_CALENDAR_UPDATE = "com.tommasoberlose.anotherwidget.action.CALENDAR_UPDATE"
|
||||||
const val ACTION_WEATHER_UPDATE = "com.tommasoberlose.anotherwidget.action.ACTION_WEATHER_UPDATE"
|
const val ACTION_WEATHER_UPDATE = "com.tommasoberlose.anotherwidget.action.WEATHER_UPDATE"
|
||||||
const val ACTION_OPEN_WEATHER_INTENT = "com.tommasoberlose.anotherwidget.action.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"
|
||||||
}
|
}
|
@ -7,63 +7,30 @@ 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 PREF_SHOW_EVENTS = "PREF_SHOW_EVENTS"
|
|
||||||
const val PREF_SHOW_WEATHER = "PREF_SHOW_WEATHER"
|
|
||||||
const val PREF_WEATHER_ICON = "PREF_WEATHER_ICON"
|
|
||||||
const val PREF_WEATHER_TEMP = "PREF_WEATHER_TEMP"
|
|
||||||
const val PREF_WEATHER_TEMP_UNIT = "PREF_WEATHER_TEMP_UNIT"
|
|
||||||
const val PREF_WEATHER_REAL_TEMP_UNIT = "PREF_WEATHER_REAL_TEMP_UNIT"
|
|
||||||
const val PREF_CALENDAR_ALL_DAY = "PREF_CALENDAR_ALL_DAY"
|
|
||||||
const val PREF_CALENDAR_FILTER = "PREF_CALENDAR_FILTER"
|
|
||||||
|
|
||||||
const val PREF_EVENT_ID = "PREF_EVENT_ID"
|
|
||||||
const val PREF_NEXT_EVENT_ID = "PREF_NEXT_EVENT_ID"
|
|
||||||
const val PREF_NEXT_EVENT_NAME = "PREF_NEXT_EVENT_NAME"
|
|
||||||
const val PREF_NEXT_EVENT_START_DATE = "PREF_NEXT_EVENT_START_DATE"
|
|
||||||
const val PREF_NEXT_EVENT_ALL_DAY = "PREF_NEXT_EVENT_ALL_DAY"
|
|
||||||
const val PREF_NEXT_EVENT_LOCATION = "PREF_NEXT_EVENT_LOCATION"
|
|
||||||
const val PREF_NEXT_EVENT_END_DATE = "PREF_NEXT_EVENT_END_DATE"
|
|
||||||
const val PREF_NEXT_EVENT_CALENDAR_ID = "PREF_NEXT_EVENT_CALENDAR_ID"
|
|
||||||
const val PREF_CUSTOM_LOCATION_LAT = "PREF_CUSTOM_LOCATION_LAT"
|
|
||||||
const val PREF_CUSTOM_LOCATION_LON = "PREF_CUSTOM_LOCATION_LON"
|
|
||||||
const val PREF_CUSTOM_LOCATION_ADD = "PREF_CUSTOM_LOCATION_ADD"
|
|
||||||
const val PREF_HOUR_FORMAT = "PREF_HOUR_FORMAT"
|
|
||||||
const val PREF_ITA_FORMAT_DATE = "PREF_ITA_FORMAT_DATE"
|
|
||||||
const val PREF_WEATHER_REFRESH_PERIOD = "PREF_WEATHER_REFRESH_PERIOD"
|
|
||||||
const val PREF_SHOW_UNTIL = "PREF_SHOW_UNTIL"
|
|
||||||
const val PREF_CALENDAR_APP_NAME = "PREF_CALENDAR_APP_NAME"
|
|
||||||
const val PREF_CALENDAR_APP_PACKAGE = "PREF_CALENDAR_APP_PACKAGE"
|
|
||||||
const val PREF_WEATHER_APP_NAME = "PREF_WEATHER_APP_NAME"
|
|
||||||
const val PREF_WEATHER_APP_PACKAGE = "PREF_WEATHER_APP_PACKAGE"
|
|
||||||
const val PREF_WEATHER_PROVIDER_API_KEY = "PREF_WEATHER_PROVIDER_API_KEY"
|
|
||||||
const val PREF_EVENT_APP_NAME = "PREF_EVENT_APP_NAME"
|
|
||||||
const val PREF_EVENT_APP_PACKAGE = "PREF_EVENT_APP_PACKAGE"
|
|
||||||
const val PREF_SHOW_EVENT_LOCATION = "PREF_SHOW_EVENT_LOCATION"
|
|
||||||
const val PREF_TEXT_COLOR = "PREF_TEXT_COLOR"
|
|
||||||
const val PREF_TEXT_MAIN_SIZE = "PREF_TEXT_MAIN_SIZE"
|
|
||||||
const val PREF_TEXT_SECOND_SIZE = "PREF_TEXT_SECOND_SIZE"
|
|
||||||
const val PREF_TEXT_CLOCK_SIZE = "PREF_TEXT_CLOCK_SIZE"
|
|
||||||
const val PREF_WEATHER_PROVIDER = "PREF_WEATHER_PROVIDER"
|
|
||||||
const val PREF_SHOW_CLOCK = "PREF_SHOW_CLOCK"
|
|
||||||
const val PREF_CLOCK_APP_NAME = "PREF_CLOCK_APP_NAME"
|
|
||||||
const val PREF_CLOCK_APP_PACKAGE = "PREF_CLOCK_APP_PACKAGE"
|
|
||||||
const val PREF_TEXT_SHADOW = "PREF_TEXT_SHADOW"
|
|
||||||
const val PREF_SHOW_DIFF_TIME = "PREF_SHOW_DIFF_TIME"
|
|
||||||
const val PREF_SHOW_DECLINED_EVENTS = "PREF_SHOW_DECLINED_EVENTS"
|
|
||||||
const val PREF_OPEN_WEATHER_API_KEY = "PREF_OPEN_WEATHER_API_KEY"
|
|
||||||
const val PREF_DARK_SKY_API_KEY = "PREF_DARK_SKY_API_KEY"
|
|
||||||
const val PREF_WU_API_KEY = "PREF_WU_API_KEY"
|
|
||||||
const val PREF_SECOND_ROW_INFORMATION = "PREF_SECOND_ROW_INFORMATION"
|
|
||||||
const val PREF_CUSTOM_FONT = "PREF_CUSTOM_FONT"
|
|
||||||
const val PREF_CUSTOM_FONT_FILE = "PREF_CUSTOM_FONT_FILE"
|
|
||||||
const val PREF_SHOW_NEXT_EVENT = "PREF_SHOW_NEXT_EVENT"
|
|
||||||
const val PREF_SHOW_WIDGET_PREVIEW = "PREF_SHOW_WIDGET_PREVIEW"
|
|
||||||
const val PREF_SHOW_GPS_NOTIFICATION = "PREF_SHOW_GPS_NOTIFICATION"
|
|
||||||
|
|
||||||
const val CUSTOM_FONT_PRODUCT_SANS = 1
|
const val CUSTOM_FONT_PRODUCT_SANS = 1
|
||||||
|
enum class ClockBottomMargin(val value: Int) {
|
||||||
const val itDateFormat = "EEEE, d MMM"
|
NONE(0),
|
||||||
const val engDateFormat = "EEEE, MMM d"
|
SMALL(1),
|
||||||
const val goodHourFormat = "HH:mm"
|
MEDIUM(2),
|
||||||
const val badHourFormat = "hh:mm a"
|
LARGE(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class GlanceProviderId(val id: String) {
|
||||||
|
PLAYING_SONG("PLAYING_SONG"),
|
||||||
|
NEXT_CLOCK_ALARM("NEXT_CLOCK_ALARM"),
|
||||||
|
BATTERY_LEVEL_LOW("BATTERY_LEVEL_LOW"),
|
||||||
|
CUSTOM_INFO("CUSTOM_INFO"),
|
||||||
|
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS")
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class WidgetUpdateFrequency(val value: Int) {
|
||||||
|
LOW(0),
|
||||||
|
DEFAULT(1),
|
||||||
|
HIGH(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class WeatherIconPack(val value: Int) {
|
||||||
|
DEFAULT(0),
|
||||||
|
MINIMAL(1)
|
||||||
|
}
|
||||||
}
|
}
|
@ -7,18 +7,18 @@ import com.chibatching.kotpref.KotprefModel
|
|||||||
object Preferences : KotprefModel() {
|
object Preferences : KotprefModel() {
|
||||||
override val commitAllPropertiesByDefault: Boolean = true
|
override val commitAllPropertiesByDefault: Boolean = true
|
||||||
|
|
||||||
var darkThemePreference by intPref(default = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) MODE_NIGHT_FOLLOW_SYSTEM else MODE_NIGHT_AUTO_BATTERY)
|
var darkThemePreference by intPref(default = MODE_NIGHT_FOLLOW_SYSTEM)
|
||||||
|
|
||||||
|
// Calendar and weather
|
||||||
var showEvents by booleanPref(key = "PREF_SHOW_EVENTS", default = false)
|
var showEvents by booleanPref(key = "PREF_SHOW_EVENTS", default = false)
|
||||||
var showWeather by booleanPref(key = "PREF_SHOW_WEATHER")
|
var showWeather by booleanPref(key = "PREF_SHOW_WEATHER", default = false)
|
||||||
var weatherIcon by stringPref(key = "PREF_WEATHER_ICON")
|
var weatherIcon by stringPref(key = "PREF_WEATHER_ICON", default = "")
|
||||||
var weatherTemp by floatPref(key = "PREF_WEATHER_TEMP")
|
var weatherTemp by floatPref(key = "PREF_WEATHER_TEMP", default = 0f)
|
||||||
var weatherTempUnit by stringPref(key = "PREF_WEATHER_TEMP_UNIT", default = "F")
|
var weatherTempUnit by stringPref(key = "PREF_WEATHER_TEMP_UNIT", default = "F")
|
||||||
var weatherRealTempUnit by stringPref(key = "PREF_WEATHER_REAL_TEMP_UNIT", default = "F")
|
var weatherRealTempUnit by stringPref(key = "PREF_WEATHER_REAL_TEMP_UNIT", default = "F")
|
||||||
var calendarAllDay by booleanPref(key = "PREF_CALENDAR_ALL_DAY", default = false)
|
var calendarAllDay by booleanPref(key = "PREF_CALENDAR_ALL_DAY", default = true)
|
||||||
var calendarFilter by stringPref(key = "PREF_CALENDAR_FILTER", default = "")
|
var calendarFilter by stringPref(key = "PREF_CALENDAR_FILTER", default = "")
|
||||||
|
|
||||||
var eventId by intPref(key = "PREF_EVENT_ID", default = -1)
|
|
||||||
var nextEventId by longPref(key = "PREF_NEXT_EVENT_ID", default = -1)
|
var nextEventId by longPref(key = "PREF_NEXT_EVENT_ID", default = -1)
|
||||||
var nextEventName by stringPref(key = "PREF_NEXT_EVENT_NAME")
|
var nextEventName by stringPref(key = "PREF_NEXT_EVENT_NAME")
|
||||||
var nextEventStartDate by longPref(key = "PREF_NEXT_EVENT_START_DATE")
|
var nextEventStartDate by longPref(key = "PREF_NEXT_EVENT_START_DATE")
|
||||||
@ -29,8 +29,8 @@ object Preferences : KotprefModel() {
|
|||||||
var customLocationLat by stringPref(key = "PREF_CUSTOM_LOCATION_LAT", default = "")
|
var customLocationLat by stringPref(key = "PREF_CUSTOM_LOCATION_LAT", default = "")
|
||||||
var customLocationLon by stringPref(key = "PREF_CUSTOM_LOCATION_LON", default = "")
|
var customLocationLon by stringPref(key = "PREF_CUSTOM_LOCATION_LON", default = "")
|
||||||
var customLocationAdd by stringPref(key = "PREF_CUSTOM_LOCATION_ADD", default = "")
|
var customLocationAdd by stringPref(key = "PREF_CUSTOM_LOCATION_ADD", default = "")
|
||||||
var hourFormat by stringPref(key = "PREF_HOUR_FORMAT", default = "12")
|
|
||||||
var dateFormat by stringPref(default = "")
|
var dateFormat by stringPref(default = "")
|
||||||
|
var isDateCapitalize by booleanPref(default = true)
|
||||||
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 = "")
|
||||||
@ -40,28 +40,68 @@ object Preferences : KotprefModel() {
|
|||||||
var weatherProviderApi by stringPref(key = "PREF_WEATHER_PROVIDER_API_KEY", default = "")
|
var weatherProviderApi by stringPref(key = "PREF_WEATHER_PROVIDER_API_KEY", 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 showEventLocation by stringPref(key = "PREF_SHOW_EVENT_LOCATION", default = "")
|
var openEventDetails by booleanPref(default = true)
|
||||||
|
|
||||||
|
var widgetUpdateFrequency by intPref(default = Constants.WidgetUpdateFrequency.DEFAULT.value)
|
||||||
|
|
||||||
var textGlobalColor by stringPref(key = "PREF_TEXT_COLOR", default = "#FFFFFF")
|
var textGlobalColor by stringPref(key = "PREF_TEXT_COLOR", default = "#FFFFFF")
|
||||||
|
var textGlobalAlpha by stringPref(default = "FF")
|
||||||
|
|
||||||
|
var textSecondaryColor by stringPref(default = "#FFFFFF")
|
||||||
|
var textSecondaryAlpha by stringPref(default = "FF")
|
||||||
|
|
||||||
|
var backgroundCardColor by stringPref(default = "#000000")
|
||||||
|
var backgroundCardAlpha by stringPref(default = "00")
|
||||||
|
|
||||||
|
var clockTextColor by stringPref(default = "#FFFFFF")
|
||||||
|
var clockTextAlpha by stringPref(default = "FF")
|
||||||
|
var showAMPMIndicator by booleanPref(default = true)
|
||||||
|
|
||||||
|
var weatherIconPack by intPref(default = Constants.WeatherIconPack.DEFAULT.value)
|
||||||
|
|
||||||
|
// Global
|
||||||
var textMainSize by floatPref(key = "PREF_TEXT_MAIN_SIZE", default = 26f)
|
var textMainSize by floatPref(key = "PREF_TEXT_MAIN_SIZE", default = 26f)
|
||||||
var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 18f)
|
var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 18f)
|
||||||
var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 90f)
|
var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 90f)
|
||||||
|
var clockBottomMargin by intPref(default = Constants.ClockBottomMargin.MEDIUM.value)
|
||||||
var 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 showNextAlarm by booleanPref(default = true)
|
|
||||||
var textShadow by intPref(key = "PREF_TEXT_SHADOW", default = 1)
|
var textShadow by intPref(key = "PREF_TEXT_SHADOW", default = 1)
|
||||||
var showDiffTime by booleanPref(key = "PREF_SHOW_DIFF_TIME")
|
var showDiffTime by booleanPref(key = "PREF_SHOW_DIFF_TIME", default = true)
|
||||||
var showDeclinedEvents by booleanPref(key = "PREF_SHOW_DECLINED_EVENTS", default = true)
|
var showDeclinedEvents by booleanPref(key = "PREF_SHOW_DECLINED_EVENTS", default = false)
|
||||||
var openWeatherApiKey by stringPref(key = "PREF_OPEN_WEATHER_API_KEY", default = "")
|
var secondRowInformation by intPref(key = "PREF_SECOND_ROW_INFORMATION", default = 0)
|
||||||
var darkSkyApiKey by stringPref(key = "PREF_DARK_SKY_API_KEY", default = "")
|
|
||||||
var wuApiKey by stringPref(key = "PREF_WU_API_KEY", default = "")
|
|
||||||
var secondRowInformation by intPref(key = "PREF_SECOND_ROW_INFORMATION", default = 1)
|
|
||||||
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_PRODUCT_SANS)
|
||||||
var customFontFile by stringPref(key = "PREF_CUSTOM_FONT_FILE")
|
var customFontFile by stringPref(key = "PREF_CUSTOM_FONT_FILE")
|
||||||
var showNextEvent by booleanPref(key = "PREF_SHOW_NEXT_EVENT", default = true)
|
var showNextEvent by booleanPref(key = "PREF_SHOW_NEXT_EVENT", default = true)
|
||||||
var showGpsInformation by booleanPref(key = "PREF_SHOW_GPS_NOTIFICATION", default = true)
|
|
||||||
|
|
||||||
var showWallpaper by booleanPref(default = false)
|
var showDividers by booleanPref(default = true)
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
var showWallpaper by booleanPref(default = true)
|
||||||
var showBigClockWarning by booleanPref(default = true)
|
var showBigClockWarning by booleanPref(default = true)
|
||||||
var showWeatherWarning by booleanPref(default = true)
|
var showWeatherWarning by booleanPref(default = true)
|
||||||
|
var showPreview by booleanPref(default = true)
|
||||||
|
var showXiaomiWarning by booleanPref(default = true)
|
||||||
|
|
||||||
|
// Glance
|
||||||
|
var showGlance by booleanPref(default = true)
|
||||||
|
var enabledGlanceProviderOrder by stringPref(default = "")
|
||||||
|
var customNotes by stringPref(default = "")
|
||||||
|
var showNextAlarm by booleanPref(default = true)
|
||||||
|
var showBatteryCharging by booleanPref(default = false)
|
||||||
|
var isBatteryLevelLow by booleanPref(default = false)
|
||||||
|
var isCharging by booleanPref(default = false)
|
||||||
|
var googleFitSteps by longPref(default = -1)
|
||||||
|
var showDailySteps by booleanPref(default = false)
|
||||||
|
|
||||||
|
var showMusic by booleanPref(default = false)
|
||||||
|
var mediaInfoFormat by stringPref(default = "")
|
||||||
|
var mediaPlayerTitle by stringPref(default = "")
|
||||||
|
var mediaPlayerAlbum by stringPref(default = "")
|
||||||
|
var mediaPlayerArtist by stringPref(default = "")
|
||||||
|
var mediaPlayerPackage by stringPref(default = "")
|
||||||
|
|
||||||
|
// Integrations
|
||||||
|
var installedIntegrations by intPref(default = 0)
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.tommasoberlose.anotherwidget.helpers
|
|||||||
import android.app.AlarmManager
|
import android.app.AlarmManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
|
import android.util.Log
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ object AlarmHelper {
|
|||||||
val alarm = nextAlarmClock
|
val alarm = nextAlarmClock
|
||||||
return if (
|
return if (
|
||||||
alarm != null
|
alarm != null
|
||||||
&& alarm.triggerTime - Calendar.getInstance().timeInMillis > 2 * 60 * 1000
|
&& alarm.triggerTime - Calendar.getInstance().timeInMillis > 10 * 60 * 1000
|
||||||
&& alarm.triggerTime - Calendar.getInstance().timeInMillis < 12 * 60 * 60 * 1000
|
&& alarm.triggerTime - Calendar.getInstance().timeInMillis < 12 * 60 * 60 * 1000
|
||||||
) {
|
) {
|
||||||
"%s %s".format(
|
"%s %s".format(
|
||||||
@ -22,4 +23,14 @@ object AlarmHelper {
|
|||||||
""
|
""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isAlarmProbablyWrong(context: Context): Boolean {
|
||||||
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
|
val alarm = nextAlarmClock
|
||||||
|
return (
|
||||||
|
alarm != null
|
||||||
|
&& alarm.triggerTime - Calendar.getInstance().timeInMillis < 5 * 60 * 1000
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Context.BATTERY_SERVICE
|
||||||
|
import android.os.BatteryManager
|
||||||
|
import androidx.core.content.ContextCompat.getSystemService
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
|
||||||
|
|
||||||
|
object BatteryHelper {
|
||||||
|
fun updateBatteryInfo(context: Context) {
|
||||||
|
with(context.getSystemService(BATTERY_SERVICE) as BatteryManager) {
|
||||||
|
Preferences.isBatteryLevelLow = getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY) <= 15
|
||||||
|
Preferences.isCharging = isCharging
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBatteryLevel(context: Context): Int {
|
||||||
|
with(context.getSystemService(BATTERY_SERVICE) as BatteryManager) {
|
||||||
|
return getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,27 +2,57 @@ package com.tommasoberlose.anotherwidget.helpers
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.*
|
import android.graphics.*
|
||||||
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.graphics.drawable.DrawableCompat
|
import androidx.core.graphics.drawable.DrawableCompat
|
||||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
object BitmapHelper {
|
object BitmapHelper {
|
||||||
|
|
||||||
fun getBitmapFromView(view: View, width: Int? = null, height: Int? = null, draw: Boolean = true): Bitmap {
|
fun getBitmapFromView(view: View, width: Int? = null, height: Int? = null, draw: Boolean = true): Bitmap {
|
||||||
//Define a bitmap with the same size as the view
|
//Define a bitmap with the same size as the view
|
||||||
val measuredWidth = View.MeasureSpec.makeMeasureSpec(width ?: view.width, if (width != null) View.MeasureSpec.EXACTLY else View.MeasureSpec.UNSPECIFIED)
|
val measuredWidth = View.MeasureSpec.makeMeasureSpec(width ?: view.width, if (width != null) View.MeasureSpec.EXACTLY else View.MeasureSpec.AT_MOST)
|
||||||
val measuredHeight = View.MeasureSpec.makeMeasureSpec(height ?: view.height, if (height != null) View.MeasureSpec.EXACTLY else View.MeasureSpec.UNSPECIFIED)
|
val measuredHeight = View.MeasureSpec.makeMeasureSpec(height ?: view.height, if (height != null) View.MeasureSpec.EXACTLY else View.MeasureSpec.UNSPECIFIED)
|
||||||
view.measure(measuredWidth, measuredHeight)
|
view.measure(
|
||||||
|
if (measuredWidth > 0) measuredWidth else 0,
|
||||||
|
if (measuredHeight > 0) measuredHeight else 0
|
||||||
|
)
|
||||||
|
|
||||||
|
val calculatedWidth = view.measuredWidth
|
||||||
|
val widgetWidth = if (calculatedWidth in 1..16000) {
|
||||||
|
calculatedWidth
|
||||||
|
} else if (width != null && width > 0) {
|
||||||
|
width
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
val calculatedHeight = view.measuredHeight
|
||||||
|
val widgetHeight = if (calculatedHeight in 1..16000) {
|
||||||
|
calculatedHeight
|
||||||
|
} else if (height != null && height > 0) {
|
||||||
|
height
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (draw) {
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("WIDTH SPEC", measuredWidth)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("HEIGHT SPEC", measuredHeight)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("VIEW measuredWidth", view.measuredWidth)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("VIEW measuredHeight", view.measuredHeight)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("WIDGET final width", measuredWidth)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("WIDGET final height", view.measuredHeight)
|
||||||
|
}
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
val btm = Bitmap.createBitmap(
|
val btm = Bitmap.createBitmap(
|
||||||
view.measuredWidth,
|
widgetWidth,
|
||||||
view.measuredHeight,
|
widgetHeight,
|
||||||
Bitmap.Config.ARGB_8888
|
if (draw) Bitmap.Config.ARGB_8888 else Bitmap.Config.ALPHA_8
|
||||||
)
|
)
|
||||||
if (draw) {
|
if (draw) {
|
||||||
//Bind a canvas to it
|
//Bind a canvas to it
|
||||||
@ -35,7 +65,7 @@ object BitmapHelper {
|
|||||||
btm
|
btm
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
FirebaseCrashlytics.getInstance().recordException(ex)
|
FirebaseCrashlytics.getInstance().recordException(ex)
|
||||||
Bitmap.createBitmap(5, 5, Bitmap.Config.ARGB_8888)
|
Bitmap.createBitmap(5, 5, Bitmap.Config.ALPHA_8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,4 +102,30 @@ object BitmapHelper {
|
|||||||
|
|
||||||
return resultBitmap
|
return resultBitmap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun drawableToBitmap(drawable: Drawable): Bitmap? {
|
||||||
|
var bitmap: Bitmap? = null
|
||||||
|
if (drawable is BitmapDrawable) {
|
||||||
|
if (drawable.bitmap != null) {
|
||||||
|
return drawable.bitmap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bitmap = if (drawable.intrinsicWidth <= 0 || drawable.intrinsicHeight <= 0) {
|
||||||
|
Bitmap.createBitmap(
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
Bitmap.Config.ARGB_8888
|
||||||
|
) // Single color bitmap will be created of 1x1 pixel
|
||||||
|
} else {
|
||||||
|
Bitmap.createBitmap(
|
||||||
|
drawable.intrinsicWidth,
|
||||||
|
drawable.intrinsicHeight,
|
||||||
|
Bitmap.Config.ARGB_8888
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val canvas = Canvas(bitmap)
|
||||||
|
drawable.setBounds(0, 0, canvas.width, canvas.height)
|
||||||
|
drawable.draw(canvas)
|
||||||
|
return bitmap
|
||||||
|
}
|
||||||
}
|
}
|
@ -10,7 +10,7 @@ import com.tommasoberlose.anotherwidget.db.EventRepository
|
|||||||
import com.tommasoberlose.anotherwidget.models.Event
|
import com.tommasoberlose.anotherwidget.models.Event
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
import me.everything.providers.android.calendar.CalendarProvider
|
import me.everything.providers.android.calendar.CalendarProvider
|
||||||
@ -31,22 +31,16 @@ object CalendarHelper {
|
|||||||
val eventList = ArrayList<Event>()
|
val eventList = ArrayList<Event>()
|
||||||
|
|
||||||
val now = Calendar.getInstance()
|
val now = Calendar.getInstance()
|
||||||
val limit = Calendar.getInstance()
|
val begin = Calendar.getInstance().apply {
|
||||||
when (Preferences.showUntil) {
|
set(Calendar.MILLISECOND, 0)
|
||||||
0 -> limit.add(Calendar.HOUR, 3)
|
set(Calendar.SECOND, 0)
|
||||||
1 -> limit.add(Calendar.HOUR, 6)
|
set(Calendar.MINUTE, 0)
|
||||||
2 -> limit.add(Calendar.HOUR, 12)
|
set(Calendar.HOUR_OF_DAY, 0)
|
||||||
3 -> limit.add(Calendar.DAY_OF_MONTH, 1)
|
}
|
||||||
4 -> limit.add(Calendar.DAY_OF_MONTH, 3)
|
val limit = Calendar.getInstance().apply {
|
||||||
5 -> limit.add(Calendar.DAY_OF_MONTH, 7)
|
timeInMillis = begin.timeInMillis
|
||||||
6 -> limit.add(Calendar.MINUTE, 30)
|
add(Calendar.DAY_OF_YEAR, 2)
|
||||||
7 -> limit.add(Calendar.HOUR, 1)
|
|
||||||
else -> limit.add(Calendar.HOUR, 6)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val builder = CalendarContract.Instances.CONTENT_URI.buildUpon()
|
|
||||||
ContentUris.appendId(builder, now.timeInMillis)
|
|
||||||
ContentUris.appendId(builder, limit.timeInMillis)
|
|
||||||
|
|
||||||
if (!context.checkGrantedPermission(
|
if (!context.checkGrantedPermission(
|
||||||
Manifest.permission.READ_CALENDAR
|
Manifest.permission.READ_CALENDAR
|
||||||
@ -56,13 +50,13 @@ object CalendarHelper {
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
val provider = CalendarProvider(context)
|
val provider = CalendarProvider(context)
|
||||||
val data = provider.getInstances(now.timeInMillis, limit.timeInMillis)
|
val data = provider.getInstances(begin.timeInMillis, limit.timeInMillis)
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
val instances = data.list
|
val instances = data.list
|
||||||
for (instance in instances) {
|
for (instance in instances) {
|
||||||
try {
|
try {
|
||||||
val e = provider.getEvent(instance.eventId)
|
val e = provider.getEvent(instance.eventId)
|
||||||
if (e != null && !e.deleted && instance.begin <= limit.timeInMillis && (Preferences.calendarAllDay || !e.allDay) && !getFilteredCalendarIdList().contains(
|
if (e != null && !e.deleted && instance.begin <= limit.timeInMillis && now.timeInMillis < instance.end && (Preferences.calendarAllDay || !e.allDay) && !getFilteredCalendarIdList().contains(
|
||||||
e.calendarId
|
e.calendarId
|
||||||
) && (Preferences.showDeclinedEvents || e.selfAttendeeStatus.toInt() != CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED)
|
) && (Preferences.showDeclinedEvents || e.selfAttendeeStatus.toInt() != CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED)
|
||||||
) {
|
) {
|
||||||
@ -96,6 +90,7 @@ object CalendarHelper {
|
|||||||
|
|
||||||
if (eventList.isEmpty()) {
|
if (eventList.isEmpty()) {
|
||||||
eventRepository.resetNextEventData()
|
eventRepository.resetNextEventData()
|
||||||
|
eventRepository.clearEvents()
|
||||||
} else {
|
} else {
|
||||||
eventList.sortWith(Comparator { event: Event, event1: Event ->
|
eventList.sortWith(Comparator { event: Event, event1: Event ->
|
||||||
if (event.allDay && event1.allDay) {
|
if (event.allDay && event1.allDay) {
|
||||||
@ -127,7 +122,8 @@ object CalendarHelper {
|
|||||||
UpdatesReceiver.setUpdates(context)
|
UpdatesReceiver.setUpdates(context)
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
|
|
||||||
EventBus.getDefault().post(MainActivity.UpdateUiMessageEvent())
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
|
eventRepository.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCalendarList(context: Context): List<me.everything.providers.android.calendar.Calendar> {
|
fun getCalendarList(context: Context): List<me.everything.providers.android.calendar.Calendar> {
|
||||||
|
@ -1,14 +1,105 @@
|
|||||||
package com.tommasoberlose.anotherwidget.helpers
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.util.Log
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
object ColorHelper {
|
object ColorHelper {
|
||||||
fun getFontColor(): Int {
|
fun getFontColor(): Int {
|
||||||
|
return try {
|
||||||
|
Color.parseColor("#%s%s".format(Preferences.textGlobalAlpha, Preferences.textGlobalColor.replace("#", "")))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Color.parseColor("#FFFFFFFF")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFontColorAlpha(): Int {
|
||||||
|
return try {
|
||||||
|
Preferences.textGlobalAlpha.toIntValue().toDouble() * 255 / 100
|
||||||
|
} catch (e: Exception) {
|
||||||
|
"FF".toIntValue().toDouble() * 255 / 100
|
||||||
|
}.roundToInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFontColorRgb(): Int {
|
||||||
return try {
|
return try {
|
||||||
Color.parseColor(Preferences.textGlobalColor)
|
Color.parseColor(Preferences.textGlobalColor)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Color.parseColor("#FFFFFF")
|
Color.parseColor("#000000")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSecondaryFontColor(): Int {
|
||||||
|
return try {
|
||||||
|
Color.parseColor("#%s%s".format(Preferences.textSecondaryAlpha, Preferences.textSecondaryColor.replace("#", "")))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Color.parseColor("#FFFFFFFF")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSecondaryFontColorAlpha(): Int {
|
||||||
|
return try {
|
||||||
|
Preferences.textSecondaryAlpha.toIntValue().toDouble() * 255 / 100
|
||||||
|
} catch (e: Exception) {
|
||||||
|
"FF".toIntValue().toDouble() * 255 / 100
|
||||||
|
}.roundToInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSecondaryFontColorRgb(): Int {
|
||||||
|
return try {
|
||||||
|
Color.parseColor(Preferences.textSecondaryColor)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Color.parseColor("#000000")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getClockFontColor(): Int {
|
||||||
|
return try {
|
||||||
|
Color.parseColor("#%s%s".format(Preferences.clockTextAlpha, Preferences.clockTextColor.replace("#", "")))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Color.parseColor("#FFFFFFFF")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getClockFontColorAlpha(): Int {
|
||||||
|
return try {
|
||||||
|
Preferences.clockTextAlpha.toIntValue().toDouble() * 255 / 100
|
||||||
|
} catch (e: Exception) {
|
||||||
|
"FF".toIntValue().toDouble() * 255 / 100
|
||||||
|
}.roundToInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getClockFontColorRgb(): Int {
|
||||||
|
return try {
|
||||||
|
Color.parseColor(Preferences.clockTextColor)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Color.parseColor("#000000")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBackgroundColor(): Int {
|
||||||
|
return try {
|
||||||
|
Color.parseColor("#%s%s".format(Preferences.backgroundCardAlpha, Preferences.backgroundCardColor.replace("#", "")))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Color.parseColor("#00000000")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBackgroundAlpha(): Int {
|
||||||
|
return try {
|
||||||
|
Preferences.backgroundCardAlpha.toIntValue().toDouble() * 255 / 100
|
||||||
|
} catch (e: Exception) {
|
||||||
|
"00".toIntValue().toDouble() * 255 / 100
|
||||||
|
}.roundToInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBackgroundColorRgb(): Int {
|
||||||
|
return try {
|
||||||
|
Color.parseColor(Preferences.backgroundCardColor)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Color.parseColor("#000000")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,4 +111,16 @@ object ColorHelper {
|
|||||||
1 - (0.299 * Color.red(this) + 0.587 * Color.green(this) + 0.114 * Color.blue(this)) / 255
|
1 - (0.299 * Color.red(this) + 0.587 * Color.green(this) + 0.114 * Color.blue(this)) / 255
|
||||||
return darkness >= threshold
|
return darkness >= threshold
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
fun Int.toHexValue(): String {
|
||||||
|
val intValue = (this * 255 / 100).toDouble().roundToInt()
|
||||||
|
val hexValue = intValue.toString(16)
|
||||||
|
return hexValue.padStart(2, '0').toUpperCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.toIntValue(): Int {
|
||||||
|
val hexValue = this.toInt(16).toDouble()
|
||||||
|
return (hexValue * 100 / 255).roundToInt()
|
||||||
|
}
|
||||||
}
|
}
|
@ -12,27 +12,30 @@ import java.util.*
|
|||||||
object DateHelper {
|
object DateHelper {
|
||||||
fun getDateText(context: Context, date: Calendar): String {
|
fun getDateText(context: Context, date: Calendar): String {
|
||||||
return if (Preferences.dateFormat != "") {
|
return if (Preferences.dateFormat != "") {
|
||||||
try {
|
val text = try {
|
||||||
SimpleDateFormat(Preferences.dateFormat, Locale.getDefault()).format(date.time)
|
SimpleDateFormat(Preferences.dateFormat, Locale.getDefault()).format(date.time)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
getDefaultDateText(context, date)
|
getDefaultDateText(context, date)
|
||||||
}
|
}
|
||||||
|
if (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
|
||||||
"%s, %s".format(
|
val text = "%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)
|
||||||
).getCapWordString()
|
)
|
||||||
|
if (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
|
||||||
return "%s, %s".format(
|
val text = "%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)
|
||||||
).getCapWordString()
|
)
|
||||||
|
return if (Preferences.isDateCapitalize) text.getCapWordString() else text
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.models.GlanceProvider
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.checkIfFitInstalled
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
object GlanceProviderHelper {
|
||||||
|
fun getGlanceProviders(context: Context): ArrayList<Constants.GlanceProviderId> {
|
||||||
|
val enabledProviders = Preferences.enabledGlanceProviderOrder.split(",").filter { it != "" }
|
||||||
|
|
||||||
|
val providers = Constants.GlanceProviderId.values()
|
||||||
|
.filter {
|
||||||
|
context.checkIfFitInstalled() || it != Constants.GlanceProviderId.GOOGLE_FIT_STEPS
|
||||||
|
}.toTypedArray()
|
||||||
|
|
||||||
|
providers.sortWith(Comparator { p1, p2 ->
|
||||||
|
when {
|
||||||
|
enabledProviders.contains(p1.id) && enabledProviders.contains(p2.id) -> {
|
||||||
|
enabledProviders.indexOf(p1.id).compareTo(enabledProviders.indexOf(p2.id))
|
||||||
|
}
|
||||||
|
enabledProviders.contains(p1.id) -> {
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
enabledProviders.contains(p2.id) -> {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
p1.id.compareTo(p2.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return ArrayList(providers.toList())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getGlanceProviderById(context: Context, providerId: Constants.GlanceProviderId): GlanceProvider? {
|
||||||
|
return when(providerId) {
|
||||||
|
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
||||||
|
GlanceProvider(providerId.id,
|
||||||
|
context.getString(R.string.settings_show_next_alarm_title),
|
||||||
|
R.drawable.round_alarm
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||||
|
GlanceProvider(providerId.id,
|
||||||
|
context.getString(R.string.settings_show_music_title),
|
||||||
|
R.drawable.round_music_note
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
||||||
|
GlanceProvider(providerId.id,
|
||||||
|
context.getString(R.string.settings_custom_notes_title),
|
||||||
|
R.drawable.round_notes
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
||||||
|
GlanceProvider(providerId.id,
|
||||||
|
context.getString(R.string.settings_low_battery_level_title),
|
||||||
|
R.drawable.round_battery_charging_full
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||||
|
GlanceProvider(providerId.id,
|
||||||
|
context.getString(R.string.settings_daily_steps_title),
|
||||||
|
R.drawable.round_directions_walk
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveGlanceProviderOrder(list: ArrayList<Constants.GlanceProviderId>) {
|
||||||
|
Preferences.enabledGlanceProviderOrder = list.joinToString(separator = ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun showGlanceProviders(context: Context): Boolean {
|
||||||
|
val eventRepository = EventRepository(context)
|
||||||
|
BatteryHelper.updateBatteryInfo(context)
|
||||||
|
val showGlance = Preferences.showGlance && eventRepository.getEventsCount() == 0 && (
|
||||||
|
(Preferences.showNextAlarm && AlarmHelper.getNextAlarm(context) != "") ||
|
||||||
|
(MediaPlayerHelper.isSomeonePlaying(context)) ||
|
||||||
|
(Preferences.showBatteryCharging && Preferences.isCharging || Preferences.isBatteryLevelLow) ||
|
||||||
|
(Preferences.customNotes.isNotEmpty()) ||
|
||||||
|
(Preferences.showDailySteps && Preferences.googleFitSteps > 0)
|
||||||
|
)
|
||||||
|
eventRepository.close()
|
||||||
|
return showGlance
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package com.tommasoberlose.anotherwidget.helpers
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
|
import android.appwidget.AppWidgetManager
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.ContentUris
|
import android.content.ContentUris
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@ -12,10 +13,22 @@ import android.provider.CalendarContract.Events
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.models.Event
|
import com.tommasoberlose.anotherwidget.models.Event
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
object IntentHelper {
|
object IntentHelper {
|
||||||
|
|
||||||
|
fun getWidgetUpdateIntent(context: Context): Intent {
|
||||||
|
val widgetManager = AppWidgetManager.getInstance(context)
|
||||||
|
val widgetComponent = ComponentName(context, MainWidget::class.java)
|
||||||
|
val widgetIds = widgetManager.getAppWidgetIds(widgetComponent)
|
||||||
|
return Intent(context, MainWidget::class.java).apply {
|
||||||
|
putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds)
|
||||||
|
action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getGoogleMapsIntentFromAddress(context: Context, address: String): Intent {
|
fun getGoogleMapsIntentFromAddress(context: Context, address: String): Intent {
|
||||||
val gmmIntentUri: Uri = Uri.parse("geo:0,0?q=$address")
|
val gmmIntentUri: Uri = Uri.parse("geo:0,0?q=$address")
|
||||||
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
|
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
|
||||||
@ -30,35 +43,6 @@ object IntentHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCalendarIntent(context: Context): Intent {
|
|
||||||
return when (Preferences.calendarAppPackage) {
|
|
||||||
"" -> {
|
|
||||||
Intent(Intent.ACTION_MAIN).apply {
|
|
||||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
addCategory(Intent.CATEGORY_APP_CALENDAR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"_" -> {
|
|
||||||
Intent()
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
val pm: PackageManager = context.packageManager
|
|
||||||
try {
|
|
||||||
pm.getLaunchIntentForPackage(Preferences.calendarAppPackage)!!.apply {
|
|
||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
|
||||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
Intent(Intent.ACTION_MAIN).apply {
|
|
||||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
addCategory(Intent.CATEGORY_APP_CALENDAR)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getWeatherIntent(context: Context): Intent {
|
fun getWeatherIntent(context: Context): Intent {
|
||||||
return when (Preferences.weatherAppPackage) {
|
return when (Preferences.weatherAppPackage) {
|
||||||
"" -> {
|
"" -> {
|
||||||
@ -91,15 +75,16 @@ object IntentHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEventIntent(context: Context, e: Event): Intent {
|
fun getCalendarIntent(context: Context): Intent {
|
||||||
return when (Preferences.eventAppPackage) {
|
val calendarUri = CalendarContract.CONTENT_URI
|
||||||
|
.buildUpon()
|
||||||
|
.appendPath("time")
|
||||||
|
.appendPath(Calendar.getInstance().timeInMillis.toString())
|
||||||
|
.build()
|
||||||
|
return when (Preferences.calendarAppPackage) {
|
||||||
"" -> {
|
"" -> {
|
||||||
val uri = ContentUris.withAppendedId(Events.CONTENT_URI, e.eventID)
|
|
||||||
Intent(Intent.ACTION_VIEW).apply {
|
Intent(Intent.ACTION_VIEW).apply {
|
||||||
data = uri
|
data = calendarUri
|
||||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
|
||||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"_" -> {
|
"_" -> {
|
||||||
@ -107,26 +92,72 @@ object IntentHelper {
|
|||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val pm: PackageManager = context.packageManager
|
val pm: PackageManager = context.packageManager
|
||||||
val uri = ContentUris.withAppendedId(Events.CONTENT_URI, e.eventID)
|
|
||||||
try {
|
try {
|
||||||
pm.getLaunchIntentForPackage(Preferences.eventAppPackage)!!.apply {
|
pm.getLaunchIntentForPackage(Preferences.calendarAppPackage)!!.apply {
|
||||||
action = Intent.ACTION_VIEW
|
action = Intent.ACTION_VIEW
|
||||||
data = uri
|
data = calendarUri
|
||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
|
||||||
// addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
||||||
// putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
|
||||||
// putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
|
||||||
}
|
}
|
||||||
} catch (ex: Exception) {
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
Intent(Intent.ACTION_VIEW).apply {
|
||||||
|
data = calendarUri
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getEventIntent(context: Context, e: Event, forceEventDetails: Boolean = false): Intent {
|
||||||
|
return when (Preferences.openEventDetails || forceEventDetails) {
|
||||||
|
true -> {
|
||||||
|
val uri = ContentUris.withAppendedId(Events.CONTENT_URI, e.eventID)
|
||||||
|
if (Preferences.calendarAppPackage == "") {
|
||||||
Intent(Intent.ACTION_VIEW).apply {
|
Intent(Intent.ACTION_VIEW).apply {
|
||||||
data = uri
|
data = uri
|
||||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
flags = (Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||||
|
if (!e.allDay) {
|
||||||
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||||
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||||
|
} else {
|
||||||
|
val start = Calendar.getInstance().apply {
|
||||||
|
timeInMillis = e.startDate
|
||||||
|
}
|
||||||
|
val end = Calendar.getInstance().apply {
|
||||||
|
timeInMillis = e.endDate
|
||||||
|
}
|
||||||
|
|
||||||
|
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate + start.timeZone.getOffset(start.timeInMillis))
|
||||||
|
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate + end.timeZone.getOffset(end.timeInMillis))
|
||||||
|
// putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d("ciao", "intent: ${this} - extras: ${this.extras}")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
getCalendarIntent(context).apply {
|
||||||
|
action = Intent.ACTION_VIEW
|
||||||
|
data = uri
|
||||||
|
if (!e.allDay) {
|
||||||
|
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, e.startDate)
|
||||||
|
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, e.endDate)
|
||||||
|
} else {
|
||||||
|
val start = Calendar.getInstance().apply {
|
||||||
|
timeInMillis = e.startDate
|
||||||
|
}
|
||||||
|
val end = Calendar.getInstance().apply {
|
||||||
|
timeInMillis = e.endDate
|
||||||
|
}
|
||||||
|
putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, start.timeInMillis + start.timeZone.getOffset(start.timeInMillis))
|
||||||
|
putExtra(CalendarContract.EXTRA_EVENT_END_TIME, end.timeInMillis + end.timeZone.getOffset(end.timeInMillis))
|
||||||
|
putExtra(CalendarContract.EXTRA_EVENT_ALL_DAY, 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
false -> {
|
||||||
|
getCalendarIntent(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getClockIntent(context: Context): Intent {
|
fun getClockIntent(context: Context): Intent {
|
||||||
@ -153,4 +184,37 @@ object IntentHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getBatteryIntent(): Intent {
|
||||||
|
return Intent(Intent.ACTION_POWER_USAGE_SUMMARY)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getMusicIntent(context: Context): Intent {
|
||||||
|
return when (Preferences.mediaPlayerPackage) {
|
||||||
|
"" -> {
|
||||||
|
Intent()
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
val pm: PackageManager = context.packageManager
|
||||||
|
try {
|
||||||
|
pm.getLaunchIntentForPackage(Preferences.mediaPlayerPackage)!!.apply {
|
||||||
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Intent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFitIntent(context: Context): Intent {
|
||||||
|
val pm: PackageManager = context.packageManager
|
||||||
|
return try {
|
||||||
|
pm.getLaunchIntentForPackage("com.google.android.apps.fitness")!!.apply {
|
||||||
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Intent()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
|
import android.app.Notification
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.media.MediaMetadata
|
||||||
|
import android.media.session.MediaController
|
||||||
|
import android.media.session.MediaSession
|
||||||
|
import android.media.session.MediaSessionManager
|
||||||
|
import android.media.session.PlaybackState
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import com.chibatching.kotpref.bulk
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.MusicNotificationListener
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
|
object MediaPlayerHelper {
|
||||||
|
fun isSomeonePlaying(context: Context) = Preferences.showMusic && NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName) && Preferences.mediaPlayerTitle != ""
|
||||||
|
|
||||||
|
fun getMediaInfo(): String {
|
||||||
|
return if (Preferences.mediaPlayerArtist == "") {
|
||||||
|
Preferences.mediaPlayerTitle
|
||||||
|
} else {
|
||||||
|
"%s, %s".format(Preferences.mediaPlayerTitle, Preferences.mediaPlayerArtist)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updatePlayingMediaInfo(context: Context) {
|
||||||
|
if (NotificationManagerCompat.getEnabledListenerPackages(context).contains(context.packageName)) {
|
||||||
|
val list = try {
|
||||||
|
(context.getSystemService(Context.MEDIA_SESSION_SERVICE) as MediaSessionManager).getActiveSessions(
|
||||||
|
ComponentName(context.packageName, MusicNotificationListener::class.java.name)
|
||||||
|
)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
emptyList<MediaController>()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.isNotEmpty()) {
|
||||||
|
var isSomeonePlaying = false
|
||||||
|
list.forEach { mc ->
|
||||||
|
val metadata = mc.metadata
|
||||||
|
val isPlaying =
|
||||||
|
mc.playbackState?.state == PlaybackState.STATE_PLAYING || mc.playbackState?.state == PlaybackState.STATE_CONNECTING
|
||||||
|
|
||||||
|
if (isPlaying) {
|
||||||
|
isSomeonePlaying = true
|
||||||
|
if (metadata != null) {
|
||||||
|
Preferences.bulk {
|
||||||
|
mediaPlayerTitle =
|
||||||
|
metadata.getText(MediaMetadata.METADATA_KEY_TITLE)?.toString()
|
||||||
|
?: ""
|
||||||
|
mediaPlayerArtist =
|
||||||
|
metadata.getText(MediaMetadata.METADATA_KEY_ARTIST)?.toString()
|
||||||
|
?: ""
|
||||||
|
mediaPlayerAlbum =
|
||||||
|
metadata.getText(MediaMetadata.METADATA_KEY_ALBUM)?.toString()
|
||||||
|
?: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Preferences.mediaPlayerPackage = mc.packageName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isSomeonePlaying) {
|
||||||
|
removeMediaInfo()
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
removeMediaInfo()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
removeMediaInfo()
|
||||||
|
}
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeMediaInfo() {
|
||||||
|
Preferences.bulk {
|
||||||
|
remove(Preferences::mediaPlayerTitle)
|
||||||
|
remove(Preferences::mediaPlayerArtist)
|
||||||
|
remove(Preferences::mediaPlayerAlbum)
|
||||||
|
remove(Preferences::mediaPlayerPackage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,8 @@ package com.tommasoberlose.anotherwidget.helpers
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.text.format.DateUtils
|
import android.text.format.DateUtils
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import org.joda.time.DateTime
|
import org.joda.time.DateTime
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@ -39,7 +41,6 @@ object SettingsStringHelper {
|
|||||||
return when (info) {
|
return when (info) {
|
||||||
0 -> R.string.settings_second_row_info_subtitle_0
|
0 -> R.string.settings_second_row_info_subtitle_0
|
||||||
1 -> R.string.settings_second_row_info_subtitle_1
|
1 -> R.string.settings_second_row_info_subtitle_1
|
||||||
2 -> R.string.settings_second_row_info_subtitle_2
|
|
||||||
else -> R.string.settings_second_row_info_subtitle_0
|
else -> R.string.settings_second_row_info_subtitle_0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,11 +70,38 @@ object SettingsStringHelper {
|
|||||||
difference += 60 * 1000 - (difference % (60 * 1000))
|
difference += 60 * 1000 - (difference % (60 * 1000))
|
||||||
|
|
||||||
when {
|
when {
|
||||||
difference <= 0 || TimeUnit.MILLISECONDS.toHours(difference) < 1 -> {
|
difference <= 0 -> {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.HIGH.value && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> {
|
||||||
|
return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 5), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
||||||
|
}
|
||||||
|
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.DEFAULT.value && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> {
|
||||||
|
return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 15), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
||||||
|
}
|
||||||
|
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.LOW.value -> {
|
||||||
|
return context.getString(R.string.soon)
|
||||||
|
}
|
||||||
|
TimeUnit.MILLISECONDS.toHours(difference) < 1 -> {
|
||||||
|
return context.getString(R.string.now)
|
||||||
|
}
|
||||||
TimeUnit.MILLISECONDS.toHours(difference) < 12 -> {
|
TimeUnit.MILLISECONDS.toHours(difference) < 12 -> {
|
||||||
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.HOUR_IN_MILLIS).toString()
|
val minutes = TimeUnit.MILLISECONDS.toMinutes(difference) - 60 * TimeUnit.MILLISECONDS.toHours(difference)
|
||||||
|
return if (minutes < 1 || minutes > 30) {
|
||||||
|
DateUtils.getRelativeTimeSpanString(
|
||||||
|
start,
|
||||||
|
now - 1000 * 60 * 40,
|
||||||
|
DateUtils.HOUR_IN_MILLIS,
|
||||||
|
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||||
|
).toString()
|
||||||
|
} else {
|
||||||
|
DateUtils.getRelativeTimeSpanString(
|
||||||
|
start,
|
||||||
|
now,
|
||||||
|
DateUtils.HOUR_IN_MILLIS,
|
||||||
|
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||||
|
).toString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
eventDate.dayOfYear == nowDate.plusDays(1).dayOfYear -> {
|
eventDate.dayOfYear == nowDate.plusDays(1).dayOfYear -> {
|
||||||
return String.format("%s", context.getString(R.string.tomorrow))
|
return String.format("%s", context.getString(R.string.tomorrow))
|
||||||
@ -82,7 +110,7 @@ object SettingsStringHelper {
|
|||||||
return String.format("%s", context.getString(R.string.today))
|
return String.format("%s", context.getString(R.string.today))
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.DAY_IN_MILLIS).toString()
|
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.DAY_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,16 +2,16 @@ package com.tommasoberlose.anotherwidget.helpers
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
import com.google.android.gms.location.LocationServices
|
import com.google.android.gms.location.LocationServices
|
||||||
import com.kwabenaberko.openweathermaplib.constants.Units
|
|
||||||
import com.kwabenaberko.openweathermaplib.implementation.OpenWeatherMapHelper
|
|
||||||
import com.kwabenaberko.openweathermaplib.implementation.callbacks.CurrentWeatherCallback
|
|
||||||
import com.kwabenaberko.openweathermaplib.models.currentweather.CurrentWeather
|
|
||||||
import com.tommasoberlose.anotherwidget.R
|
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.network.WeatherNetworkApi
|
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
||||||
|
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 org.greenrobot.eventbus.EventBus
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,7 +24,7 @@ object WeatherHelper {
|
|||||||
val networkApi = WeatherNetworkApi(context)
|
val networkApi = WeatherNetworkApi(context)
|
||||||
if (Preferences.customLocationAdd != "") {
|
if (Preferences.customLocationAdd != "") {
|
||||||
networkApi.updateWeather()
|
networkApi.updateWeather()
|
||||||
} else if (context.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
|
} else if (context.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION)) {
|
||||||
LocationServices.getFusedLocationProviderClient(context).lastLocation.addOnCompleteListener { task ->
|
LocationServices.getFusedLocationProviderClient(context).lastLocation.addOnCompleteListener { task ->
|
||||||
if (task.isSuccessful) {
|
if (task.isSuccessful) {
|
||||||
val location = task.result
|
val location = task.result
|
||||||
@ -33,6 +33,7 @@ object WeatherHelper {
|
|||||||
Preferences.customLocationLon = location.longitude.toString()
|
Preferences.customLocationLon = location.longitude.toString()
|
||||||
|
|
||||||
networkApi.updateWeather()
|
networkApi.updateWeather()
|
||||||
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,86 +42,86 @@ object WeatherHelper {
|
|||||||
|
|
||||||
fun removeWeather(context: Context) {
|
fun removeWeather(context: Context) {
|
||||||
Preferences.remove(Preferences::weatherTemp)
|
Preferences.remove(Preferences::weatherTemp)
|
||||||
Preferences.remove(Preferences::weatherTempUnit)
|
Preferences.remove(Preferences::weatherRealTempUnit)
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getWeatherIconResource(icon: String): Int {
|
fun getWeatherIconResource(icon: String): Int {
|
||||||
when (icon) {
|
when (icon) {
|
||||||
"01d" -> {
|
"01d" -> {
|
||||||
return R.drawable.clear_day
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.clear_day else R.drawable.clear_day_2
|
||||||
}
|
}
|
||||||
"02d" -> {
|
"02d" -> {
|
||||||
return R.drawable.partly_cloudy
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.partly_cloudy else R.drawable.partly_cloudy_2
|
||||||
}
|
}
|
||||||
"03d" -> {
|
"03d" -> {
|
||||||
return R.drawable.mostly_cloudy
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.mostly_cloudy else R.drawable.mostly_cloudy_2
|
||||||
}
|
}
|
||||||
"04d" -> {
|
"04d" -> {
|
||||||
return R.drawable.cloudy_weather
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.cloudy_weather else R.drawable.cloudy_weather_2
|
||||||
}
|
}
|
||||||
"09d" -> {
|
"09d" -> {
|
||||||
return R.drawable.storm_weather_day
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.storm_weather_day else R.drawable.storm_weather_day_2
|
||||||
}
|
}
|
||||||
"10d" -> {
|
"10d" -> {
|
||||||
return R.drawable.rainy_day
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.rainy_day else R.drawable.rainy_day_2
|
||||||
}
|
}
|
||||||
"11d" -> {
|
"11d" -> {
|
||||||
return R.drawable.thunder_day
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.thunder_day else R.drawable.thunder_day_2
|
||||||
}
|
}
|
||||||
"13d" -> {
|
"13d" -> {
|
||||||
return R.drawable.snow_day
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.snow_day else R.drawable.snow_day_2
|
||||||
}
|
}
|
||||||
"50d" -> {
|
"50d" -> {
|
||||||
return R.drawable.haze_day
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.haze_day else R.drawable.haze_day_2
|
||||||
}
|
}
|
||||||
"80d" -> {
|
"80d" -> {
|
||||||
return R.drawable.windy_day
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.windy_day else R.drawable.windy_day_2
|
||||||
}
|
}
|
||||||
"81d" -> {
|
"81d" -> {
|
||||||
return R.drawable.rain_snow_day
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.rain_snow_day else R.drawable.rain_snow_day_2
|
||||||
}
|
}
|
||||||
"82d" -> {
|
"82d" -> {
|
||||||
return R.drawable.haze_weather
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.haze_weather else R.drawable.haze_weather_2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"01n" -> {
|
"01n" -> {
|
||||||
return R.drawable.clear_night
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.clear_night else R.drawable.clear_night_2
|
||||||
}
|
}
|
||||||
"02n" -> {
|
"02n" -> {
|
||||||
return R.drawable.partly_cloudy_night
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.partly_cloudy_night else R.drawable.partly_cloudy_night_2
|
||||||
}
|
}
|
||||||
"03n" -> {
|
"03n" -> {
|
||||||
return R.drawable.mostly_cloudy_night
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.mostly_cloudy_night else R.drawable.mostly_cloudy_night_2
|
||||||
}
|
}
|
||||||
"04n" -> {
|
"04n" -> {
|
||||||
return R.drawable.cloudy_weather
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.cloudy_weather else R.drawable.cloudy_weather_2
|
||||||
}
|
}
|
||||||
"09n" -> {
|
"09n" -> {
|
||||||
return R.drawable.storm_weather_night
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.storm_weather_night else R.drawable.storm_weather_night_2
|
||||||
}
|
}
|
||||||
"10n" -> {
|
"10n" -> {
|
||||||
return R.drawable.rainy_night
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.rainy_night else R.drawable.rainy_night_2
|
||||||
}
|
}
|
||||||
"11n" -> {
|
"11n" -> {
|
||||||
return R.drawable.thunder_night
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.thunder_night else R.drawable.thunder_night_2
|
||||||
}
|
}
|
||||||
"13n" -> {
|
"13n" -> {
|
||||||
return R.drawable.snow_night
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.snow_night else R.drawable.snow_night_2
|
||||||
}
|
}
|
||||||
"50n" -> {
|
"50n" -> {
|
||||||
return R.drawable.haze_night
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.haze_night else R.drawable.haze_night_2
|
||||||
}
|
}
|
||||||
"80n" -> {
|
"80n" -> {
|
||||||
return R.drawable.windy_night
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.windy_night else R.drawable.windy_night_2
|
||||||
}
|
}
|
||||||
"81n" -> {
|
"81n" -> {
|
||||||
return R.drawable.rain_snow_night
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.rain_snow_night else R.drawable.rain_snow_night_2
|
||||||
}
|
}
|
||||||
"82n" -> {
|
"82n" -> {
|
||||||
return R.drawable.haze_weather
|
return if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) R.drawable.haze_weather else R.drawable.haze_weather_2
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
return R.drawable.unknown
|
return R.drawable.unknown
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
|
import android.appwidget.AppWidgetManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.Configuration.ORIENTATION_PORTRAIT
|
||||||
|
import android.util.Log
|
||||||
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
|
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
|
||||||
|
object WidgetHelper {
|
||||||
|
class WidgetSizeProvider(
|
||||||
|
private val context: Context,
|
||||||
|
private val appWidgetManager: AppWidgetManager
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun getWidgetsSize(widgetId: Int): Pair<Int, Int> {
|
||||||
|
val isPortrait = context.resources.configuration.orientation == ORIENTATION_PORTRAIT
|
||||||
|
val width = getWidgetWidth(isPortrait, widgetId)
|
||||||
|
val height = getWidgetHeight(isPortrait, widgetId)
|
||||||
|
val widthInPx = context.dip(width)
|
||||||
|
val heightInPx = context.dip(height)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("widthInPx", widthInPx)
|
||||||
|
FirebaseCrashlytics.getInstance().setCustomKey("heightInPx", heightInPx)
|
||||||
|
return widthInPx to heightInPx
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getWidgetWidth(isPortrait: Boolean, widgetId: Int): Int = getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)
|
||||||
|
|
||||||
|
private fun getWidgetHeight(isPortrait: Boolean, widgetId: Int): Int = getWidgetSizeInDp(widgetId, AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)
|
||||||
|
|
||||||
|
private fun getWidgetSizeInDp(widgetId: Int, key: String): Int =
|
||||||
|
appWidgetManager.getAppWidgetOptions(widgetId).getInt(key, 0)
|
||||||
|
|
||||||
|
private fun Context.dip(value: Int): Int = (value * resources.displayMetrics.density).toInt()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Pair<Int, Int>.reduceDimensionWithMaxWidth(width: Int): Pair<Int, Int> {
|
||||||
|
return if (first < width) {
|
||||||
|
this
|
||||||
|
} else {
|
||||||
|
val factor = width / first
|
||||||
|
width to second * factor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,8 +15,7 @@ open class Event(var id: Long = 0,
|
|||||||
var calendarID: Int = 0,
|
var calendarID: Int = 0,
|
||||||
var allDay: Boolean = false,
|
var allDay: Boolean = false,
|
||||||
var address: String = "") : RealmObject() {
|
var address: String = "") : RealmObject() {
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "Event:\nID: " + id + "\nTITLE: " + title + "\nSTART DATE: " + Date(startDate) + "\nEND DATE: " + Date(endDate) + "\nCAL DAY: " + calendarID + "\nADDRESS: " + address
|
return "Event:\nEVENT ID: " + eventID + "\nTITLE: " + title + "\nSTART DATE: " + Date(startDate) + "\nEND DATE: " + Date(endDate) + "\nCAL ID: " + calendarID + "\nADDRESS: " + address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.models
|
||||||
|
|
||||||
|
class GlanceProvider(
|
||||||
|
val id: String,
|
||||||
|
val title: String,
|
||||||
|
val icon: Int
|
||||||
|
)
|
@ -7,7 +7,7 @@ import com.kwabenaberko.openweathermaplib.implementation.callbacks.CurrentWeathe
|
|||||||
import com.kwabenaberko.openweathermaplib.models.currentweather.CurrentWeather
|
import com.kwabenaberko.openweathermaplib.models.currentweather.CurrentWeather
|
||||||
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.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
|
||||||
@ -23,11 +23,9 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
Preferences.weatherTemp = currentWeather.main.temp.toFloat()
|
Preferences.weatherTemp = currentWeather.main.temp.toFloat()
|
||||||
Preferences.weatherIcon = currentWeather.weather[0].icon
|
Preferences.weatherIcon = currentWeather.weather[0].icon
|
||||||
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
Preferences.weatherRealTempUnit = Preferences.weatherTempUnit
|
||||||
MainWidget.updateWidget(
|
MainWidget.updateWidget(context)
|
||||||
context
|
|
||||||
)
|
|
||||||
|
|
||||||
EventBus.getDefault().post(MainActivity.UpdateUiMessageEvent())
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,176 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.receivers
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.AlarmManager
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.Log
|
||||||
|
import com.google.android.gms.auth.api.signin.GoogleSignIn
|
||||||
|
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
|
||||||
|
import com.google.android.gms.fitness.Fitness
|
||||||
|
import com.google.android.gms.fitness.FitnessOptions
|
||||||
|
import com.google.android.gms.fitness.data.DataType
|
||||||
|
import com.google.android.gms.fitness.data.Field.FIELD_STEPS
|
||||||
|
import com.google.android.gms.fitness.request.DataReadRequest
|
||||||
|
import com.google.android.gms.location.*
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
|
||||||
|
class ActivityDetectionReceiver : BroadcastReceiver() {
|
||||||
|
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
if (ActivityTransitionResult.hasResult(intent)) {
|
||||||
|
val result = ActivityTransitionResult.extractResult(intent)!!
|
||||||
|
val lastEvent = result.transitionEvents.last()
|
||||||
|
|
||||||
|
if (lastEvent.activityType == DetectedActivity.WALKING || lastEvent.activityType == DetectedActivity.RUNNING && lastEvent.transitionType == ActivityTransition.ACTIVITY_TRANSITION_EXIT) {
|
||||||
|
requestDailySteps(context)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (intent.action == Intent.ACTION_BOOT_COMPLETED || intent.action == Intent.ACTION_MY_PACKAGE_REPLACED && Preferences.showDailySteps && Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || context.checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION)) {
|
||||||
|
resetDailySteps()
|
||||||
|
registerFence(context)
|
||||||
|
} else {
|
||||||
|
resetDailySteps()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resetDailySteps() {
|
||||||
|
Preferences.googleFitSteps = -1
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val FITNESS_OPTIONS: FitnessOptions = FitnessOptions.builder()
|
||||||
|
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
|
||||||
|
.addDataType(DataType.AGGREGATE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
fun registerFence(context: Context) {
|
||||||
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || context.checkGrantedPermission(
|
||||||
|
Manifest.permission.ACTIVITY_RECOGNITION)) {
|
||||||
|
val transitions = mutableListOf<ActivityTransition>()
|
||||||
|
|
||||||
|
transitions +=
|
||||||
|
ActivityTransition.Builder()
|
||||||
|
.setActivityType(DetectedActivity.WALKING)
|
||||||
|
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
transitions +=
|
||||||
|
ActivityTransition.Builder()
|
||||||
|
.setActivityType(DetectedActivity.RUNNING)
|
||||||
|
.setActivityTransition(ActivityTransition.ACTIVITY_TRANSITION_EXIT)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val request = ActivityTransitionRequest(transitions)
|
||||||
|
|
||||||
|
// myPendingIntent is the instance of PendingIntent where the app receives callbacks.
|
||||||
|
val task = ActivityRecognition.getClient(context)
|
||||||
|
.requestActivityTransitionUpdates(
|
||||||
|
request,
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
2,
|
||||||
|
Intent(context, ActivityDetectionReceiver::class.java),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
task.addOnFailureListener { e: Exception ->
|
||||||
|
e.printStackTrace()
|
||||||
|
Preferences.showDailySteps = false
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unregisterFence(context: Context) {
|
||||||
|
val task = ActivityRecognition.getClient(context)
|
||||||
|
.removeActivityTransitionUpdates(
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
2,
|
||||||
|
Intent(context, ActivityDetectionReceiver::class.java),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
task.addOnCompleteListener {
|
||||||
|
if (it.isSuccessful) {
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
2,
|
||||||
|
Intent(context, ActivityDetectionReceiver::class.java),
|
||||||
|
0
|
||||||
|
).cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun requestDailySteps(context: Context) {
|
||||||
|
|
||||||
|
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
|
||||||
|
if (account != null && GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
|
||||||
|
|
||||||
|
val cal: Calendar = Calendar.getInstance()
|
||||||
|
cal.set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
cal.set(Calendar.MINUTE, 0)
|
||||||
|
cal.set(Calendar.SECOND, 0)
|
||||||
|
cal.set(Calendar.MILLISECOND, 0)
|
||||||
|
val startTime: Long = cal.timeInMillis
|
||||||
|
|
||||||
|
cal.add(Calendar.DAY_OF_YEAR, 1)
|
||||||
|
val endTime: Long = cal.timeInMillis
|
||||||
|
|
||||||
|
val readRequest = DataReadRequest.Builder()
|
||||||
|
.aggregate(
|
||||||
|
DataType.TYPE_STEP_COUNT_DELTA,
|
||||||
|
DataType.AGGREGATE_STEP_COUNT_DELTA
|
||||||
|
)
|
||||||
|
.setTimeRange(startTime, endTime, TimeUnit.MILLISECONDS)
|
||||||
|
.bucketByTime(1, TimeUnit.DAYS)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
Fitness.getHistoryClient(context, account)
|
||||||
|
.readData(readRequest)
|
||||||
|
.addOnSuccessListener { response ->
|
||||||
|
Preferences.googleFitSteps = response.buckets.sumBy {
|
||||||
|
try {
|
||||||
|
it.getDataSet(DataType.AGGREGATE_STEP_COUNT_DELTA)?.dataPoints?.get(
|
||||||
|
0
|
||||||
|
)?.getValue(FIELD_STEPS)?.asInt() ?: 0
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}.toLong()
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
setTimeout(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setTimeout(context: Context) {
|
||||||
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
|
cancel(PendingIntent.getBroadcast(context, 5, Intent(context, ActivityDetectionReceiver::class.java), 0))
|
||||||
|
setExactAndAllowWhileIdle(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
Calendar.getInstance().timeInMillis + 5 * 60 * 1000,
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
5,
|
||||||
|
Intent(context, ActivityDetectionReceiver::class.java),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.receivers
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.BatteryManager
|
||||||
|
import android.util.Log
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.toast
|
||||||
|
|
||||||
|
class BatteryLevelReceiver : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
when(intent.action) {
|
||||||
|
Intent.ACTION_BATTERY_LOW -> Preferences.isBatteryLevelLow = true
|
||||||
|
Intent.ACTION_BATTERY_OKAY -> Preferences.isBatteryLevelLow = false
|
||||||
|
Intent.ACTION_POWER_CONNECTED -> Preferences.isCharging = true
|
||||||
|
Intent.ACTION_POWER_DISCONNECTED -> Preferences.isCharging = false
|
||||||
|
}
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.receivers
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.util.Log
|
||||||
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Actions
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
|
class CrashlyticsReceiver : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
if (intent.action == Actions.ACTION_REPORT_CRASH) {
|
||||||
|
val exception: Exception = intent.getSerializableExtra(EXCEPTION) as Exception
|
||||||
|
FirebaseCrashlytics.getInstance().recordException(exception)
|
||||||
|
FirebaseCrashlytics.getInstance().sendUnsentReports()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val EXCEPTION = "EXCEPTION"
|
||||||
|
|
||||||
|
fun sendCrash(context: Context, exception: Exception) {
|
||||||
|
context.sendBroadcast(Intent(context, CrashlyticsReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_REPORT_CRASH
|
||||||
|
putExtra(EXCEPTION, exception)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,6 @@ class NewCalendarEventReceiver : BroadcastReceiver() {
|
|||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
val eventRepository = EventRepository(context)
|
val eventRepository = EventRepository(context)
|
||||||
Log.d("ciao", "nuovo evento")
|
|
||||||
when (intent.action) {
|
when (intent.action) {
|
||||||
Intent.ACTION_PROVIDER_CHANGED,
|
Intent.ACTION_PROVIDER_CHANGED,
|
||||||
Intent.ACTION_TIME_CHANGED -> {
|
Intent.ACTION_TIME_CHANGED -> {
|
||||||
@ -25,5 +24,6 @@ class NewCalendarEventReceiver : BroadcastReceiver() {
|
|||||||
eventRepository.goToPreviousEvent()
|
eventRepository.goToPreviousEvent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
eventRepository.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,22 @@
|
|||||||
package com.tommasoberlose.anotherwidget.receivers
|
package com.tommasoberlose.anotherwidget.receivers
|
||||||
|
|
||||||
|
import android.app.AlarmManager
|
||||||
|
import android.app.PendingIntent
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.app.AlarmManager
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.core.app.AlarmManagerCompat
|
||||||
|
import androidx.core.content.ContextCompat.getSystemService
|
||||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||||
import com.tommasoberlose.anotherwidget.global.Actions
|
import com.tommasoberlose.anotherwidget.global.Actions
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.BatteryHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||||
|
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
|
||||||
import java.text.DateFormat
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
@ -21,37 +26,139 @@ class UpdatesReceiver : BroadcastReceiver() {
|
|||||||
when (intent.action) {
|
when (intent.action) {
|
||||||
Intent.ACTION_BOOT_COMPLETED,
|
Intent.ACTION_BOOT_COMPLETED,
|
||||||
Intent.ACTION_MY_PACKAGE_REPLACED,
|
Intent.ACTION_MY_PACKAGE_REPLACED,
|
||||||
Actions.ACTION_CALENDAR_UPDATE -> CalendarHelper.updateEventList(context)
|
Intent.ACTION_TIME_CHANGED,
|
||||||
|
Intent.ACTION_TIMEZONE_CHANGED,
|
||||||
|
Intent.ACTION_LOCALE_CHANGED,
|
||||||
|
Intent.ACTION_DATE_CHANGED,
|
||||||
|
Actions.ACTION_CALENDAR_UPDATE -> {
|
||||||
|
CalendarHelper.updateEventList(context)
|
||||||
|
}
|
||||||
|
|
||||||
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
|
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
|
||||||
Intent.ACTION_DATE_CHANGED,
|
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
|
||||||
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED -> MainWidget.updateWidget(context)
|
Actions.ACTION_TIME_UPDATE -> {
|
||||||
|
MainWidget.updateWidget(context)
|
||||||
|
if (intent.hasExtra(EVENT_ID)) {
|
||||||
|
setUpdates(context, intent.getLongExtra(EVENT_ID, -1))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun setUpdates(context: Context) {
|
const val EVENT_ID = "EVENT_ID"
|
||||||
|
|
||||||
|
fun setUpdates(context: Context, eventId: Long? = null) {
|
||||||
|
val eventRepository = EventRepository(context)
|
||||||
|
if (eventId == null) {
|
||||||
removeUpdates(context)
|
removeUpdates(context)
|
||||||
|
|
||||||
val eventRepository = EventRepository(context)
|
eventRepository.getFutureEvents().forEach { event ->
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
setEventUpdate(context, event)
|
||||||
eventRepository.getEvents().forEach { event ->
|
}
|
||||||
val hoursDiff = Period(Calendar.getInstance().timeInMillis, event.startDate).hours
|
} else {
|
||||||
|
val event = eventRepository.getEventByEventId(eventId)
|
||||||
// Update the widget every hour till the event
|
if (event != null) {
|
||||||
(0 .. hoursDiff).forEach {
|
setEventUpdate(context, event)
|
||||||
setExact(
|
}
|
||||||
AlarmManager.RTC_WAKEUP,
|
}
|
||||||
(event.startDate + 1000) - it * 1000 * 60* 60,
|
eventRepository.close()
|
||||||
PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_TIME_UPDATE }, 0)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the widget one second after the event is finished
|
private fun setEventUpdate(context: Context, event: Event) {
|
||||||
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
|
val now = Calendar.getInstance().apply {
|
||||||
|
set(Calendar.SECOND, 0)
|
||||||
|
set(Calendar.MILLISECOND, 0)
|
||||||
|
}
|
||||||
|
val diff = Period(now.timeInMillis, event.startDate)
|
||||||
|
val limit = when (Preferences.showUntil) {
|
||||||
|
0 -> 1000 * 60 * 60 * 3
|
||||||
|
1 -> 1000 * 60 * 60 * 6
|
||||||
|
2 -> 1000 * 60 * 60 * 12
|
||||||
|
3 -> 1000 * 60 * 60 * 24
|
||||||
|
4 -> 1000 * 60 * 60 * 24 * 3
|
||||||
|
5 -> 1000 * 60 * 60 * 24 * 7
|
||||||
|
6 -> 1000 * 60 * 30
|
||||||
|
7 -> 1000 * 60 * 60
|
||||||
|
else -> 1000 * 60 * 60 * 6
|
||||||
|
}
|
||||||
|
if (event.startDate <= limit) {
|
||||||
|
if (event.startDate > now.timeInMillis) {
|
||||||
|
// Update the widget every hour till the event
|
||||||
|
if (diff.hours == 0) {
|
||||||
|
var minutes = 0
|
||||||
|
when (Preferences.widgetUpdateFrequency) {
|
||||||
|
Constants.WidgetUpdateFrequency.DEFAULT.value -> {
|
||||||
|
minutes = when {
|
||||||
|
diff.minutes > 50 -> 50
|
||||||
|
diff.minutes > 30 -> 30
|
||||||
|
diff.minutes > 15 -> 15
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.WidgetUpdateFrequency.HIGH.value -> {
|
||||||
|
minutes = diff.minutes - (diff.minutes % 5)
|
||||||
|
}
|
||||||
|
}
|
||||||
setExact(
|
setExact(
|
||||||
AlarmManager.RTC_WAKEUP,
|
AlarmManager.RTC,
|
||||||
event.endDate + 1000,
|
if (event.startDate - minutes * 1000 * 60 > (now.timeInMillis + 120 * 1000)) event.startDate - 60 * 1000 * minutes else now.timeInMillis + 120000,
|
||||||
PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_TIME_UPDATE }, 0)
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
event.eventID.toInt(),
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_TIME_UPDATE
|
||||||
|
putExtra(EVENT_ID, event.eventID)
|
||||||
|
},
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
setExact(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
event.startDate - diff.hours * 1000 * 60 * 60 + if (diff.minutes > 30) (-30) else (+30),
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
event.eventID.toInt(),
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_TIME_UPDATE
|
||||||
|
putExtra(EVENT_ID, event.eventID)
|
||||||
|
},
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Update the widget one second after the event is finished
|
||||||
|
val fireTime =
|
||||||
|
if (event.endDate > now.timeInMillis + 120 * 1000) event.endDate else now.timeInMillis + 120000
|
||||||
|
setExact(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
fireTime,
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
event.eventID.toInt(),
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_TIME_UPDATE
|
||||||
|
},
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setExact(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
if (event.startDate - limit > now.timeInMillis + 120 * 1000) event.startDate - limit else now.timeInMillis + 120000,
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
event.eventID.toInt(),
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_TIME_UPDATE
|
||||||
|
putExtra(EVENT_ID, event.eventID)
|
||||||
|
},
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,7 +166,11 @@ class UpdatesReceiver : BroadcastReceiver() {
|
|||||||
|
|
||||||
fun removeUpdates(context: Context) {
|
fun removeUpdates(context: Context) {
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
cancel(PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java), 0))
|
val eventRepository = EventRepository(context)
|
||||||
|
eventRepository.getFutureEvents().forEach {
|
||||||
|
cancel(PendingIntent.getBroadcast(context, it.eventID.toInt(), Intent(context, UpdatesReceiver::class.java), 0))
|
||||||
|
}
|
||||||
|
eventRepository.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ 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
|
||||||
@ -17,68 +18,63 @@ class WeatherReceiver : BroadcastReceiver() {
|
|||||||
when (intent.action) {
|
when (intent.action) {
|
||||||
Intent.ACTION_BOOT_COMPLETED,
|
Intent.ACTION_BOOT_COMPLETED,
|
||||||
Intent.ACTION_MY_PACKAGE_REPLACED,
|
Intent.ACTION_MY_PACKAGE_REPLACED,
|
||||||
|
Intent.ACTION_TIMEZONE_CHANGED,
|
||||||
|
Intent.ACTION_LOCALE_CHANGED,
|
||||||
Intent.ACTION_TIME_CHANGED -> setUpdates(context)
|
Intent.ACTION_TIME_CHANGED -> setUpdates(context)
|
||||||
|
|
||||||
Actions.ACTION_WEATHER_UPDATE -> WeatherHelper.updateWeather(context)
|
Actions.ACTION_WEATHER_UPDATE -> {
|
||||||
|
WeatherHelper.updateWeather(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
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 && Preferences.weatherProviderApi != "") {
|
||||||
WeatherHelper.updateWeather(context)
|
val interval = MINUTE * when (Preferences.weatherRefreshPeriod) {
|
||||||
|
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
|
||||||
val pi = PendingIntent.getBroadcast(
|
|
||||||
context,
|
|
||||||
1,
|
|
||||||
Intent(context, WeatherReceiver::class.java).apply {
|
|
||||||
action = Actions.ACTION_WEATHER_UPDATE
|
|
||||||
},
|
|
||||||
0
|
|
||||||
)
|
|
||||||
|
|
||||||
val refresh: Long = when (Preferences.weatherRefreshPeriod) {
|
|
||||||
0 -> 30
|
0 -> 30
|
||||||
1 -> 60
|
1 -> 60
|
||||||
2 -> 60 * 3
|
2 -> 60L * 3
|
||||||
3 -> 60 * 6
|
3 -> 60L * 6
|
||||||
4 -> 60 * 12
|
4 -> 60L * 12
|
||||||
5 -> 60 * 24
|
5 -> 60L * 24
|
||||||
else -> 60
|
else -> 60
|
||||||
}
|
}
|
||||||
val now = Calendar.getInstance().apply {
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
set(Calendar.MILLISECOND, 0)
|
setRepeating(
|
||||||
set(Calendar.SECOND, 0)
|
AlarmManager.RTC,
|
||||||
}
|
Calendar.getInstance().timeInMillis,
|
||||||
|
interval,
|
||||||
setRepeating(AlarmManager.RTC_WAKEUP, now.timeInMillis, 1000 * 60 * refresh, pi)
|
PendingIntent.getBroadcast(context, 0, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setOneTimeUpdate(context: Context) {
|
fun setOneTimeUpdate(context: Context) {
|
||||||
// Update the weather in a few minuter when the api key has been changed
|
if (Preferences.showWeather && Preferences.weatherProviderApi != "") {
|
||||||
|
listOf(10, 20, 30).forEach {
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
val pi = PendingIntent.getBroadcast(context, 1, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0)
|
setExactAndAllowWhileIdle(
|
||||||
val now = Calendar.getInstance().apply {
|
AlarmManager.RTC,
|
||||||
set(Calendar.MILLISECOND, 0)
|
it * MINUTE,
|
||||||
set(Calendar.SECOND, 0)
|
PendingIntent.getBroadcast(context, it, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
listOf(10, 15, 20).forEach {
|
|
||||||
setExact(AlarmManager.RTC_WAKEUP, now.timeInMillis + 1000 * 60 * it, pi)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeUpdates(context: Context) {
|
fun removeUpdates(context: Context) {
|
||||||
val intent = Intent(context, WeatherReceiver::class.java)
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
val sender = PendingIntent.getBroadcast(context, 1, intent, 0)
|
cancel(PendingIntent.getBroadcast(context, 0, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0))
|
||||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
listOf(10, 20, 30).forEach {
|
||||||
alarmManager.cancel(sender)
|
cancel(PendingIntent.getBroadcast(context, it, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.services
|
||||||
|
|
||||||
|
import android.app.job.JobInfo
|
||||||
|
import android.app.job.JobParameters
|
||||||
|
import android.app.job.JobScheduler
|
||||||
|
import android.app.job.JobService
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.provider.CalendarContract
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
|
||||||
|
class BatteryListenerJob : JobService() {
|
||||||
|
override fun onStartJob(params: JobParameters): Boolean {
|
||||||
|
MainWidget.updateWidget(this)
|
||||||
|
schedule(
|
||||||
|
this
|
||||||
|
)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
|
override fun onStopJob(params: JobParameters): Boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val chargingJobId = 1006
|
||||||
|
private const val notChargingJobId = 1007
|
||||||
|
fun schedule(context: Context) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
|
remove(context)
|
||||||
|
val componentName = ComponentName(
|
||||||
|
context,
|
||||||
|
EventListenerJob::class.java
|
||||||
|
)
|
||||||
|
with(context.getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler) {
|
||||||
|
schedule(
|
||||||
|
JobInfo.Builder(chargingJobId, componentName)
|
||||||
|
.setRequiresCharging(true)
|
||||||
|
.setPersisted(true)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
schedule(
|
||||||
|
JobInfo.Builder(notChargingJobId, componentName)
|
||||||
|
.setRequiresCharging(false)
|
||||||
|
.setPersisted(true)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun remove(context: Context) {
|
||||||
|
val js = context.getSystemService(JobScheduler::class.java)
|
||||||
|
js?.cancel(chargingJobId)
|
||||||
|
js?.cancel(notChargingJobId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,9 @@ import com.tommasoberlose.anotherwidget.databinding.ActivityCustomDateBinding
|
|||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.helpers.DateHelper
|
import com.tommasoberlose.anotherwidget.helpers.DateHelper
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.CustomDateViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.CustomDateViewModel
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.getCapWordString
|
||||||
import com.tommasoberlose.anotherwidget.utils.openURI
|
import com.tommasoberlose.anotherwidget.utils.openURI
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.toast
|
||||||
import kotlinx.android.synthetic.main.activity_custom_date.*
|
import kotlinx.android.synthetic.main.activity_custom_date.*
|
||||||
import kotlinx.android.synthetic.main.activity_custom_location.action_back
|
import kotlinx.android.synthetic.main.activity_custom_location.action_back
|
||||||
import kotlinx.android.synthetic.main.activity_custom_location.list_view
|
import kotlinx.android.synthetic.main.activity_custom_location.list_view
|
||||||
@ -78,7 +80,7 @@ class CustomDateActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
delay(200)
|
delay(200)
|
||||||
val text = if (dateFormat != "") {
|
var text = if (dateFormat != "") {
|
||||||
try {
|
try {
|
||||||
SimpleDateFormat(dateFormat, Locale.getDefault()).format(DATE.time)
|
SimpleDateFormat(dateFormat, Locale.getDefault()).format(DATE.time)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@ -88,6 +90,10 @@ class CustomDateActivity : AppCompatActivity() {
|
|||||||
"__"
|
"__"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Preferences.isDateCapitalize) {
|
||||||
|
text = text.getCapWordString()
|
||||||
|
}
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
action_save.isVisible = text != ERROR_STRING
|
action_save.isVisible = text != ERROR_STRING
|
||||||
loader.visibility = View.INVISIBLE
|
loader.visibility = View.INVISIBLE
|
||||||
@ -96,6 +102,11 @@ class CustomDateActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
viewModel.isDateCapitalize.observe(this, Observer {
|
||||||
|
viewModel.dateInput.value = viewModel.dateInput.value
|
||||||
|
binding.isdCapitalizeEnabled = it
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
@ -108,6 +119,15 @@ class CustomDateActivity : AppCompatActivity() {
|
|||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action_capitalize.setOnClickListener {
|
||||||
|
Preferences.isDateCapitalize = !Preferences.isDateCapitalize
|
||||||
|
}
|
||||||
|
|
||||||
|
action_capitalize.setOnLongClickListener {
|
||||||
|
toast(getString(R.string.action_capitalize_the_date))
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
action_date_format_info.setOnClickListener {
|
action_date_format_info.setOnClickListener {
|
||||||
openURI("https://developer.android.com/reference/java/text/SimpleDateFormat")
|
openURI("https://developer.android.com/reference/java/text/SimpleDateFormat")
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import android.annotation.SuppressLint
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.location.Address
|
import android.location.Address
|
||||||
import android.location.Geocoder
|
import android.location.Geocoder
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
@ -125,7 +126,7 @@ class CustomLocationActivity : AppCompatActivity() {
|
|||||||
private fun requirePermission() {
|
private fun requirePermission() {
|
||||||
Dexter.withContext(this)
|
Dexter.withContext(this)
|
||||||
.withPermissions(
|
.withPermissions(
|
||||||
Manifest.permission.ACCESS_FINE_LOCATION
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
|
||||||
).withListener(object: MultiplePermissionsListener {
|
).withListener(object: MultiplePermissionsListener {
|
||||||
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
||||||
report?.let {
|
report?.let {
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.activities
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.databinding.DataBindingUtil
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.databinding.ActivityIntegrationsBinding
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.IntegrationsViewModel
|
||||||
|
import kotlinx.android.synthetic.main.activity_integrations.*
|
||||||
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
|
|
||||||
|
class IntegrationsActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
private lateinit var adapter: SlimAdapter
|
||||||
|
private lateinit var viewModel: IntegrationsViewModel
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
viewModel = ViewModelProvider(this).get(IntegrationsViewModel::class.java)
|
||||||
|
val binding = DataBindingUtil.setContentView<ActivityIntegrationsBinding>(this, R.layout.activity_integrations)
|
||||||
|
|
||||||
|
list_view.setHasFixedSize(true)
|
||||||
|
val mLayoutManager = LinearLayoutManager(this)
|
||||||
|
list_view.layoutManager = mLayoutManager
|
||||||
|
|
||||||
|
adapter = SlimAdapter.create()
|
||||||
|
adapter
|
||||||
|
.register<String>(R.layout.application_info_layout) { _, injector ->
|
||||||
|
injector
|
||||||
|
.text(R.id.text, getString(R.string.default_name))
|
||||||
|
|
||||||
|
}
|
||||||
|
.attachTo(list_view)
|
||||||
|
|
||||||
|
setupListener()
|
||||||
|
subscribeUi(binding, viewModel)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun subscribeUi(binding: ActivityIntegrationsBinding, viewModel: IntegrationsViewModel) {
|
||||||
|
binding.viewModel = viewModel
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupListener() {
|
||||||
|
action_back.setOnClickListener {
|
||||||
|
onBackPressed()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,50 +1,73 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.activities
|
package com.tommasoberlose.anotherwidget.ui.activities
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.appwidget.AppWidgetManager
|
import android.appwidget.AppWidgetManager
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.Matrix
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.util.DisplayMetrics
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.animation.addListener
|
import androidx.core.animation.addListener
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
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.navigation.NavController
|
||||||
|
import androidx.navigation.Navigation
|
||||||
|
import com.chibatching.kotpref.Kotpref
|
||||||
|
import com.google.android.material.badge.BadgeDrawable
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
|
import com.karumi.dexter.Dexter
|
||||||
|
import com.karumi.dexter.MultiplePermissionsReport
|
||||||
|
import com.karumi.dexter.PermissionToken
|
||||||
|
import com.karumi.dexter.listener.PermissionRequest
|
||||||
|
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
|
||||||
import com.tommasoberlose.anotherwidget.global.Actions
|
import com.tommasoberlose.anotherwidget.global.Actions
|
||||||
|
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.BitmapHelper
|
import com.tommasoberlose.anotherwidget.helpers.BitmapHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||||
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||||
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.getCurrentWallpaper
|
import com.tommasoberlose.anotherwidget.utils.getCurrentWallpaper
|
||||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.android.synthetic.main.the_widget_sans.*
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceChangeListener {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private var mAppWidgetId: Int = -1
|
private var mAppWidgetId: Int = -1
|
||||||
private lateinit var viewModel: MainViewModel
|
private lateinit var viewModel: MainViewModel
|
||||||
|
private val mainNavController: NavController? by lazy {
|
||||||
|
Navigation.findNavController(
|
||||||
|
this,
|
||||||
|
R.id.content_fragment
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -53,132 +76,22 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
|
|||||||
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
|
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
|
||||||
|
|
||||||
controlExtras(intent)
|
controlExtras(intent)
|
||||||
|
if (Preferences.showWallpaper) {
|
||||||
// Viewpager
|
requirePermission()
|
||||||
pager.adapter = ViewPagerAdapter(this)
|
|
||||||
pager.offscreenPageLimit = 4
|
|
||||||
TabLayoutMediator(tabs, pager) { tab, position ->
|
|
||||||
tab.text = when (position) {
|
|
||||||
0 -> getString(R.string.settings_general_title)
|
|
||||||
1 -> getString(R.string.settings_calendar_title)
|
|
||||||
2 -> getString(R.string.settings_weather_title)
|
|
||||||
3 -> getString(R.string.settings_clock_title)
|
|
||||||
4 -> getString(R.string.advanced_settings_title)
|
|
||||||
else -> ""
|
|
||||||
}
|
|
||||||
}.attach()
|
|
||||||
|
|
||||||
// Init clock
|
|
||||||
clock.setTextColor(ColorHelper.getFontColor())
|
|
||||||
clock.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(this@MainActivity))
|
|
||||||
clock.format12Hour = "hh:mm"
|
|
||||||
clock.isVisible = Preferences.showClock
|
|
||||||
|
|
||||||
preview.layoutParams = preview.layoutParams.apply {
|
|
||||||
height = 160.toPixel(this@MainActivity) + if (Preferences.showClock) 100.toPixel(this@MainActivity) else 0
|
|
||||||
}
|
|
||||||
|
|
||||||
Preferences.preferences.registerOnSharedPreferenceChangeListener(this)
|
|
||||||
subscribeUi(viewModel)
|
|
||||||
updateUI()
|
|
||||||
|
|
||||||
CalendarHelper.updateEventList(this)
|
|
||||||
WeatherHelper.updateWeather(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
private var uiJob: Job? = null
|
|
||||||
|
|
||||||
private fun updateUI() {
|
|
||||||
preview.setCardBackgroundColor(getColor(if (ColorHelper.getFontColor().isColorDark()) android.R.color.white else R.color.colorAccent))
|
|
||||||
val generatedView = MainWidget.generateWidgetView(this@MainActivity)
|
|
||||||
generatedView.measure(0, 0)
|
|
||||||
preview.measure(0, 0)
|
|
||||||
|
|
||||||
uiJob?.cancel()
|
|
||||||
uiJob = lifecycleScope.launch(Dispatchers.IO) {
|
|
||||||
val bitmap = BitmapHelper.getBitmapFromView(generatedView, if (preview.width > 0) preview.width else generatedView.measuredWidth, generatedView.measuredHeight)
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
// Clock
|
|
||||||
clock.setTextColor(ColorHelper.getFontColor())
|
|
||||||
clock.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(this@MainActivity))
|
|
||||||
clock.format12Hour = "hh:mm"
|
|
||||||
|
|
||||||
if ((Preferences.showClock && !clock.isVisible) || (!Preferences.showClock && clock.isVisible)) {
|
|
||||||
if (Preferences.showClock) {
|
|
||||||
clock.layoutParams = clock.layoutParams.apply {
|
|
||||||
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
}
|
|
||||||
clock.measure(0, 0)
|
|
||||||
}
|
|
||||||
val initialHeight = clock.measuredHeight
|
|
||||||
ValueAnimator.ofFloat(
|
|
||||||
if (Preferences.showClock) 0f else 1f,
|
|
||||||
if (Preferences.showClock) 1f else 0f
|
|
||||||
).apply {
|
|
||||||
duration = 500L
|
|
||||||
addUpdateListener {
|
|
||||||
val animatedValue = animatedValue as Float
|
|
||||||
clock.layoutParams = clock.layoutParams.apply {
|
|
||||||
height = (initialHeight * animatedValue).toInt()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addListener(
|
|
||||||
onStart = {
|
|
||||||
if (Preferences.showClock) {
|
|
||||||
clock.isVisible = true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onEnd = {
|
|
||||||
if (!Preferences.showClock) {
|
|
||||||
clock.isVisible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}.start()
|
|
||||||
|
|
||||||
ValueAnimator.ofInt(
|
|
||||||
preview.height,
|
|
||||||
160.toPixel(this@MainActivity) + if (Preferences.showClock) 100.toPixel(this@MainActivity) else 0
|
|
||||||
).apply {
|
|
||||||
duration = 500L
|
|
||||||
addUpdateListener {
|
|
||||||
val animatedValue = animatedValue as Int
|
|
||||||
val layoutParams = preview.layoutParams
|
|
||||||
layoutParams.height = animatedValue
|
|
||||||
preview.layoutParams = layoutParams
|
|
||||||
}
|
|
||||||
}.start()
|
|
||||||
} else {
|
|
||||||
clock.layoutParams = clock.layoutParams.apply {
|
|
||||||
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
}
|
|
||||||
clock.measure(0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
widget_bitmap.setImageBitmap(bitmap)
|
|
||||||
widget_loader.animate().scaleX(0f).scaleY(0f).start()
|
|
||||||
widget.animate().alpha(1f).start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun subscribeUi(viewModel: MainViewModel) {
|
|
||||||
viewModel.showWallpaper.observe(this, Observer {
|
|
||||||
widget_bg.setImageDrawable(if (it) getCurrentWallpaper() else null)
|
|
||||||
})
|
|
||||||
|
|
||||||
logo.setOnClickListener {
|
|
||||||
// startActivity(Intent(this, SupportDevActivity::class.java))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
override fun onBackPressed() {
|
||||||
|
if (mainNavController?.currentDestination?.id == R.id.appMainFragment) {
|
||||||
if (mAppWidgetId > 0) {
|
if (mAppWidgetId > 0) {
|
||||||
addNewWidget()
|
addNewWidget()
|
||||||
} else {
|
} else {
|
||||||
setResult(Activity.RESULT_OK)
|
setResult(Activity.RESULT_OK)
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
super.onBackPressed()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent?) {
|
override fun onNewIntent(intent: Intent?) {
|
||||||
@ -217,30 +130,27 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
|
|||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
private fun requirePermission() {
|
||||||
super.onDestroy()
|
Dexter.withContext(this)
|
||||||
Preferences.preferences.unregisterOnSharedPreferenceChangeListener(this)
|
.withPermissions(
|
||||||
|
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||||
|
).withListener(object : MultiplePermissionsListener {
|
||||||
|
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
||||||
|
report?.let {
|
||||||
|
Preferences.showWallpaper = false
|
||||||
|
Preferences.showWallpaper = report.areAllPermissionsGranted()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(preferences: SharedPreferences, p1: String) {
|
override fun onPermissionRationaleShouldBeShown(
|
||||||
updateUI()
|
permissions: MutableList<PermissionRequest>?,
|
||||||
MainWidget.updateWidget(this)
|
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?.cancelPermissionRequest()
|
||||||
}
|
}
|
||||||
|
})
|
||||||
override fun onStart() {
|
.check()
|
||||||
super.onStart()
|
|
||||||
EventBus.getDefault().register(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStop() {
|
|
||||||
super.onStop()
|
|
||||||
EventBus.getDefault().unregister(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
class UpdateUiMessageEvent
|
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
|
||||||
fun onMessageEvent(ignore: UpdateUiMessageEvent?) {
|
|
||||||
updateUI()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import android.location.Address
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
@ -45,8 +46,17 @@ class SupportDevActivity : AppCompatActivity(), PurchasesUpdatedListener {
|
|||||||
adapter = SlimAdapter.create()
|
adapter = SlimAdapter.create()
|
||||||
adapter
|
adapter
|
||||||
.register<SkuDetails>(R.layout.inapp_product_layout) { item, injector ->
|
.register<SkuDetails>(R.layout.inapp_product_layout) { item, injector ->
|
||||||
|
item.sku
|
||||||
injector
|
injector
|
||||||
.text(R.id.product_title, item.title.replace("(Another Widget)", ""))
|
.with<TextView>(R.id.product_title) {
|
||||||
|
it.text = when (item.sku) {
|
||||||
|
"donation_coffee" -> getString(R.string.donation_coffee)
|
||||||
|
"donation_donuts" -> getString(R.string.donation_donuts)
|
||||||
|
"donation_breakfast" -> getString(R.string.donation_breakfast)
|
||||||
|
"donation_lunch" -> getString(R.string.donation_lunch)
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
}
|
||||||
.text(R.id.product_price, item.price)
|
.text(R.id.product_price, item.price)
|
||||||
.clicked(R.id.item) {
|
.clicked(R.id.item) {
|
||||||
viewModel.purchase(this, item)
|
viewModel.purchase(this, item)
|
||||||
|
@ -32,11 +32,6 @@ class WeatherProviderActivity : AppCompatActivity() {
|
|||||||
openURI("https://home.openweathermap.org/users/sign_up")
|
openURI("https://home.openweathermap.org/users/sign_up")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
||||||
last_info.text = Html.fromHtml(getString(R.string.api_key_info_all_set), Html.FROM_HTML_MODE_LEGACY)
|
|
||||||
} else {
|
|
||||||
last_info.text = Html.fromHtml(getString(R.string.api_key_info_all_set))
|
|
||||||
}
|
|
||||||
api_key.editText?.setText(Preferences.weatherProviderApi)
|
api_key.editText?.setText(Preferences.weatherProviderApi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,11 @@ class ViewPagerAdapter(fragmentActivity: FragmentActivity) :
|
|||||||
|
|
||||||
override fun createFragment(position: Int): Fragment {
|
override fun createFragment(position: Int): Fragment {
|
||||||
return when (position) {
|
return when (position) {
|
||||||
1 -> CalendarSettingsFragment.newInstance()
|
1 -> CalendarTabFragment.newInstance()
|
||||||
2 -> WeatherSettingsFragment.newInstance()
|
2 -> WeatherTabFragment.newInstance()
|
||||||
3 -> ClockSettingsFragment.newInstance()
|
3 -> ClockTabFragment.newInstance()
|
||||||
4 -> AdvancedSettingsFragment.newInstance()
|
4 -> GlanceTabFragment.newInstance()
|
||||||
else -> GeneralSettingsFragment.newInstance()
|
else -> GeneralTabFragment.newInstance()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,14 +2,12 @@ package com.tommasoberlose.anotherwidget.ui.fragments
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
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 androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
@ -42,14 +40,13 @@ 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.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.Comparator
|
import kotlin.Comparator
|
||||||
|
|
||||||
class CalendarSettingsFragment : Fragment() {
|
class CalendarTabFragment : Fragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance() = CalendarSettingsFragment()
|
fun newInstance() = CalendarTabFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var viewModel: MainViewModel
|
private lateinit var viewModel: MainViewModel
|
||||||
@ -84,6 +81,8 @@ class CalendarSettingsFragment : Fragment() {
|
|||||||
binding: FragmentCalendarSettingsBinding,
|
binding: FragmentCalendarSettingsBinding,
|
||||||
viewModel: MainViewModel
|
viewModel: MainViewModel
|
||||||
) {
|
) {
|
||||||
|
binding.isCalendarEnabled = Preferences.showEvents
|
||||||
|
|
||||||
viewModel.showEvents.observe(viewLifecycleOwner, Observer {
|
viewModel.showEvents.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.isCalendarEnabled = it
|
binding.isCalendarEnabled = it
|
||||||
@ -99,57 +98,65 @@ class CalendarSettingsFragment : Fragment() {
|
|||||||
|
|
||||||
viewModel.calendarAllDay.observe(viewLifecycleOwner, Observer {
|
viewModel.calendarAllDay.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
all_day_label.text =
|
all_day_label?.text =
|
||||||
if (it) getString(R.string.settings_all_day_subtitle_visible) else getString(R.string.settings_all_day_subtitle_gone)
|
if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||||
}
|
}
|
||||||
checkReadEventsPermission()
|
checkReadEventsPermission()
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.showDeclinedEvents.observe(viewLifecycleOwner, Observer {
|
viewModel.showDeclinedEvents.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
show_declined_events_label.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
show_declined_events_label?.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||||
}
|
}
|
||||||
checkReadEventsPermission()
|
checkReadEventsPermission()
|
||||||
})
|
})
|
||||||
|
|
||||||
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))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.showDiffTime.observe(viewLifecycleOwner, Observer {
|
viewModel.showDiffTime.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
show_diff_time_label.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
show_diff_time_label?.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.widgetUpdateFrequency.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
widget_update_frequency_label?.text = when (it) {
|
||||||
|
Constants.WidgetUpdateFrequency.HIGH.value -> getString(R.string.settings_widget_update_frequency_high)
|
||||||
|
Constants.WidgetUpdateFrequency.DEFAULT.value -> getString(R.string.settings_widget_update_frequency_default)
|
||||||
|
Constants.WidgetUpdateFrequency.LOW.value -> getString(R.string.settings_widget_update_frequency_low)
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.showUntil.observe(viewLifecycleOwner, Observer {
|
viewModel.showUntil.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
show_until_label.text = getString(SettingsStringHelper.getShowUntilString(it))
|
show_until_label?.text = getString(SettingsStringHelper.getShowUntilString(it))
|
||||||
}
|
}
|
||||||
checkReadEventsPermission()
|
checkReadEventsPermission()
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.showNextEvent.observe(viewLifecycleOwner, Observer {
|
viewModel.showNextEvent.observe(viewLifecycleOwner, Observer {
|
||||||
show_multiple_events_label.setTextKeepState(if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible))
|
|
||||||
})
|
|
||||||
|
|
||||||
viewModel.dateFormat.observe(viewLifecycleOwner, Observer {
|
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
date_format_label.text = DateHelper.getDateText(requireContext(), Calendar.getInstance())
|
show_multiple_events_label?.text =
|
||||||
|
if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.calendarAppName.observe(viewLifecycleOwner, Observer {
|
viewModel.calendarAppName.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
calendar_app_label.text = if (it != "") it else getString(R.string.default_calendar_app)
|
calendar_app_label?.text = if (it != "") it else getString(R.string.default_calendar_app)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.eventAppName.observe(viewLifecycleOwner, Observer {
|
viewModel.openEventDetails.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
event_app_label.text = if (it != "") it else getString(R.string.default_calendar_app)
|
open_event_details_label?.text = if (it) getString(R.string.default_event_app) else getString(R.string.default_calendar_app)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -159,6 +166,16 @@ class CalendarSettingsFragment : Fragment() {
|
|||||||
|
|
||||||
action_show_events.setOnClickListener {
|
action_show_events.setOnClickListener {
|
||||||
Preferences.showEvents = !Preferences.showEvents
|
Preferences.showEvents = !Preferences.showEvents
|
||||||
|
if (Preferences.showEvents) {
|
||||||
|
requirePermission()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
show_events_switch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
||||||
|
Preferences.showEvents = enabled
|
||||||
|
if (Preferences.showEvents) {
|
||||||
|
requirePermission()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
action_filter_calendar.setOnClickListener {
|
action_filter_calendar.setOnClickListener {
|
||||||
@ -198,7 +215,7 @@ class CalendarSettingsFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dialog.addItem(
|
dialog.addItem(
|
||||||
if (calendarSelectorList[index].name == calendarSelectorList[index].accountName) getString(R.string.account_events) else calendarSelectorList[index].name,
|
if (calendarSelectorList[index].name == calendarSelectorList[index].accountName) getString(R.string.main_calendar) else calendarSelectorList[index].name,
|
||||||
calendarSelectorList[index].id
|
calendarSelectorList[index].id
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -215,8 +232,8 @@ class CalendarSettingsFragment : Fragment() {
|
|||||||
action_show_all_day.setOnClickListener {
|
action_show_all_day.setOnClickListener {
|
||||||
if (Preferences.showEvents) {
|
if (Preferences.showEvents) {
|
||||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_all_day_title)).setSelectedValue(Preferences.calendarAllDay)
|
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_all_day_title)).setSelectedValue(Preferences.calendarAllDay)
|
||||||
.addItem(getString(R.string.settings_all_day_subtitle_visible), true)
|
.addItem(getString(R.string.settings_visible), true)
|
||||||
.addItem(getString(R.string.settings_all_day_subtitle_gone), false)
|
.addItem(getString(R.string.settings_not_visible), false)
|
||||||
.addOnSelectItemListener { value ->
|
.addOnSelectItemListener { value ->
|
||||||
Preferences.calendarAllDay = value
|
Preferences.calendarAllDay = value
|
||||||
}.show()
|
}.show()
|
||||||
@ -256,6 +273,18 @@ class CalendarSettingsFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action_widget_update_frequency.setOnClickListener {
|
||||||
|
if (Preferences.showEvents) {
|
||||||
|
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_widget_update_frequency_title), message = getString(R.string.settings_widget_update_frequency_subtitle)).setSelectedValue(Preferences.widgetUpdateFrequency)
|
||||||
|
.addItem(getString(R.string.settings_widget_update_frequency_high), Constants.WidgetUpdateFrequency.HIGH.value)
|
||||||
|
.addItem(getString(R.string.settings_widget_update_frequency_default), Constants.WidgetUpdateFrequency.DEFAULT.value)
|
||||||
|
.addItem(getString(R.string.settings_widget_update_frequency_low), Constants.WidgetUpdateFrequency.LOW.value)
|
||||||
|
.addOnSelectItemListener { value ->
|
||||||
|
Preferences.widgetUpdateFrequency = value
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
action_second_row_info.setOnClickListener {
|
action_second_row_info.setOnClickListener {
|
||||||
if (Preferences.showEvents) {
|
if (Preferences.showEvents) {
|
||||||
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_second_row_info_title)).setSelectedValue(Preferences.secondRowInformation)
|
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_second_row_info_title)).setSelectedValue(Preferences.secondRowInformation)
|
||||||
@ -271,7 +300,7 @@ class CalendarSettingsFragment : Fragment() {
|
|||||||
action_show_until.setOnClickListener {
|
action_show_until.setOnClickListener {
|
||||||
if (Preferences.showEvents) {
|
if (Preferences.showEvents) {
|
||||||
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_show_until_title)).setSelectedValue(Preferences.showUntil)
|
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_show_until_title)).setSelectedValue(Preferences.showUntil)
|
||||||
intArrayOf(6,7,0,1,2,3,4,5).forEach {
|
intArrayOf(6,7,0,1,2,3).forEach {
|
||||||
dialog.addItem(getString(SettingsStringHelper.getShowUntilString(it)), it)
|
dialog.addItem(getString(SettingsStringHelper.getShowUntilString(it)), it)
|
||||||
}
|
}
|
||||||
dialog.addOnSelectItemListener { value ->
|
dialog.addOnSelectItemListener { value ->
|
||||||
@ -280,31 +309,17 @@ class CalendarSettingsFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
action_date_format.setOnClickListener {
|
action_open_event_details.setOnClickListener {
|
||||||
if (Preferences.showEvents) {
|
if (Preferences.showEvents) {
|
||||||
val now = Calendar.getInstance()
|
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_event_app_title)).setSelectedValue(Preferences.openEventDetails)
|
||||||
val dialog = BottomSheetMenu<String>(requireContext(), header = getString(R.string.settings_date_format_title)).setSelectedValue(Preferences.dateFormat)
|
.addItem(getString(R.string.default_event_app), true)
|
||||||
|
.addItem(getString(R.string.default_calendar_app), false)
|
||||||
dialog.addItem(DateHelper.getDefaultDateText(requireContext(), now), "")
|
.addOnSelectItemListener { value ->
|
||||||
if (Preferences.dateFormat != "") {
|
Preferences.openEventDetails = value
|
||||||
dialog.addItem(DateHelper.getDateText(requireContext(), now), Preferences.dateFormat)
|
|
||||||
}
|
|
||||||
dialog.addItem(getString(R.string.custom_date_format), "-")
|
|
||||||
|
|
||||||
dialog.addOnSelectItemListener { value ->
|
|
||||||
if (value == "-") {
|
|
||||||
startActivity(Intent(requireContext(), CustomDateActivity::class.java))
|
|
||||||
} else {
|
|
||||||
Preferences.dateFormat = value
|
|
||||||
}
|
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
action_event_app.setOnClickListener {
|
|
||||||
startActivityForResult(Intent(requireContext(), ChooseApplicationActivity::class.java), RequestCode.EVENT_APP_REQUEST_CODE.code)
|
|
||||||
}
|
|
||||||
|
|
||||||
action_calendar_app.setOnClickListener {
|
action_calendar_app.setOnClickListener {
|
||||||
startActivityForResult(Intent(requireContext(), ChooseApplicationActivity::class.java), RequestCode.CALENDAR_APP_REQUEST_CODE.code)
|
startActivityForResult(Intent(requireContext(), ChooseApplicationActivity::class.java), RequestCode.CALENDAR_APP_REQUEST_CODE.code)
|
||||||
}
|
}
|
||||||
@ -312,13 +327,13 @@ class CalendarSettingsFragment : Fragment() {
|
|||||||
|
|
||||||
private fun checkReadEventsPermission(showEvents: Boolean = Preferences.showEvents) {
|
private fun checkReadEventsPermission(showEvents: Boolean = Preferences.showEvents) {
|
||||||
if (activity?.checkGrantedPermission(Manifest.permission.READ_CALENDAR) == true) {
|
if (activity?.checkGrantedPermission(Manifest.permission.READ_CALENDAR) == true) {
|
||||||
show_events_label.text = if (showEvents) getString(R.string.show_events_visible) else getString(R.string.show_events_not_visible)
|
show_events_label?.text = if (showEvents) getString(R.string.show_events_visible) else getString(R.string.show_events_not_visible)
|
||||||
read_calendar_permission_alert_icon.isVisible = false
|
read_calendar_permission_alert?.isVisible = false
|
||||||
CalendarHelper.updateEventList(requireContext())
|
CalendarHelper.updateEventList(requireContext())
|
||||||
} else {
|
} else {
|
||||||
show_events_label.text = if (showEvents) getString(R.string.description_permission_calendar) else getString(R.string.show_events_not_visible)
|
show_events_label?.text = if (showEvents) getString(R.string.description_permission_calendar) else getString(R.string.show_events_not_visible)
|
||||||
read_calendar_permission_alert_icon.isVisible = showEvents
|
read_calendar_permission_alert?.isVisible = showEvents
|
||||||
read_calendar_permission_alert_icon.setOnClickListener {
|
read_calendar_permission_alert?.setOnClickListener {
|
||||||
requirePermission()
|
requirePermission()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -333,6 +348,8 @@ class CalendarSettingsFragment : Fragment() {
|
|||||||
report?.let {
|
report?.let {
|
||||||
if (report.areAllPermissionsGranted()){
|
if (report.areAllPermissionsGranted()){
|
||||||
checkReadEventsPermission()
|
checkReadEventsPermission()
|
||||||
|
} else {
|
||||||
|
Preferences.showEvents = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,12 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.fragments
|
package com.tommasoberlose.anotherwidget.ui.fragments
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.app.AlarmManager
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -14,25 +19,35 @@ import androidx.lifecycle.ViewModelProvider
|
|||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.chibatching.kotpref.bulk
|
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.BottomSheetMenu
|
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||||
import com.tommasoberlose.anotherwidget.databinding.FragmentClockSettingsBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentClockSettingsBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.global.RequestCode
|
import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toHexValue
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
||||||
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 kotlinx.android.synthetic.main.fragment_clock_settings.*
|
import kotlinx.android.synthetic.main.fragment_clock_settings.*
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.lang.Exception
|
||||||
|
|
||||||
class ClockSettingsFragment : Fragment() {
|
|
||||||
|
class ClockTabFragment : Fragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance() = ClockSettingsFragment()
|
fun newInstance() = ClockTabFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var viewModel: MainViewModel
|
private lateinit var viewModel: MainViewModel
|
||||||
|
private lateinit var colors: IntArray
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -57,6 +72,12 @@ class ClockSettingsFragment : Fragment() {
|
|||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
super.onActivityCreated(savedInstanceState)
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
val lazyColors = requireContext().resources.getIntArray(R.array.material_colors)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
colors = lazyColors
|
||||||
|
}
|
||||||
|
}
|
||||||
setupListener()
|
setupListener()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,14 +85,16 @@ class ClockSettingsFragment : Fragment() {
|
|||||||
binding: FragmentClockSettingsBinding,
|
binding: FragmentClockSettingsBinding,
|
||||||
viewModel: MainViewModel
|
viewModel: MainViewModel
|
||||||
) {
|
) {
|
||||||
|
binding.isClockVisible = Preferences.showClock
|
||||||
|
|
||||||
viewModel.showBigClockWarning.observe(viewLifecycleOwner, Observer {
|
viewModel.showBigClockWarning.observe(viewLifecycleOwner, Observer {
|
||||||
large_clock_warning.isVisible = it
|
large_clock_warning?.isVisible = it
|
||||||
small_clock_warning.isVisible = !it
|
small_clock_warning?.isVisible = !it
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.showClock.observe(viewLifecycleOwner, Observer {
|
viewModel.showClock.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
show_clock_label.text =
|
show_clock_label?.text =
|
||||||
if (it) getString(R.string.show_clock_visible) else getString(R.string.show_clock_not_visible)
|
if (it) getString(R.string.show_clock_visible) else getString(R.string.show_clock_not_visible)
|
||||||
binding.isClockVisible = it
|
binding.isClockVisible = it
|
||||||
}
|
}
|
||||||
@ -79,19 +102,52 @@ class ClockSettingsFragment : Fragment() {
|
|||||||
|
|
||||||
viewModel.clockTextSize.observe(viewLifecycleOwner, Observer {
|
viewModel.clockTextSize.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
clock_text_size_label.text = String.format("%.0fsp", it)
|
clock_text_size_label?.text = String.format("%.0fsp", it)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.showNextAlarm.observe(viewLifecycleOwner, Observer {
|
viewModel.showAMPMIndicator.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
show_next_alarm_label.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
ampm_indicator_label?.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.clockTextColor.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.clockTextAlpha == "00") {
|
||||||
|
clock_text_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
clock_text_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getClockFontColor())).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.clockTextAlpha.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.clockTextAlpha == "00") {
|
||||||
|
clock_text_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
clock_text_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getClockFontColor())).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.clockBottomMargin.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
clock_bottom_margin_label?.text = when (it) {
|
||||||
|
Constants.ClockBottomMargin.NONE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_none)
|
||||||
|
Constants.ClockBottomMargin.SMALL.value -> getString(R.string.settings_clock_bottom_margin_subtitle_small)
|
||||||
|
Constants.ClockBottomMargin.LARGE.value -> getString(R.string.settings_clock_bottom_margin_subtitle_large)
|
||||||
|
else -> getString(R.string.settings_clock_bottom_margin_subtitle_medium)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.clockAppName.observe(viewLifecycleOwner, Observer {
|
viewModel.clockAppName.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
clock_app_label.text =
|
clock_app_label?.text =
|
||||||
if (Preferences.clockAppName != "") Preferences.clockAppName else getString(R.string.default_clock_app)
|
if (Preferences.clockAppName != "") Preferences.clockAppName else getString(R.string.default_clock_app)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -106,6 +162,10 @@ class ClockSettingsFragment : Fragment() {
|
|||||||
Preferences.showClock = !Preferences.showClock
|
Preferences.showClock = !Preferences.showClock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
show_clock_switch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
||||||
|
Preferences.showClock = enabled
|
||||||
|
}
|
||||||
|
|
||||||
action_clock_text_size.setOnClickListener {
|
action_clock_text_size.setOnClickListener {
|
||||||
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.settings_clock_text_size_title)).setSelectedValue(Preferences.clockTextSize)
|
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.settings_clock_text_size_title)).setSelectedValue(Preferences.clockTextSize)
|
||||||
(46 downTo 12).filter { it % 2 == 0 }.forEach {
|
(46 downTo 12).filter { it % 2 == 0 }.forEach {
|
||||||
@ -116,12 +176,40 @@ class ClockSettingsFragment : Fragment() {
|
|||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
action_show_next_alarm.setOnClickListener {
|
action_ampm_indicator_size.setOnClickListener {
|
||||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_show_next_alarm_title)).setSelectedValue(Preferences.showNextAlarm)
|
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_ampm_indicator_title)).setSelectedValue(Preferences.showAMPMIndicator)
|
||||||
.addItem(getString(R.string.settings_visible), true)
|
.addItem(getString(R.string.settings_visible), true)
|
||||||
.addItem(getString(R.string.settings_not_visible), false)
|
.addItem(getString(R.string.settings_not_visible), false)
|
||||||
.addOnSelectItemListener { value ->
|
.addOnSelectItemListener { value ->
|
||||||
Preferences.showNextAlarm = value
|
Preferences.showAMPMIndicator = value
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
action_clock_text_color.setOnClickListener {
|
||||||
|
BottomSheetColorPicker(requireContext(),
|
||||||
|
colors = colors,
|
||||||
|
header = getString(R.string.settings_font_color_title),
|
||||||
|
getSelected = ColorHelper::getClockFontColorRgb,
|
||||||
|
onColorSelected = { color: Int ->
|
||||||
|
val colorString = Integer.toHexString(color)
|
||||||
|
Preferences.clockTextColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||||
|
},
|
||||||
|
showAlphaSelector = true,
|
||||||
|
alpha = Preferences.clockTextAlpha.toIntValue(),
|
||||||
|
onAlphaChangeListener = { alpha ->
|
||||||
|
Preferences.clockTextAlpha = alpha.toHexValue()
|
||||||
|
}
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
action_clock_bottom_margin_size.setOnClickListener {
|
||||||
|
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_clock_bottom_margin_title)).setSelectedValue(Preferences.clockBottomMargin)
|
||||||
|
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_none), Constants.ClockBottomMargin.NONE.value)
|
||||||
|
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_small), Constants.ClockBottomMargin.SMALL.value)
|
||||||
|
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_medium), Constants.ClockBottomMargin.MEDIUM.value)
|
||||||
|
.addItem(getString(R.string.settings_clock_bottom_margin_subtitle_large), Constants.ClockBottomMargin.LARGE.value)
|
||||||
|
.addOnSelectItemListener { value ->
|
||||||
|
Preferences.clockBottomMargin = value
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
@ -1,213 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.fragments
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.databinding.DataBindingUtil
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import com.tommasoberlose.anotherwidget.R
|
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
|
||||||
import com.tommasoberlose.anotherwidget.databinding.FragmentGeneralSettingsBinding
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
import com.tommasoberlose.anotherwidget.global.RequestCode
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
|
||||||
import kotlinx.android.synthetic.main.fragment_general_settings.*
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
|
|
||||||
class GeneralSettingsFragment : Fragment() {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun newInstance() = GeneralSettingsFragment()
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var viewModel: MainViewModel
|
|
||||||
private lateinit var colors: IntArray
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View {
|
|
||||||
|
|
||||||
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
|
||||||
val binding = DataBindingUtil.inflate<FragmentGeneralSettingsBinding>(inflater, R.layout.fragment_general_settings, container, false)
|
|
||||||
|
|
||||||
subscribeUi(viewModel)
|
|
||||||
|
|
||||||
binding.lifecycleOwner = this
|
|
||||||
binding.viewModel = viewModel
|
|
||||||
|
|
||||||
return binding.root
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
|
||||||
super.onActivityCreated(savedInstanceState)
|
|
||||||
|
|
||||||
setupListener()
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
|
||||||
val lazyColors = requireContext().resources.getIntArray(R.array.material_colors)
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
colors = lazyColors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun subscribeUi(
|
|
||||||
viewModel: MainViewModel
|
|
||||||
) {
|
|
||||||
|
|
||||||
viewModel.textMainSize.observe(viewLifecycleOwner, Observer {
|
|
||||||
maintainScrollPosition {
|
|
||||||
main_text_size_label.text = String.format("%.0fsp", it)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
viewModel.textSecondSize.observe(viewLifecycleOwner, Observer {
|
|
||||||
maintainScrollPosition {
|
|
||||||
second_text_size_label.text = String.format("%.0fsp", it)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
viewModel.textGlobalColor.observe(viewLifecycleOwner, Observer {
|
|
||||||
maintainScrollPosition {
|
|
||||||
try {
|
|
||||||
Color.parseColor(it)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Preferences.textGlobalColor = "#FFFFFF"
|
|
||||||
}
|
|
||||||
font_color_label.text = it.toUpperCase()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
viewModel.textShadow.observe(viewLifecycleOwner, Observer {
|
|
||||||
maintainScrollPosition {
|
|
||||||
text_shadow_label.text = getString(SettingsStringHelper.getTextShadowString(it))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
viewModel.customFont.observe(viewLifecycleOwner, Observer {
|
|
||||||
maintainScrollPosition {
|
|
||||||
custom_font_label.text = getString(SettingsStringHelper.getCustomFontLabel(it))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun maintainScrollPosition(callback: () -> Unit) {
|
|
||||||
val scrollPosition = scrollView.scrollY
|
|
||||||
callback.invoke()
|
|
||||||
lifecycleScope.launch {
|
|
||||||
delay(200)
|
|
||||||
scrollView.smoothScrollTo(0, scrollPosition)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupListener() {
|
|
||||||
action_main_text_size.setOnClickListener {
|
|
||||||
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.title_main_text_size)).setSelectedValue(Preferences.textMainSize)
|
|
||||||
(32 downTo 10).filter { it % 2 == 0 }.forEach {
|
|
||||||
dialog.addItem("${it}sp", it.toFloat())
|
|
||||||
}
|
|
||||||
dialog.addOnSelectItemListener { value ->
|
|
||||||
Preferences.textMainSize = value
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
action_second_text_size.setOnClickListener {
|
|
||||||
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.title_second_text_size)).setSelectedValue(Preferences.textSecondSize)
|
|
||||||
(28 downTo 10).filter { it % 2 == 0 }.forEach {
|
|
||||||
dialog.addItem("${it}sp", it.toFloat())
|
|
||||||
}
|
|
||||||
dialog.addOnSelectItemListener { value ->
|
|
||||||
Preferences.textSecondSize = value
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
action_font_color.setOnClickListener {
|
|
||||||
val textColor = try {
|
|
||||||
Color.parseColor(Preferences.textGlobalColor)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Preferences.textGlobalColor = "#FFFFFF"
|
|
||||||
Color.parseColor(Preferences.textGlobalColor)
|
|
||||||
}
|
|
||||||
BottomSheetColorPicker(requireContext(),
|
|
||||||
colors = colors,
|
|
||||||
header = getString(R.string.settings_font_color_title),
|
|
||||||
selected = textColor,
|
|
||||||
onColorSelected = { color: Int ->
|
|
||||||
val colorString = Integer.toHexString(color)
|
|
||||||
Preferences.textGlobalColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
|
||||||
}
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
action_text_shadow.setOnClickListener {
|
|
||||||
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.title_text_shadow)).setSelectedValue(Preferences.textShadow)
|
|
||||||
(2 downTo 0).forEach {
|
|
||||||
dialog.addItem(getString(SettingsStringHelper.getTextShadowString(it)), it)
|
|
||||||
}
|
|
||||||
dialog.addOnSelectItemListener { value ->
|
|
||||||
Preferences.textShadow = value
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
action_custom_font.setOnClickListener {
|
|
||||||
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_custom_font_title)).setSelectedValue(Preferences.customFont)
|
|
||||||
(0..1).forEach {
|
|
||||||
dialog.addItem(getString(SettingsStringHelper.getCustomFontLabel(it)), it)
|
|
||||||
}
|
|
||||||
dialog.addOnSelectItemListener { value ->
|
|
||||||
Preferences.customFont = value
|
|
||||||
}.show()
|
|
||||||
|
|
||||||
/*
|
|
||||||
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
|
||||||
intent.type = "* / *" TO FIX WITHOUT SPACE
|
|
||||||
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
|
||||||
|
|
||||||
try {
|
|
||||||
startActivityForResult(Intent.createChooser(intent, "Select a File to Upload"), Constants.CUSTOM_FONT_CHOOSER_REQUEST_CODE)
|
|
||||||
} catch (ex: android.content.ActivityNotFoundException) {
|
|
||||||
Toast.makeText(this, "Please install a File Manager.", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,351 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.fragments
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.databinding.DataBindingUtil
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
||||||
|
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||||
|
import com.tommasoberlose.anotherwidget.databinding.FragmentGeneralSettingsBinding
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.global.RequestCode
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toHexValue
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.DateHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.SettingsStringHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.CustomDateActivity
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
|
import kotlinx.android.synthetic.main.fragment_general_settings.*
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
class GeneralTabFragment : Fragment() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance() = GeneralTabFragment()
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var viewModel: MainViewModel
|
||||||
|
private lateinit var colors: IntArray
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
|
||||||
|
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
||||||
|
val binding = DataBindingUtil.inflate<FragmentGeneralSettingsBinding>(inflater, R.layout.fragment_general_settings, container, false)
|
||||||
|
|
||||||
|
subscribeUi(viewModel)
|
||||||
|
|
||||||
|
binding.lifecycleOwner = this
|
||||||
|
binding.viewModel = viewModel
|
||||||
|
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
|
setupListener()
|
||||||
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
val lazyColors = requireContext().resources.getIntArray(R.array.material_colors)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
colors = lazyColors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
private fun subscribeUi(
|
||||||
|
viewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
|
||||||
|
viewModel.textMainSize.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
main_text_size_label?.text = String.format("%.0fsp", it)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.textSecondSize.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
second_text_size_label?.text = String.format("%.0fsp", it)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.textGlobalColor.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.textGlobalAlpha == "00") {
|
||||||
|
font_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
font_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getFontColor())).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.textGlobalAlpha.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.textGlobalAlpha == "00") {
|
||||||
|
font_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
font_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getFontColor())).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.textSecondaryColor.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.textSecondaryAlpha == "00") {
|
||||||
|
secondary_font_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
secondary_font_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getSecondaryFontColor())).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.textSecondaryAlpha.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.textSecondaryAlpha == "00") {
|
||||||
|
secondary_font_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
secondary_font_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getSecondaryFontColor())).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.backgroundCardColor.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.backgroundCardAlpha == "00") {
|
||||||
|
background_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
background_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getBackgroundColor())).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.backgroundCardAlpha.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
if (Preferences.backgroundCardAlpha == "00") {
|
||||||
|
background_color_label?.text = getString(R.string.transparent)
|
||||||
|
} else {
|
||||||
|
background_color_label?.text =
|
||||||
|
"#%s".format(Integer.toHexString(ColorHelper.getBackgroundColor())).toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.textShadow.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
text_shadow_label?.text = getString(SettingsStringHelper.getTextShadowString(it))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.dateFormat.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
date_format_label?.text = DateHelper.getDateText(requireContext(), Calendar.getInstance())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.customFont.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
custom_font_label?.text = getString(SettingsStringHelper.getCustomFontLabel(it))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.showDividers.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
show_dividers_label?.text =
|
||||||
|
if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun maintainScrollPosition(callback: () -> Unit) {
|
||||||
|
val scrollPosition = scrollView.scrollY
|
||||||
|
callback.invoke()
|
||||||
|
lifecycleScope.launch {
|
||||||
|
delay(200)
|
||||||
|
scrollView.smoothScrollTo(0, scrollPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupListener() {
|
||||||
|
action_main_text_size.setOnClickListener {
|
||||||
|
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.title_main_text_size)).setSelectedValue(Preferences.textMainSize)
|
||||||
|
(40 downTo 10).filter { it % 2 == 0 }.forEach {
|
||||||
|
dialog.addItem("${it}sp", it.toFloat())
|
||||||
|
}
|
||||||
|
dialog.addOnSelectItemListener { value ->
|
||||||
|
Preferences.textMainSize = value
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
action_second_text_size.setOnClickListener {
|
||||||
|
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.title_second_text_size)).setSelectedValue(Preferences.textSecondSize)
|
||||||
|
(40 downTo 10).filter { it % 2 == 0 }.forEach {
|
||||||
|
dialog.addItem("${it}sp", it.toFloat())
|
||||||
|
}
|
||||||
|
dialog.addOnSelectItemListener { value ->
|
||||||
|
Preferences.textSecondSize = value
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
action_font_color.setOnClickListener {
|
||||||
|
BottomSheetColorPicker(requireContext(),
|
||||||
|
colors = colors,
|
||||||
|
header = getString(R.string.settings_font_color_title),
|
||||||
|
getSelected = ColorHelper::getFontColorRgb,
|
||||||
|
onColorSelected = { color: Int ->
|
||||||
|
val colorString = Integer.toHexString(color)
|
||||||
|
Preferences.textGlobalColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||||
|
},
|
||||||
|
showAlphaSelector = true,
|
||||||
|
alpha = Preferences.textGlobalAlpha.toIntValue(),
|
||||||
|
onAlphaChangeListener = { alpha ->
|
||||||
|
Preferences.textGlobalAlpha = alpha.toHexValue()
|
||||||
|
}
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
action_secondary_font_color.setOnClickListener {
|
||||||
|
BottomSheetColorPicker(requireContext(),
|
||||||
|
colors = colors,
|
||||||
|
header = getString(R.string.settings_secondary_font_color_title),
|
||||||
|
getSelected = ColorHelper::getSecondaryFontColorRgb,
|
||||||
|
onColorSelected = { color: Int ->
|
||||||
|
val colorString = Integer.toHexString(color)
|
||||||
|
Preferences.textSecondaryColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||||
|
},
|
||||||
|
showAlphaSelector = true,
|
||||||
|
alpha = Preferences.textSecondaryAlpha.toIntValue(),
|
||||||
|
onAlphaChangeListener = { alpha ->
|
||||||
|
Preferences.textSecondaryAlpha = alpha.toHexValue()
|
||||||
|
}
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
action_date_format.setOnClickListener {
|
||||||
|
if (Preferences.showEvents) {
|
||||||
|
val now = Calendar.getInstance()
|
||||||
|
val dialog = BottomSheetMenu<String>(requireContext(), header = getString(R.string.settings_date_format_title)).setSelectedValue(Preferences.dateFormat)
|
||||||
|
|
||||||
|
dialog.addItem(DateHelper.getDefaultDateText(requireContext(), now), "")
|
||||||
|
if (Preferences.dateFormat != "") {
|
||||||
|
dialog.addItem(DateHelper.getDateText(requireContext(), now), Preferences.dateFormat)
|
||||||
|
}
|
||||||
|
dialog.addItem(getString(R.string.custom_date_format), "-")
|
||||||
|
|
||||||
|
dialog.addOnSelectItemListener { value ->
|
||||||
|
if (value == "-") {
|
||||||
|
startActivity(Intent(requireContext(), CustomDateActivity::class.java))
|
||||||
|
} else {
|
||||||
|
Preferences.dateFormat = value
|
||||||
|
}
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
action_background_color.setOnClickListener {
|
||||||
|
BottomSheetColorPicker(requireContext(),
|
||||||
|
colors = colors,
|
||||||
|
header = getString(R.string.settings_background_color_title),
|
||||||
|
getSelected = { ColorHelper.getBackgroundColorRgb() },
|
||||||
|
onColorSelected = { color: Int ->
|
||||||
|
val colorString = Integer.toHexString(color)
|
||||||
|
Preferences.backgroundCardColor = "#" + if (colorString.length > 6) colorString.substring(2) else colorString
|
||||||
|
},
|
||||||
|
showAlphaSelector = true,
|
||||||
|
alpha = Preferences.backgroundCardAlpha.toIntValue(),
|
||||||
|
onAlphaChangeListener = { alpha ->
|
||||||
|
Preferences.backgroundCardAlpha = alpha.toHexValue()
|
||||||
|
}
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
action_text_shadow.setOnClickListener {
|
||||||
|
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.title_text_shadow)).setSelectedValue(Preferences.textShadow)
|
||||||
|
(2 downTo 0).forEach {
|
||||||
|
dialog.addItem(getString(SettingsStringHelper.getTextShadowString(it)), it)
|
||||||
|
}
|
||||||
|
dialog.addOnSelectItemListener { value ->
|
||||||
|
Preferences.textShadow = value
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
action_custom_font.setOnClickListener {
|
||||||
|
val dialog = BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_custom_font_title)).setSelectedValue(Preferences.customFont)
|
||||||
|
(0..1).forEach {
|
||||||
|
dialog.addItem(getString(SettingsStringHelper.getCustomFontLabel(it)), it)
|
||||||
|
}
|
||||||
|
dialog.addOnSelectItemListener { value ->
|
||||||
|
Preferences.customFont = value
|
||||||
|
}.show()
|
||||||
|
|
||||||
|
/*
|
||||||
|
val intent = Intent(Intent.ACTION_GET_CONTENT)
|
||||||
|
intent.type = "* / *" TO FIX WITHOUT SPACE
|
||||||
|
intent.addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
|
||||||
|
try {
|
||||||
|
startActivityForResult(Intent.createChooser(intent, "Select a File to Upload"), Constants.CUSTOM_FONT_CHOOSER_REQUEST_CODE)
|
||||||
|
} catch (ex: android.content.ActivityNotFoundException) {
|
||||||
|
Toast.makeText(this, "Please install a File Manager.", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
action_show_dividers.setOnClickListener {
|
||||||
|
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_show_dividers_title)).setSelectedValue(Preferences.showDividers)
|
||||||
|
.addItem(getString(R.string.settings_visible), true)
|
||||||
|
.addItem(getString(R.string.settings_not_visible), false)
|
||||||
|
.addOnSelectItemListener { value ->
|
||||||
|
Preferences.showDividers = value
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,388 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.fragments
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.app.Activity
|
||||||
|
import android.app.AlarmManager
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.databinding.DataBindingUtil
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
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.gms.common.api.ApiException
|
||||||
|
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.components.BottomSheetMenu
|
||||||
|
import com.tommasoberlose.anotherwidget.components.CustomNotesDialog
|
||||||
|
import com.tommasoberlose.anotherwidget.components.GlanceProviderSortMenu
|
||||||
|
import com.tommasoberlose.anotherwidget.databinding.FragmentGlanceSettingsBinding
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver.Companion.FITNESS_OPTIONS
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.checkIfFitInstalled
|
||||||
|
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.scrollView
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
|
class GlanceTabFragment : Fragment() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance() = GlanceTabFragment()
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var viewModel: MainViewModel
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
|
||||||
|
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
||||||
|
val binding = DataBindingUtil.inflate<FragmentGlanceSettingsBinding>(inflater, R.layout.fragment_glance_settings, container, false)
|
||||||
|
|
||||||
|
subscribeUi(binding, viewModel)
|
||||||
|
|
||||||
|
binding.lifecycleOwner = this
|
||||||
|
binding.viewModel = viewModel
|
||||||
|
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
|
action_show_steps.isVisible = requireContext().checkIfFitInstalled()
|
||||||
|
|
||||||
|
setupListener()
|
||||||
|
updateNextAlarmWarningUi()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun subscribeUi(
|
||||||
|
binding: FragmentGlanceSettingsBinding,
|
||||||
|
viewModel: MainViewModel
|
||||||
|
) {
|
||||||
|
binding.isGlanceVisible = Preferences.showGlance
|
||||||
|
|
||||||
|
viewModel.showGlance.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
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() {
|
||||||
|
|
||||||
|
action_show_glance.setOnClickListener {
|
||||||
|
Preferences.showGlance = !Preferences.showGlance
|
||||||
|
}
|
||||||
|
|
||||||
|
show_glance_switch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
||||||
|
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() {
|
||||||
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
|
updateNextAlarmWarningUi()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
super.onStart()
|
||||||
|
activity?.registerReceiver(nextAlarmChangeBroadcastReceiver, IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
activity?.unregisterReceiver(nextAlarmChangeBroadcastReceiver)
|
||||||
|
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(
|
||||||
|
requestCode: Int,
|
||||||
|
resultCode: Int,
|
||||||
|
data: Intent?
|
||||||
|
) {
|
||||||
|
when (requestCode) {
|
||||||
|
1 -> {
|
||||||
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
|
checkFitnessPermission()
|
||||||
|
} else {
|
||||||
|
Preferences.showDailySteps = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2-> {
|
||||||
|
try {
|
||||||
|
val account: GoogleSignInAccount? = GoogleSignIn.getSignedInAccountFromIntent(data).getResult(ApiException::class.java)
|
||||||
|
if (!GoogleSignIn.hasPermissions(account, FITNESS_OPTIONS)) {
|
||||||
|
GoogleSignIn.requestPermissions(
|
||||||
|
requireActivity(),
|
||||||
|
1,
|
||||||
|
account,
|
||||||
|
FITNESS_OPTIONS)
|
||||||
|
} else {
|
||||||
|
checkFitnessPermission()
|
||||||
|
}
|
||||||
|
} catch (e: ApiException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
Preferences.showDailySteps = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun requireFitnessPermission() {
|
||||||
|
Dexter.withContext(requireContext())
|
||||||
|
.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) {
|
||||||
|
val scrollPosition = scrollView.scrollY
|
||||||
|
callback.invoke()
|
||||||
|
lifecycleScope.launch {
|
||||||
|
delay(200)
|
||||||
|
scrollView.smoothScrollTo(0, scrollPosition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
checkNotificationPermission()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,400 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.fragments
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.animation.ValueAnimator
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.util.DisplayMetrics
|
||||||
|
import android.util.Log
|
||||||
|
import android.util.TypedValue
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.RelativeLayout
|
||||||
|
import androidx.core.animation.addListener
|
||||||
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.navigation.Navigation
|
||||||
|
import com.google.android.material.badge.BadgeDrawable
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.BitmapHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.SupportDevActivity
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.adapters.ViewPagerAdapter
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
|
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.the_widget_sans.*
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.greenrobot.eventbus.Subscribe
|
||||||
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
|
|
||||||
|
class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun newInstance() = MainFragment()
|
||||||
|
private const val PREVIEW_BASE_HEIGHT = 120
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var viewModel: MainViewModel
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
enterTransition = MaterialSharedAxis.create(MaterialSharedAxis.X, true)
|
||||||
|
reenterTransition = MaterialSharedAxis.create(MaterialSharedAxis.X, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
||||||
|
return inflater.inflate(R.layout.fragment_app_main, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
subscribeUi(viewModel)
|
||||||
|
|
||||||
|
// Viewpager
|
||||||
|
pager.adapter = ViewPagerAdapter(requireActivity())
|
||||||
|
pager.offscreenPageLimit = 4
|
||||||
|
TabLayoutMediator(tabs, pager) { tab, position ->
|
||||||
|
tab.text = when (position) {
|
||||||
|
0 -> getString(R.string.settings_general_title)
|
||||||
|
1 -> getString(R.string.settings_calendar_title)
|
||||||
|
2 -> getString(R.string.settings_weather_title)
|
||||||
|
3 -> getString(R.string.settings_clock_title)
|
||||||
|
4 -> getString(R.string.settings_at_a_glance_title)
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
}.attach()
|
||||||
|
|
||||||
|
// Init clock
|
||||||
|
time.setTextColor(ColorHelper.getClockFontColor())
|
||||||
|
time.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(requireContext()))
|
||||||
|
time_am_pm.setTextColor(ColorHelper.getClockFontColor())
|
||||||
|
time_am_pm.setTextSize(TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2)
|
||||||
|
time_container.isVisible = Preferences.showClock
|
||||||
|
|
||||||
|
preview.layoutParams = preview.layoutParams.apply {
|
||||||
|
height = PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(requireContext()) else 0
|
||||||
|
}
|
||||||
|
subscribeUi(viewModel)
|
||||||
|
updateUI()
|
||||||
|
|
||||||
|
// Warnings
|
||||||
|
if (getString(R.string.xiaomi_manufacturer).equals(Build.MANUFACTURER, ignoreCase = true) && Preferences.showXiaomiWarning) {
|
||||||
|
MaterialBottomSheetDialog(requireContext(), getString(R.string.xiaomi_warning_title), getString(R.string.xiaomi_warning_message))
|
||||||
|
.setNegativeButton(getString(R.string.action_ignore)) {
|
||||||
|
Preferences.showXiaomiWarning = false
|
||||||
|
}
|
||||||
|
.setPositiveButton(getString(R.string.action_grant_permission)) {
|
||||||
|
Preferences.showXiaomiWarning = false
|
||||||
|
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||||
|
data = Uri.parse("package:${activity?.packageName}")
|
||||||
|
}
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var uiJob: Job? = null
|
||||||
|
|
||||||
|
private fun updateUI() {
|
||||||
|
uiJob?.cancel()
|
||||||
|
|
||||||
|
preview?.clearAnimation()
|
||||||
|
time_container?.clearAnimation()
|
||||||
|
|
||||||
|
if (Preferences.showPreview) {
|
||||||
|
preview?.setCardBackgroundColor(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
requireContext(),
|
||||||
|
if (ColorHelper.getFontColor()
|
||||||
|
.isColorDark()
|
||||||
|
) android.R.color.white else R.color.colorAccent
|
||||||
|
)
|
||||||
|
)
|
||||||
|
widget_shape_background?.setImageDrawable(
|
||||||
|
BitmapHelper.getTintedDrawable(
|
||||||
|
requireContext(),
|
||||||
|
R.drawable.card_background,
|
||||||
|
ColorHelper.getBackgroundColor()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
uiJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
val generatedView = MainWidget.generateWidgetView(requireContext())
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
generatedView.measure(0, 0)
|
||||||
|
preview?.measure(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
val bitmap = if (preview != null) {
|
||||||
|
BitmapHelper.getBitmapFromView(
|
||||||
|
generatedView,
|
||||||
|
if (preview.width > 0) preview.width else generatedView.measuredWidth,
|
||||||
|
generatedView.measuredHeight
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
// Clock
|
||||||
|
time?.setTextColor(ColorHelper.getClockFontColor())
|
||||||
|
time_am_pm?.setTextColor(ColorHelper.getClockFontColor())
|
||||||
|
time?.setTextSize(
|
||||||
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
|
Preferences.clockTextSize.toPixel(requireContext())
|
||||||
|
)
|
||||||
|
time_am_pm?.setTextSize(
|
||||||
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
|
Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2
|
||||||
|
)
|
||||||
|
time_am_pm?.isVisible = Preferences.showAMPMIndicator
|
||||||
|
|
||||||
|
// Clock bottom margin
|
||||||
|
clock_bottom_margin_none?.isVisible =
|
||||||
|
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value
|
||||||
|
clock_bottom_margin_small?.isVisible =
|
||||||
|
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value
|
||||||
|
clock_bottom_margin_medium?.isVisible =
|
||||||
|
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value
|
||||||
|
clock_bottom_margin_large?.isVisible =
|
||||||
|
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value
|
||||||
|
|
||||||
|
if ((Preferences.showClock && (time?.alpha ?: 1f < 1f)) || (!Preferences.showClock && (time?.alpha ?: 0f > 0f))) {
|
||||||
|
if (Preferences.showClock) {
|
||||||
|
time_container?.layoutParams = time_container.layoutParams.apply {
|
||||||
|
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
}
|
||||||
|
time_container?.measure(0, 0)
|
||||||
|
}
|
||||||
|
val initialHeight = time_container?.measuredHeight ?: 0
|
||||||
|
ValueAnimator.ofFloat(
|
||||||
|
if (Preferences.showClock) 0f else 1f,
|
||||||
|
if (Preferences.showClock) 1f else 0f
|
||||||
|
).apply {
|
||||||
|
duration = 500L
|
||||||
|
addUpdateListener {
|
||||||
|
val animatedValue = animatedValue as Float
|
||||||
|
time_container?.layoutParams =
|
||||||
|
time_container.layoutParams.apply {
|
||||||
|
height = (initialHeight * animatedValue).toInt()
|
||||||
|
}
|
||||||
|
time?.alpha = animatedValue
|
||||||
|
}
|
||||||
|
addListener(
|
||||||
|
onStart = {
|
||||||
|
if (Preferences.showClock) {
|
||||||
|
time_container?.isVisible = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onEnd = {
|
||||||
|
if (!Preferences.showClock) {
|
||||||
|
time_container?.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}.start()
|
||||||
|
|
||||||
|
if (preview != null) {
|
||||||
|
ValueAnimator.ofInt(
|
||||||
|
preview.height,
|
||||||
|
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||||
|
requireContext()
|
||||||
|
) else 0
|
||||||
|
).apply {
|
||||||
|
duration = 500L
|
||||||
|
addUpdateListener {
|
||||||
|
if (preview != null) {
|
||||||
|
val animatedValue = animatedValue as Int
|
||||||
|
val layoutParams = preview.layoutParams
|
||||||
|
layoutParams.height = animatedValue
|
||||||
|
preview.layoutParams = layoutParams
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
time_container?.layoutParams = time_container.layoutParams.apply {
|
||||||
|
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||||
|
}
|
||||||
|
time_container?.measure(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preview != null && preview.height == 0) {
|
||||||
|
ValueAnimator.ofInt(
|
||||||
|
preview.height,
|
||||||
|
PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
||||||
|
requireContext()
|
||||||
|
) else 0
|
||||||
|
).apply {
|
||||||
|
duration = 300L
|
||||||
|
addUpdateListener {
|
||||||
|
if (preview != null) {
|
||||||
|
val animatedValue = animatedValue as Int
|
||||||
|
val layoutParams = preview.layoutParams
|
||||||
|
layoutParams.height = animatedValue
|
||||||
|
preview?.layoutParams = layoutParams
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
widget_loader?.animate()?.scaleX(0f)?.scaleY(0f)?.alpha(0f)?.setDuration(200L)?.start()
|
||||||
|
bitmap_container?.apply {
|
||||||
|
setImageBitmap(bitmap)
|
||||||
|
scaleX = 0.9f
|
||||||
|
scaleY = 0.9f
|
||||||
|
}
|
||||||
|
widget?.animate()?.alpha(1f)?.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (preview != null) {
|
||||||
|
ValueAnimator.ofInt(
|
||||||
|
preview.height,
|
||||||
|
0
|
||||||
|
).apply {
|
||||||
|
duration = 300L
|
||||||
|
addUpdateListener {
|
||||||
|
if (preview != null) {
|
||||||
|
val animatedValue = animatedValue as Int
|
||||||
|
val layoutParams = preview.layoutParams
|
||||||
|
layoutParams.height = animatedValue
|
||||||
|
preview.layoutParams = layoutParams
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showErrorBadge()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun subscribeUi(viewModel: MainViewModel) {
|
||||||
|
viewModel.showWallpaper.observe(viewLifecycleOwner, Observer {
|
||||||
|
activity?.let { act ->
|
||||||
|
val wallpaper = act.getCurrentWallpaper()
|
||||||
|
widget_bg.setImageDrawable(if (it) wallpaper else null)
|
||||||
|
if (wallpaper != null) {
|
||||||
|
widget_bg.layoutParams =
|
||||||
|
(widget_bg.layoutParams as ViewGroup.MarginLayoutParams).apply {
|
||||||
|
|
||||||
|
val metrics = DisplayMetrics()
|
||||||
|
act.windowManager.defaultDisplay.getMetrics(metrics)
|
||||||
|
|
||||||
|
val dimensions: Pair<Int, Int> = if (wallpaper.intrinsicWidth >= wallpaper.intrinsicHeight) {
|
||||||
|
metrics.heightPixels to (wallpaper.intrinsicWidth) * metrics.heightPixels / (wallpaper.intrinsicHeight)
|
||||||
|
} else {
|
||||||
|
metrics.widthPixels to (wallpaper.intrinsicHeight) * metrics.widthPixels / (wallpaper.intrinsicWidth)
|
||||||
|
}
|
||||||
|
|
||||||
|
setMargins(
|
||||||
|
if (dimensions.first >= dimensions.second) (-80).toPixel(requireContext()) else 0,
|
||||||
|
(-80).toPixel(requireContext()), 0, 0
|
||||||
|
)
|
||||||
|
|
||||||
|
width = dimensions.first
|
||||||
|
height = dimensions.second
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
logo.setOnClickListener {
|
||||||
|
// startActivity(Intent(this, SupportDevActivity::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
action_settings.setOnClickListener {
|
||||||
|
Navigation.findNavController(it).navigate(R.id.action_appMainFragment_to_appSettingsFragment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showErrorBadge() {
|
||||||
|
// Calendar error indicator
|
||||||
|
tabs?.getTabAt(1)?.orCreateBadge?.apply {
|
||||||
|
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
||||||
|
badgeGravity = BadgeDrawable.TOP_END
|
||||||
|
}?.isVisible = Preferences.showEvents && activity?.checkGrantedPermission(Manifest.permission.READ_CALENDAR) != true
|
||||||
|
|
||||||
|
// Weather error indicator
|
||||||
|
tabs?.getTabAt(2)?.orCreateBadge?.apply {
|
||||||
|
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
||||||
|
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))
|
||||||
|
|
||||||
|
|
||||||
|
// Music error indicator
|
||||||
|
tabs?.getTabAt(4)?.orCreateBadge?.apply {
|
||||||
|
backgroundColor = ContextCompat.getColor(requireContext(), R.color.errorColorText)
|
||||||
|
badgeGravity = BadgeDrawable.TOP_END
|
||||||
|
}?.isVisible = Preferences.showMusic && !NotificationManagerCompat.getEnabledListenerPackages(requireContext()).contains(requireContext().packageName)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
Preferences.preferences.registerOnSharedPreferenceChangeListener(this)
|
||||||
|
EventBus.getDefault().register(this)
|
||||||
|
showErrorBadge()
|
||||||
|
updateUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
Preferences.preferences.unregisterOnSharedPreferenceChangeListener(this)
|
||||||
|
EventBus.getDefault().unregister(this)
|
||||||
|
super.onPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
var delayJob: Job? = null
|
||||||
|
|
||||||
|
override fun onSharedPreferenceChanged(preferences: SharedPreferences, p1: String) {
|
||||||
|
delayJob?.cancel()
|
||||||
|
delayJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
delay(200)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
updateUI()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MainWidget.updateWidget(requireContext())
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateUiMessageEvent
|
||||||
|
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
fun onMessageEvent(ignore: UpdateUiMessageEvent?) {
|
||||||
|
delayJob?.cancel()
|
||||||
|
delayJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
delay(200)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
updateUI()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,9 +2,9 @@ package com.tommasoberlose.anotherwidget.ui.fragments
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
@ -14,6 +14,8 @@ 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.navigation.Navigation
|
||||||
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import com.karumi.dexter.Dexter
|
import com.karumi.dexter.Dexter
|
||||||
import com.karumi.dexter.MultiplePermissionsReport
|
import com.karumi.dexter.MultiplePermissionsReport
|
||||||
import com.karumi.dexter.PermissionToken
|
import com.karumi.dexter.PermissionToken
|
||||||
@ -22,30 +24,34 @@ import com.karumi.dexter.listener.multi.MultiplePermissionsListener
|
|||||||
import com.tommasoberlose.anotherwidget.BuildConfig
|
import com.tommasoberlose.anotherwidget.BuildConfig
|
||||||
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.databinding.FragmentAdvancedSettingsBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentSettingsBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
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
|
||||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.WeatherHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.ui.activities.IntegrationsActivity
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
import com.tommasoberlose.anotherwidget.utils.openURI
|
import com.tommasoberlose.anotherwidget.utils.openURI
|
||||||
import kotlinx.android.synthetic.main.fragment_advanced_settings.*
|
import kotlinx.android.synthetic.main.fragment_settings.*
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
class AdvancedSettingsFragment : Fragment() {
|
class SettingsFragment : Fragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance() = AdvancedSettingsFragment()
|
fun newInstance() = SettingsFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var viewModel: MainViewModel
|
private lateinit var viewModel: MainViewModel
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
enterTransition = MaterialSharedAxis.create(MaterialSharedAxis.X, true)
|
||||||
|
returnTransition = MaterialSharedAxis.create(MaterialSharedAxis.X, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
@ -54,9 +60,7 @@ class AdvancedSettingsFragment : Fragment() {
|
|||||||
): View {
|
): View {
|
||||||
|
|
||||||
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
viewModel = ViewModelProvider(activity as MainActivity).get(MainViewModel::class.java)
|
||||||
val binding = DataBindingUtil.inflate<FragmentAdvancedSettingsBinding>(inflater, R.layout.fragment_advanced_settings, container, false)
|
val binding = DataBindingUtil.inflate<FragmentSettingsBinding>(inflater, R.layout.fragment_settings, container, false)
|
||||||
|
|
||||||
subscribeUi(viewModel)
|
|
||||||
|
|
||||||
binding.lifecycleOwner = this
|
binding.lifecycleOwner = this
|
||||||
binding.viewModel = viewModel
|
binding.viewModel = viewModel
|
||||||
@ -67,9 +71,15 @@ class AdvancedSettingsFragment : Fragment() {
|
|||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
super.onActivityCreated(savedInstanceState)
|
super.onActivityCreated(savedInstanceState)
|
||||||
|
|
||||||
|
action_back.setOnClickListener {
|
||||||
|
Navigation.findNavController(it).popBackStack()
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeUi(viewModel)
|
||||||
|
|
||||||
setupListener()
|
setupListener()
|
||||||
|
|
||||||
app_version.text = "v%s".format(BuildConfig.VERSION_NAME)
|
app_version.text = "v%s (%s)".format(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun subscribeUi(
|
private fun subscribeUi(
|
||||||
@ -77,21 +87,84 @@ class AdvancedSettingsFragment : Fragment() {
|
|||||||
) {
|
) {
|
||||||
viewModel.darkThemePreference.observe(viewLifecycleOwner, Observer {
|
viewModel.darkThemePreference.observe(viewLifecycleOwner, Observer {
|
||||||
AppCompatDelegate.setDefaultNightMode(it)
|
AppCompatDelegate.setDefaultNightMode(it)
|
||||||
theme.text = when (it) {
|
maintainScrollPosition {
|
||||||
|
theme?.text = when (it) {
|
||||||
AppCompatDelegate.MODE_NIGHT_NO -> getString(R.string.settings_subtitle_dark_theme_light)
|
AppCompatDelegate.MODE_NIGHT_NO -> getString(R.string.settings_subtitle_dark_theme_light)
|
||||||
AppCompatDelegate.MODE_NIGHT_YES -> getString(R.string.settings_subtitle_dark_theme_dark)
|
AppCompatDelegate.MODE_NIGHT_YES -> getString(R.string.settings_subtitle_dark_theme_dark)
|
||||||
AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY -> getString(R.string.settings_subtitle_dark_theme_by_battery_saver)
|
AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY -> getString(R.string.settings_subtitle_dark_theme_by_battery_saver)
|
||||||
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM -> getString(R.string.settings_subtitle_dark_theme_follow_system)
|
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM -> getString(R.string.settings_subtitle_dark_theme_follow_system)
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.installedIntegrations.observe(viewLifecycleOwner, Observer {
|
||||||
|
integrations_count_label?.text = getString(R.string.label_count_installed_integrations).format(it)
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.showPreview.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
show_widget_preview_label?.text =
|
||||||
|
if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.showWallpaper.observe(viewLifecycleOwner, Observer {
|
viewModel.showWallpaper.observe(viewLifecycleOwner, Observer {
|
||||||
show_wallpaper_label.text = if (it && activity?.checkGrantedPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == true) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
maintainScrollPosition {
|
||||||
|
show_wallpaper_label?.text =
|
||||||
|
if (it && activity?.checkGrantedPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == true) getString(
|
||||||
|
R.string.settings_visible
|
||||||
|
) else getString(R.string.settings_not_visible)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
|
|
||||||
|
action_show_widget_preview.setOnClickListener {
|
||||||
|
maintainScrollPosition {
|
||||||
|
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.action_show_widget_preview))
|
||||||
|
.setSelectedValue(Preferences.showPreview)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_visible),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_not_visible),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
.addOnSelectItemListener { value ->
|
||||||
|
Preferences.showPreview = value
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
action_show_wallpaper.setOnClickListener {
|
||||||
|
maintainScrollPosition {
|
||||||
|
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_title_show_wallpaper))
|
||||||
|
.setSelectedValue(Preferences.showWallpaper && activity?.checkGrantedPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == true)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_visible),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_not_visible),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
.addOnSelectItemListener { value ->
|
||||||
|
if (value) {
|
||||||
|
requirePermission()
|
||||||
|
} else {
|
||||||
|
Preferences.showWallpaper = value
|
||||||
|
}
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
action_integrations.setOnClickListener {
|
||||||
|
startActivity(Intent(requireContext(), IntegrationsActivity::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
action_change_theme.setOnClickListener {
|
action_change_theme.setOnClickListener {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_theme_title))
|
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_theme_title))
|
||||||
@ -114,28 +187,6 @@ class AdvancedSettingsFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
action_show_wallpaper.setOnClickListener {
|
|
||||||
maintainScrollPosition {
|
|
||||||
BottomSheetMenu<Boolean>(requireContext(), header = getString(R.string.settings_title_show_wallpaper))
|
|
||||||
.setSelectedValue(Preferences.showWallpaper)
|
|
||||||
.addItem(
|
|
||||||
getString(R.string.settings_visible),
|
|
||||||
true
|
|
||||||
)
|
|
||||||
.addItem(
|
|
||||||
getString(R.string.settings_not_visible),
|
|
||||||
false
|
|
||||||
)
|
|
||||||
.addOnSelectItemListener { value ->
|
|
||||||
if (value) {
|
|
||||||
requirePermission()
|
|
||||||
} else {
|
|
||||||
Preferences.showWallpaper = value
|
|
||||||
}
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
action_translate.setOnClickListener {
|
action_translate.setOnClickListener {
|
||||||
activity?.openURI("https://github.com/tommasoberlose/another-widget/blob/master/app/src/main/res/values/strings.xml")
|
activity?.openURI("https://github.com/tommasoberlose/another-widget/blob/master/app/src/main/res/values/strings.xml")
|
||||||
}
|
}
|
||||||
@ -153,8 +204,9 @@ class AdvancedSettingsFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
action_refresh_widget.setOnClickListener {
|
action_refresh_widget.setOnClickListener {
|
||||||
MainWidget.updateWidget(requireContext())
|
WeatherHelper.updateWeather(requireContext())
|
||||||
CalendarHelper.updateEventList(requireContext())
|
CalendarHelper.updateEventList(requireContext())
|
||||||
|
MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,6 +226,7 @@ class AdvancedSettingsFragment : Fragment() {
|
|||||||
).withListener(object: MultiplePermissionsListener {
|
).withListener(object: MultiplePermissionsListener {
|
||||||
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
||||||
report?.let {
|
report?.let {
|
||||||
|
Preferences.showWallpaper = false
|
||||||
Preferences.showWallpaper = report.areAllPermissionsGranted()
|
Preferences.showWallpaper = report.areAllPermissionsGranted()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,11 +3,13 @@ package com.tommasoberlose.anotherwidget.ui.fragments
|
|||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
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 androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.databinding.DataBindingUtil
|
import androidx.databinding.DataBindingUtil
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
@ -40,10 +42,10 @@ import kotlinx.android.synthetic.main.fragment_weather_settings.scrollView
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class WeatherSettingsFragment : Fragment() {
|
class WeatherTabFragment : Fragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance() = WeatherSettingsFragment()
|
fun newInstance() = WeatherTabFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var viewModel: MainViewModel
|
private lateinit var viewModel: MainViewModel
|
||||||
@ -78,14 +80,18 @@ class WeatherSettingsFragment : Fragment() {
|
|||||||
binding: FragmentWeatherSettingsBinding,
|
binding: FragmentWeatherSettingsBinding,
|
||||||
viewModel: MainViewModel
|
viewModel: MainViewModel
|
||||||
) {
|
) {
|
||||||
|
binding.isWeatherVisible = Preferences.showWeather
|
||||||
|
|
||||||
viewModel.showWeatherWarning.observe(viewLifecycleOwner, Observer {
|
viewModel.showWeatherWarning.observe(viewLifecycleOwner, Observer {
|
||||||
weather_warning.isVisible = it
|
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 =
|
||||||
if (it) getString(R.string.show_weather_visible) else getString(R.string.show_weather_not_visible)
|
if (it) getString(R.string.show_weather_visible) else getString(R.string.show_weather_not_visible)
|
||||||
|
checkWeatherProviderConfig()
|
||||||
binding.isWeatherVisible = it
|
binding.isWeatherVisible = it
|
||||||
}
|
}
|
||||||
checkLocationPermission()
|
checkLocationPermission()
|
||||||
@ -93,18 +99,14 @@ class WeatherSettingsFragment : Fragment() {
|
|||||||
|
|
||||||
viewModel.weatherProviderApi.observe(viewLifecycleOwner, Observer {
|
viewModel.weatherProviderApi.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
label_weather_provider_api_key.text =
|
checkWeatherProviderConfig()
|
||||||
if (it == "") getString(R.string.settings_weather_provider_api_key_subtitle_not_set) else getString(
|
|
||||||
R.string.settings_weather_provider_api_key_subtitle_all_set
|
|
||||||
)
|
|
||||||
api_key_alert_icon.isVisible = it == ""
|
|
||||||
}
|
}
|
||||||
checkLocationPermission()
|
checkLocationPermission()
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.customLocationAdd.observe(viewLifecycleOwner, Observer {
|
viewModel.customLocationAdd.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
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
|
||||||
}
|
}
|
||||||
checkLocationPermission()
|
checkLocationPermission()
|
||||||
@ -112,36 +114,62 @@ class WeatherSettingsFragment : Fragment() {
|
|||||||
|
|
||||||
viewModel.weatherTempUnit.observe(viewLifecycleOwner, Observer {
|
viewModel.weatherTempUnit.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
temp_unit.text =
|
temp_unit?.text =
|
||||||
if (it == "F") getString(R.string.fahrenheit) else getString(R.string.celsius)
|
if (it == "F") getString(R.string.fahrenheit) else getString(R.string.celsius)
|
||||||
}
|
}
|
||||||
|
checkLocationPermission()
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.weatherRefreshPeriod.observe(viewLifecycleOwner, Observer {
|
viewModel.weatherRefreshPeriod.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
label_weather_refresh_period.text = getString(SettingsStringHelper.getRefreshPeriodString(it))
|
label_weather_refresh_period?.text = getString(SettingsStringHelper.getRefreshPeriodString(it))
|
||||||
|
}
|
||||||
|
checkLocationPermission()
|
||||||
|
})
|
||||||
|
|
||||||
|
viewModel.weatherIconPack.observe(viewLifecycleOwner, Observer {
|
||||||
|
maintainScrollPosition {
|
||||||
|
label_weather_icon_pack?.text = when (it) {
|
||||||
|
Constants.WeatherIconPack.MINIMAL.value -> getString(R.string.settings_weather_icon_pack_minimal)
|
||||||
|
else -> getString(R.string.settings_weather_icon_pack_default)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
checkLocationPermission()
|
checkLocationPermission()
|
||||||
})
|
})
|
||||||
|
|
||||||
viewModel.weatherAppName.observe(viewLifecycleOwner, Observer {
|
viewModel.weatherAppName.observe(viewLifecycleOwner, Observer {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
weather_app_label.text =
|
weather_app_label?.text =
|
||||||
if (it != "") it else getString(R.string.default_weather_app)
|
if (it != "") it else getString(R.string.default_weather_app)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkLocationPermission() {
|
private fun checkLocationPermission() {
|
||||||
if (activity?.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) == true) {
|
// Background permission
|
||||||
location_permission_alert_icon.isVisible = false
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && activity?.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) == true && activity?.checkGrantedPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) != true) {
|
||||||
WeatherReceiver.setUpdates(requireContext())
|
|
||||||
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
|
|
||||||
location_permission_alert_icon.isVisible = true
|
|
||||||
location_permission_alert_icon.setOnClickListener {
|
|
||||||
requirePermission()
|
requirePermission()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
WeatherReceiver.setUpdates(requireContext())
|
||||||
|
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
|
||||||
|
location_permission_alert?.isVisible = true
|
||||||
|
location_permission_alert?.setOnClickListener {
|
||||||
|
requirePermission()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
location_permission_alert?.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkWeatherProviderConfig() {
|
||||||
|
label_weather_provider_api_key?.text =
|
||||||
|
if (Preferences.weatherProviderApi == "") getString(R.string.settings_weather_provider_api_key_subtitle_not_set) else getString(
|
||||||
|
R.string.settings_weather_provider_api_key_subtitle_all_set
|
||||||
|
)
|
||||||
|
label_weather_provider_api_key?.setTextColor(ContextCompat.getColor(requireContext(), if (Preferences.weatherProviderApi == "" && Preferences.showWeather) R.color.errorColorText else R.color.colorSecondaryText))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
@ -153,6 +181,10 @@ class WeatherSettingsFragment : Fragment() {
|
|||||||
Preferences.showWeather = !Preferences.showWeather
|
Preferences.showWeather = !Preferences.showWeather
|
||||||
}
|
}
|
||||||
|
|
||||||
|
show_weather_switch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
||||||
|
Preferences.showWeather = enabled
|
||||||
|
}
|
||||||
|
|
||||||
action_weather_provider_api_key.setOnClickListener {
|
action_weather_provider_api_key.setOnClickListener {
|
||||||
if (Preferences.showWeather) {
|
if (Preferences.showWeather) {
|
||||||
startActivityForResult(
|
startActivityForResult(
|
||||||
@ -196,6 +228,17 @@ class WeatherSettingsFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
action_weather_icon_pack.setOnClickListener {
|
||||||
|
if (Preferences.showWeather) {
|
||||||
|
BottomSheetMenu<Int>(requireContext(), header = getString(R.string.settings_weather_icon_pack_title)).setSelectedValue(Preferences.weatherIconPack)
|
||||||
|
.addItem(getString(R.string.settings_weather_icon_pack_default), Constants.WeatherIconPack.DEFAULT.value)
|
||||||
|
.addItem(getString(R.string.settings_weather_icon_pack_minimal), Constants.WeatherIconPack.MINIMAL.value)
|
||||||
|
.addOnSelectItemListener { value ->
|
||||||
|
Preferences.weatherIconPack = value
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
action_weather_app.setOnClickListener {
|
action_weather_app.setOnClickListener {
|
||||||
if (Preferences.showWeather) {
|
if (Preferences.showWeather) {
|
||||||
startActivityForResult(
|
startActivityForResult(
|
||||||
@ -231,7 +274,7 @@ class WeatherSettingsFragment : Fragment() {
|
|||||||
private fun requirePermission() {
|
private fun requirePermission() {
|
||||||
Dexter.withContext(requireContext())
|
Dexter.withContext(requireContext())
|
||||||
.withPermissions(
|
.withPermissions(
|
||||||
Manifest.permission.ACCESS_FINE_LOCATION
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
|
||||||
).withListener(object: MultiplePermissionsListener {
|
).withListener(object: MultiplePermissionsListener {
|
||||||
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
||||||
report?.let {
|
report?.let {
|
@ -3,8 +3,10 @@ package com.tommasoberlose.anotherwidget.ui.viewmodels
|
|||||||
import android.app.Application
|
import android.app.Application
|
||||||
import androidx.lifecycle.AndroidViewModel
|
import androidx.lifecycle.AndroidViewModel
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import com.chibatching.kotpref.livedata.asLiveData
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
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)
|
||||||
}
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.ui.viewmodels
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
|
||||||
|
class IntegrationsViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
}
|
@ -8,11 +8,17 @@ class MainViewModel : ViewModel() {
|
|||||||
|
|
||||||
// General Settings
|
// General Settings
|
||||||
val textGlobalColor = Preferences.asLiveData(Preferences::textGlobalColor)
|
val textGlobalColor = Preferences.asLiveData(Preferences::textGlobalColor)
|
||||||
|
val textGlobalAlpha = Preferences.asLiveData(Preferences::textGlobalAlpha)
|
||||||
|
val textSecondaryColor = Preferences.asLiveData(Preferences::textSecondaryColor)
|
||||||
|
val textSecondaryAlpha = Preferences.asLiveData(Preferences::textSecondaryAlpha)
|
||||||
|
val backgroundCardColor = Preferences.asLiveData(Preferences::backgroundCardColor)
|
||||||
|
val backgroundCardAlpha = Preferences.asLiveData(Preferences::backgroundCardAlpha)
|
||||||
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 customFont = Preferences.asLiveData(Preferences::customFont)
|
val customFont = Preferences.asLiveData(Preferences::customFont)
|
||||||
val secondRowInformation = Preferences.asLiveData(Preferences::secondRowInformation)
|
val secondRowInformation = Preferences.asLiveData(Preferences::secondRowInformation)
|
||||||
|
val showDividers = Preferences.asLiveData(Preferences::showDividers)
|
||||||
|
|
||||||
// Calendar Settings
|
// Calendar Settings
|
||||||
val showEvents = Preferences.asLiveData(Preferences::showEvents)
|
val showEvents = Preferences.asLiveData(Preferences::showEvents)
|
||||||
@ -21,18 +27,20 @@ class MainViewModel : ViewModel() {
|
|||||||
val showDiffTime = Preferences.asLiveData(Preferences::showDiffTime)
|
val showDiffTime = Preferences.asLiveData(Preferences::showDiffTime)
|
||||||
val showDeclinedEvents = Preferences.asLiveData(Preferences::showDeclinedEvents)
|
val showDeclinedEvents = Preferences.asLiveData(Preferences::showDeclinedEvents)
|
||||||
val showNextEvent = Preferences.asLiveData(Preferences::showNextEvent)
|
val showNextEvent = Preferences.asLiveData(Preferences::showNextEvent)
|
||||||
|
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 eventAppName = Preferences.asLiveData(Preferences::eventAppName)
|
|
||||||
|
|
||||||
// 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 clockTextAlpha = Preferences.asLiveData(Preferences::clockTextAlpha)
|
||||||
|
val showAMPMIndicator = Preferences.asLiveData(Preferences::showAMPMIndicator)
|
||||||
|
|
||||||
val clockAppName = Preferences.asLiveData(Preferences::clockAppName)
|
val clockAppName = Preferences.asLiveData(Preferences::clockAppName)
|
||||||
val showNextAlarm = Preferences.asLiveData(Preferences::showNextAlarm)
|
|
||||||
val dateFormat = Preferences.asLiveData(Preferences::dateFormat)
|
val dateFormat = Preferences.asLiveData(Preferences::dateFormat)
|
||||||
|
val clockBottomMargin = Preferences.asLiveData(Preferences::clockBottomMargin)
|
||||||
|
|
||||||
val showBigClockWarning = Preferences.asLiveData(Preferences::showBigClockWarning)
|
val showBigClockWarning = Preferences.asLiveData(Preferences::showBigClockWarning)
|
||||||
|
|
||||||
@ -47,8 +55,19 @@ class MainViewModel : ViewModel() {
|
|||||||
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)
|
||||||
|
|
||||||
|
// Glance
|
||||||
|
val showGlance = Preferences.asLiveData(Preferences::showGlance)
|
||||||
|
val showMusic = Preferences.asLiveData(Preferences::showMusic)
|
||||||
|
val showNextAlarm = Preferences.asLiveData(Preferences::showNextAlarm)
|
||||||
|
val showBatteryCharging = Preferences.asLiveData(Preferences::showBatteryCharging)
|
||||||
|
val showDailySteps = Preferences.asLiveData(Preferences::showDailySteps)
|
||||||
|
val customInfo = Preferences.asLiveData(Preferences::customNotes)
|
||||||
|
|
||||||
// Advanced Settings
|
// Advanced Settings
|
||||||
val darkThemePreference = Preferences.asLiveData(Preferences::darkThemePreference)
|
val darkThemePreference = Preferences.asLiveData(Preferences::darkThemePreference)
|
||||||
val showWallpaper = Preferences.asLiveData(Preferences::showWallpaper)
|
val showWallpaper = Preferences.asLiveData(Preferences::showWallpaper)
|
||||||
|
val showPreview = Preferences.asLiveData(Preferences::showPreview)
|
||||||
|
val installedIntegrations = Preferences.asLiveData(Preferences::installedIntegrations)
|
||||||
}
|
}
|
||||||
|
@ -26,18 +26,17 @@ 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.receivers.NewCalendarEventReceiver
|
import com.tommasoberlose.anotherwidget.receivers.*
|
||||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
|
||||||
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
|
|
||||||
import com.tommasoberlose.anotherwidget.receivers.WidgetClickListenerReceiver
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
import com.tommasoberlose.anotherwidget.utils.convertSpToPixels
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.getCapWordString
|
import com.tommasoberlose.anotherwidget.utils.getCapWordString
|
||||||
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
|
||||||
|
import kotlin.math.min
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
||||||
class MainWidget : AppWidgetProvider() {
|
class MainWidget : AppWidgetProvider() {
|
||||||
@ -56,6 +55,7 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
override fun onEnabled(context: Context) {
|
override fun onEnabled(context: Context) {
|
||||||
CalendarHelper.updateEventList(context)
|
CalendarHelper.updateEventList(context)
|
||||||
WeatherReceiver.setUpdates(context)
|
WeatherReceiver.setUpdates(context)
|
||||||
|
MediaPlayerHelper.updatePlayingMediaInfo(context)
|
||||||
|
|
||||||
if (Preferences.showEvents) {
|
if (Preferences.showEvents) {
|
||||||
CalendarHelper.setEventUpdatesAndroidN(context)
|
CalendarHelper.setEventUpdatesAndroidN(context)
|
||||||
@ -65,63 +65,100 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDisabled(context: Context) {
|
override fun onDisabled(context: Context) {
|
||||||
|
if (getWidgetCount(context) == 0) {
|
||||||
UpdatesReceiver.removeUpdates(context)
|
UpdatesReceiver.removeUpdates(context)
|
||||||
WeatherReceiver.removeUpdates(context)
|
WeatherReceiver.removeUpdates(context)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun updateWidget(context: Context) {
|
fun updateWidget(context: Context) {
|
||||||
|
context.sendBroadcast(IntentHelper.getWidgetUpdateIntent(context))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getWidgetCount(context: Context): Int {
|
||||||
val widgetManager = AppWidgetManager.getInstance(context)
|
val widgetManager = AppWidgetManager.getInstance(context)
|
||||||
val widgetComponent = ComponentName(context, MainWidget::class.java)
|
val widgetComponent = ComponentName(context, MainWidget::class.java)
|
||||||
val widgetIds = widgetManager.getAppWidgetIds(widgetComponent)
|
return widgetManager.getAppWidgetIds(widgetComponent).size
|
||||||
val update = Intent(context, MainWidget::class.java)
|
|
||||||
update.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, widgetIds)
|
|
||||||
update.action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
|
|
||||||
context.sendBroadcast(update)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager,
|
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager,
|
||||||
appWidgetId: Int) {
|
appWidgetId: Int) {
|
||||||
val displayMetrics = Resources.getSystem().displayMetrics
|
val displayMetrics = Resources.getSystem().displayMetrics
|
||||||
var height = 110.toPixel(context)
|
|
||||||
val width = displayMetrics.widthPixels
|
val width = displayMetrics.widthPixels
|
||||||
if (Preferences.showClock) {
|
val height = displayMetrics.heightPixels
|
||||||
height += Preferences.clockTextSize.convertSpToPixels(context).toInt() + 16.toPixel(context)
|
|
||||||
}
|
|
||||||
if (Preferences.textMainSize > 30 && Preferences.textSecondSize > 22) {
|
|
||||||
height += 24.toPixel(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
generateWidgetView(context, appWidgetId, appWidgetManager, width - 16.toPixel(context))
|
val dimensions = WidgetHelper.WidgetSizeProvider(context, appWidgetManager).getWidgetsSize(appWidgetId)
|
||||||
|
generateWidgetView(context, appWidgetId, appWidgetManager, min(dimensions.first - 8.toPixel(context), min(width, height) - 16.toPixel(context)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int) {
|
private fun generateWidgetView(context: Context, appWidgetId: Int, appWidgetManager: AppWidgetManager, w: Int) {
|
||||||
var views = RemoteViews(context.packageName, R.layout.the_widget_sans)
|
var views = RemoteViews(context.packageName, R.layout.the_widget_sans)
|
||||||
|
|
||||||
val generatedView = generateWidgetView(context)
|
try {
|
||||||
views.setImageViewBitmap(R.id.bitmap_container, BitmapHelper.getBitmapFromView(generatedView, width = w - 32.toPixel(context)))
|
// Background
|
||||||
|
views.setInt(
|
||||||
|
R.id.widget_shape_background,
|
||||||
|
"setColorFilter",
|
||||||
|
ColorHelper.getBackgroundColorRgb()
|
||||||
|
)
|
||||||
|
views.setInt(
|
||||||
|
R.id.widget_shape_background,
|
||||||
|
"setImageAlpha",
|
||||||
|
ColorHelper.getBackgroundAlpha()
|
||||||
|
)
|
||||||
|
val refreshIntent = PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
appWidgetId,
|
||||||
|
IntentHelper.getWidgetUpdateIntent(context),
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
views.setOnClickPendingIntent(R.id.widget_shape_background, refreshIntent)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
CrashlyticsReceiver.sendCrash(context, ex)
|
||||||
|
}
|
||||||
|
|
||||||
// Clock
|
// Clock
|
||||||
views = updateClockView(context, views, appWidgetId)
|
views = updateClockView(context, views, appWidgetId)
|
||||||
|
|
||||||
// Setup listener
|
// Setup listener
|
||||||
|
try {
|
||||||
|
val generatedView = generateWidgetView(context)
|
||||||
|
views.setImageViewBitmap(
|
||||||
|
R.id.bitmap_container,
|
||||||
|
BitmapHelper.getBitmapFromView(generatedView, width = w)
|
||||||
|
)
|
||||||
views = updateCalendarView(context, generatedView, views, appWidgetId)
|
views = updateCalendarView(context, generatedView, views, appWidgetId)
|
||||||
views = updateWeatherView(context, generatedView, views, appWidgetId)
|
views = updateWeatherView(context, generatedView, views, appWidgetId)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
CrashlyticsReceiver.sendCrash(context, ex)
|
||||||
|
}
|
||||||
|
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateCalendarView(context: Context, v: View, views: RemoteViews, widgetID: Int): RemoteViews {
|
private fun updateCalendarView(context: Context, v: View, views: RemoteViews, widgetID: Int): RemoteViews {
|
||||||
val eventRepository = EventRepository(context)
|
val eventRepository = EventRepository(context)
|
||||||
|
try {
|
||||||
views.setImageViewBitmap(R.id.empty_date_rect, BitmapHelper.getBitmapFromView(v.empty_date, draw = false))
|
views.setImageViewBitmap(
|
||||||
|
R.id.empty_date_rect,
|
||||||
|
BitmapHelper.getBitmapFromView(v.empty_date, draw = false)
|
||||||
|
)
|
||||||
|
|
||||||
views.setViewVisibility(R.id.empty_layout_rect, View.VISIBLE)
|
views.setViewVisibility(R.id.empty_layout_rect, View.VISIBLE)
|
||||||
views.setViewVisibility(R.id.calendar_layout_rect, View.GONE)
|
views.setViewVisibility(R.id.calendar_layout_rect, View.GONE)
|
||||||
views.setViewVisibility(R.id.second_row_rect, View.GONE)
|
views.setViewVisibility(R.id.second_row_rect, View.GONE)
|
||||||
|
views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE)
|
||||||
|
|
||||||
val calPIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getCalendarIntent(context), 0)
|
val calPIntent = PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
widgetID,
|
||||||
|
IntentHelper.getCalendarIntent(context),
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
views.setOnClickPendingIntent(R.id.empty_date_rect, calPIntent)
|
views.setOnClickPendingIntent(R.id.empty_date_rect, calPIntent)
|
||||||
|
|
||||||
val nextEvent = eventRepository.getNextEvent()
|
val nextEvent = eventRepository.getNextEvent()
|
||||||
@ -129,64 +166,196 @@ 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) {
|
||||||
if (Preferences.showNextEvent && eventRepository.getEventsCount() > 1) {
|
if (Preferences.showNextEvent && eventRepository.getEventsCount() > 1) {
|
||||||
views.setImageViewBitmap(R.id.action_next_rect, BitmapHelper.getBitmapFromView(v.action_next, draw = false))
|
views.setImageViewBitmap(
|
||||||
|
R.id.action_next_rect,
|
||||||
|
BitmapHelper.getBitmapFromView(v.action_next, draw = false)
|
||||||
|
)
|
||||||
views.setViewVisibility(R.id.action_next_rect, View.VISIBLE)
|
views.setViewVisibility(R.id.action_next_rect, View.VISIBLE)
|
||||||
views.setOnClickPendingIntent(R.id.action_next_rect, PendingIntent.getBroadcast(context, widgetID, Intent(context, NewCalendarEventReceiver::class.java).apply { action = Actions.ACTION_GO_TO_NEXT_EVENT }, 0))
|
views.setOnClickPendingIntent(
|
||||||
|
R.id.action_next_rect,
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
widgetID,
|
||||||
|
Intent(
|
||||||
|
context,
|
||||||
|
NewCalendarEventReceiver::class.java
|
||||||
|
).apply { action = Actions.ACTION_GO_TO_NEXT_EVENT },
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
views.setImageViewBitmap(R.id.action_previous_rect, BitmapHelper.getBitmapFromView(v.action_previous, draw = false))
|
views.setImageViewBitmap(
|
||||||
|
R.id.action_previous_rect,
|
||||||
|
BitmapHelper.getBitmapFromView(v.action_previous, draw = false)
|
||||||
|
)
|
||||||
views.setViewVisibility(R.id.action_previous_rect, View.VISIBLE)
|
views.setViewVisibility(R.id.action_previous_rect, View.VISIBLE)
|
||||||
views.setOnClickPendingIntent(R.id.action_previous_rect, PendingIntent.getBroadcast(context, widgetID, Intent(context, NewCalendarEventReceiver::class.java).apply { action = Actions.ACTION_GO_TO_PREVIOUS_EVENT }, 0))
|
views.setOnClickPendingIntent(
|
||||||
|
R.id.action_previous_rect,
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
widgetID,
|
||||||
|
Intent(
|
||||||
|
context,
|
||||||
|
NewCalendarEventReceiver::class.java
|
||||||
|
).apply { action = Actions.ACTION_GO_TO_PREVIOUS_EVENT },
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
views.setViewVisibility(R.id.action_next_rect, View.GONE)
|
views.setViewVisibility(R.id.action_next_rect, View.GONE)
|
||||||
views.setViewVisibility(R.id.action_previous_rect, View.GONE)
|
views.setViewVisibility(R.id.action_previous_rect, View.GONE)
|
||||||
}
|
}
|
||||||
|
|
||||||
val pIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getEventIntent(context, nextEvent), 0)
|
val pIntent = PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
widgetID,
|
||||||
|
IntentHelper.getEventIntent(context, nextEvent),
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
views.setOnClickPendingIntent(R.id.next_event_rect, pIntent)
|
views.setOnClickPendingIntent(R.id.next_event_rect, pIntent)
|
||||||
views.setOnClickPendingIntent(R.id.next_event_difference_time_rect, pIntent)
|
views.setOnClickPendingIntent(R.id.next_event_difference_time_rect, pIntent)
|
||||||
|
|
||||||
if (Preferences.showDiffTime && Calendar.getInstance().timeInMillis < (nextEvent.startDate - 1000 * 60 * 60)) {
|
if (Preferences.showDiffTime && Calendar.getInstance().timeInMillis < (nextEvent.startDate - 1000 * 60 * 60)) {
|
||||||
views.setImageViewBitmap(R.id.next_event_difference_time_rect, BitmapHelper.getBitmapFromView(v.next_event_difference_time, draw = false))
|
views.setImageViewBitmap(
|
||||||
|
R.id.next_event_difference_time_rect,
|
||||||
|
BitmapHelper.getBitmapFromView(
|
||||||
|
v.next_event_difference_time,
|
||||||
|
draw = false
|
||||||
|
)
|
||||||
|
)
|
||||||
views.setViewVisibility(R.id.next_event_difference_time_rect, View.VISIBLE)
|
views.setViewVisibility(R.id.next_event_difference_time_rect, View.VISIBLE)
|
||||||
} else {
|
} else {
|
||||||
views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE)
|
views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
|
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
|
||||||
val mapIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getGoogleMapsIntentFromAddress(context, nextEvent.address), 0)
|
val mapIntent = PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
widgetID,
|
||||||
|
IntentHelper.getGoogleMapsIntentFromAddress(context, nextEvent.address),
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
views.setOnClickPendingIntent(R.id.second_row_rect, mapIntent)
|
views.setOnClickPendingIntent(R.id.second_row_rect, mapIntent)
|
||||||
} else {
|
} else {
|
||||||
views.setOnClickPendingIntent(R.id.second_row_rect, pIntent)
|
val pIntentDetail = PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
widgetID,
|
||||||
|
IntentHelper.getEventIntent(
|
||||||
|
context,
|
||||||
|
nextEvent,
|
||||||
|
forceEventDetails = true
|
||||||
|
),
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
views.setOnClickPendingIntent(R.id.second_row_rect, pIntentDetail)
|
||||||
}
|
}
|
||||||
|
|
||||||
views.setImageViewBitmap(R.id.next_event_rect, BitmapHelper.getBitmapFromView(v.next_event, draw = false))
|
views.setImageViewBitmap(
|
||||||
|
R.id.next_event_rect,
|
||||||
|
BitmapHelper.getBitmapFromView(v.next_event, draw = false)
|
||||||
|
)
|
||||||
|
|
||||||
views.setImageViewBitmap(R.id.second_row_rect, BitmapHelper.getBitmapFromView(v.second_row, draw = false))
|
views.setImageViewBitmap(
|
||||||
|
R.id.second_row_rect,
|
||||||
|
BitmapHelper.getBitmapFromView(v.second_row, draw = false)
|
||||||
|
)
|
||||||
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
|
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
|
||||||
|
|
||||||
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)
|
||||||
} else if (Preferences.showNextAlarm && nextAlarm != "") {
|
} else if (GlanceProviderHelper.showGlanceProviders(context) && v.calendar_layout.isVisible) {
|
||||||
val clockIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getClockIntent(context), 0)
|
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(context)) {
|
||||||
views.setOnClickPendingIntent(R.id.second_row_rect, clockIntent)
|
when (provider) {
|
||||||
|
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||||
|
if (MediaPlayerHelper.isSomeonePlaying(context)) {
|
||||||
|
val musicIntent = PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
widgetID,
|
||||||
|
IntentHelper.getMusicIntent(context),
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
views.setOnClickPendingIntent(R.id.second_row_rect, musicIntent)
|
||||||
|
break@loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
||||||
|
if (Preferences.showNextAlarm && nextAlarm != "") {
|
||||||
|
val alarmIntent = PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
widgetID,
|
||||||
|
IntentHelper.getClockIntent(context),
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
views.setOnClickPendingIntent(R.id.second_row_rect, alarmIntent)
|
||||||
|
break@loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
||||||
|
if (Preferences.showBatteryCharging) {
|
||||||
|
BatteryHelper.updateBatteryInfo(context)
|
||||||
|
if (Preferences.isCharging || Preferences.isBatteryLevelLow) {
|
||||||
|
val batteryIntent = PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
widgetID,
|
||||||
|
IntentHelper.getBatteryIntent(),
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
views.setOnClickPendingIntent(R.id.second_row_rect, batteryIntent)
|
||||||
|
break@loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
||||||
|
if (Preferences.customNotes.isNotEmpty()) {
|
||||||
|
break@loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||||
|
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
|
||||||
|
val fitIntent = PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
widgetID,
|
||||||
|
IntentHelper.getFitIntent(context),
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
|
)
|
||||||
|
views.setOnClickPendingIntent(R.id.second_row_rect, fitIntent)
|
||||||
|
break@loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
views.setImageViewBitmap(R.id.next_event_rect, BitmapHelper.getBitmapFromView(v.next_event, draw = false))
|
views.setImageViewBitmap(
|
||||||
|
R.id.next_event_rect,
|
||||||
|
BitmapHelper.getBitmapFromView(v.next_event, draw = false)
|
||||||
|
)
|
||||||
|
|
||||||
|
views.setImageViewBitmap(
|
||||||
|
R.id.second_row_rect,
|
||||||
|
BitmapHelper.getBitmapFromView(v.second_row, draw = false)
|
||||||
|
)
|
||||||
|
|
||||||
views.setImageViewBitmap(R.id.second_row_rect, BitmapHelper.getBitmapFromView(v.second_row, draw = false))
|
|
||||||
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
|
views.setViewVisibility(R.id.second_row_rect, View.VISIBLE)
|
||||||
|
|
||||||
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)
|
||||||
|
}
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
CrashlyticsReceiver.sendCrash(context, ex)
|
||||||
|
} finally {
|
||||||
|
eventRepository.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
return views
|
return views
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateWeatherView(context: Context, v: View, views: RemoteViews, widgetID: Int): RemoteViews {
|
private fun updateWeatherView(context: Context, v: View, views: RemoteViews, widgetID: Int): RemoteViews {
|
||||||
|
try {
|
||||||
if (Preferences.showWeather && Preferences.weatherIcon != "") {
|
if (Preferences.showWeather && Preferences.weatherIcon != "") {
|
||||||
views.setViewVisibility(R.id.weather_rect, View.VISIBLE)
|
views.setViewVisibility(R.id.weather_rect, View.VISIBLE)
|
||||||
views.setViewVisibility(R.id.calendar_weather_rect, View.VISIBLE)
|
views.setViewVisibility(R.id.calendar_weather_rect, View.VISIBLE)
|
||||||
|
views.setViewVisibility(R.id.special_weather_rect, View.VISIBLE)
|
||||||
|
|
||||||
val i = Intent(context, WidgetClickListenerReceiver::class.java)
|
val i = Intent(context, WidgetClickListenerReceiver::class.java)
|
||||||
i.action = Actions.ACTION_OPEN_WEATHER_INTENT
|
i.action = Actions.ACTION_OPEN_WEATHER_INTENT
|
||||||
@ -194,26 +363,93 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
|
|
||||||
views.setOnClickPendingIntent(R.id.weather_rect, weatherPIntent)
|
views.setOnClickPendingIntent(R.id.weather_rect, weatherPIntent)
|
||||||
views.setOnClickPendingIntent(R.id.calendar_weather_rect, weatherPIntent)
|
views.setOnClickPendingIntent(R.id.calendar_weather_rect, weatherPIntent)
|
||||||
|
views.setOnClickPendingIntent(R.id.special_weather_rect, weatherPIntent)
|
||||||
|
|
||||||
views.setImageViewBitmap(R.id.weather_rect, BitmapHelper.getBitmapFromView(v.weather, draw = false))
|
views.setImageViewBitmap(
|
||||||
|
R.id.weather_rect,
|
||||||
|
BitmapHelper.getBitmapFromView(v.weather, draw = false)
|
||||||
|
)
|
||||||
|
|
||||||
views.setImageViewBitmap(R.id.calendar_weather_rect, BitmapHelper.getBitmapFromView(v.calendar_weather, draw = false))
|
views.setImageViewBitmap(
|
||||||
|
R.id.calendar_weather_rect,
|
||||||
|
BitmapHelper.getBitmapFromView(v.calendar_weather, draw = false)
|
||||||
|
)
|
||||||
|
|
||||||
|
views.setImageViewBitmap(
|
||||||
|
R.id.special_weather_rect,
|
||||||
|
BitmapHelper.getBitmapFromView(v.calendar_weather, draw = false)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (GlanceProviderHelper.showGlanceProviders(context)) {
|
||||||
|
views.setViewVisibility(R.id.calendar_weather_rect, View.GONE)
|
||||||
|
} else {
|
||||||
|
views.setViewVisibility(R.id.special_weather_rect, View.GONE)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
views.setViewVisibility(R.id.weather_rect, View.GONE)
|
views.setViewVisibility(R.id.weather_rect, View.GONE)
|
||||||
views.setViewVisibility(R.id.calendar_weather_rect, View.GONE)
|
views.setViewVisibility(R.id.calendar_weather_rect, View.GONE)
|
||||||
|
views.setViewVisibility(R.id.special_weather_rect, View.GONE)
|
||||||
|
}
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
CrashlyticsReceiver.sendCrash(context, ex)
|
||||||
}
|
}
|
||||||
return views
|
return views
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateClockView(context: Context, views: RemoteViews, widgetID: Int): RemoteViews {
|
private fun updateClockView(context: Context, views: RemoteViews, widgetID: Int): RemoteViews {
|
||||||
|
try {
|
||||||
if (!Preferences.showClock) {
|
if (!Preferences.showClock) {
|
||||||
views.setViewVisibility(R.id.time, View.GONE)
|
views.setViewVisibility(R.id.time, View.GONE)
|
||||||
|
views.setViewVisibility(R.id.time_am_pm, View.GONE)
|
||||||
|
views.setViewVisibility(R.id.clock_bottom_margin_none, View.GONE)
|
||||||
|
views.setViewVisibility(R.id.clock_bottom_margin_small, View.GONE)
|
||||||
|
views.setViewVisibility(R.id.clock_bottom_margin_medium, View.GONE)
|
||||||
|
views.setViewVisibility(R.id.clock_bottom_margin_large, View.GONE)
|
||||||
} else {
|
} else {
|
||||||
views.setTextColor(R.id.time, ColorHelper.getFontColor())
|
views.setTextColor(R.id.time, ColorHelper.getClockFontColor())
|
||||||
views.setTextViewTextSize(R.id.time, TypedValue.COMPLEX_UNIT_SP, Preferences.clockTextSize.toPixel(context))
|
views.setTextColor(R.id.time_am_pm, ColorHelper.getClockFontColor())
|
||||||
val clockPIntent = PendingIntent.getActivity(context, widgetID, IntentHelper.getClockIntent(context), 0)
|
views.setTextViewTextSize(
|
||||||
|
R.id.time,
|
||||||
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
|
Preferences.clockTextSize.toPixel(context)
|
||||||
|
)
|
||||||
|
views.setTextViewTextSize(
|
||||||
|
R.id.time_am_pm,
|
||||||
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
|
Preferences.clockTextSize.toPixel(context) / 5 * 2
|
||||||
|
)
|
||||||
|
val clockPIntent = PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
widgetID,
|
||||||
|
IntentHelper.getClockIntent(context),
|
||||||
|
0
|
||||||
|
)
|
||||||
views.setOnClickPendingIntent(R.id.time, clockPIntent)
|
views.setOnClickPendingIntent(R.id.time, clockPIntent)
|
||||||
|
views.setOnClickPendingIntent(R.id.time_am_pm, clockPIntent)
|
||||||
views.setViewVisibility(R.id.time, View.VISIBLE)
|
views.setViewVisibility(R.id.time, View.VISIBLE)
|
||||||
|
views.setViewVisibility(R.id.time_am_pm, if (Preferences.showAMPMIndicator) View.VISIBLE else View.GONE)
|
||||||
|
|
||||||
|
views.setViewVisibility(
|
||||||
|
R.id.clock_bottom_margin_none,
|
||||||
|
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.value) View.VISIBLE else View.GONE
|
||||||
|
)
|
||||||
|
views.setViewVisibility(
|
||||||
|
R.id.clock_bottom_margin_small,
|
||||||
|
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.value) View.VISIBLE else View.GONE
|
||||||
|
)
|
||||||
|
views.setViewVisibility(
|
||||||
|
R.id.clock_bottom_margin_medium,
|
||||||
|
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.value) View.VISIBLE else View.GONE
|
||||||
|
)
|
||||||
|
views.setViewVisibility(
|
||||||
|
R.id.clock_bottom_margin_large,
|
||||||
|
if (Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.value) View.VISIBLE else View.GONE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
CrashlyticsReceiver.sendCrash(context, ex)
|
||||||
}
|
}
|
||||||
|
|
||||||
return views
|
return views
|
||||||
@ -225,10 +461,14 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
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)
|
||||||
|
|
||||||
val now = Calendar.getInstance()
|
val now = Calendar.getInstance().apply {
|
||||||
|
set(Calendar.SECOND, 0)
|
||||||
|
set(Calendar.MILLISECOND, 0)
|
||||||
|
}
|
||||||
|
|
||||||
v.empty_layout.visibility = View.VISIBLE
|
v.empty_layout.visibility = View.VISIBLE
|
||||||
v.calendar_layout.visibility = View.GONE
|
v.calendar_layout.visibility = View.GONE
|
||||||
|
v.next_event_difference_time.visibility = View.GONE
|
||||||
v.action_next.isVisible = false
|
v.action_next.isVisible = false
|
||||||
v.action_previous.isVisible = false
|
v.action_previous.isVisible = false
|
||||||
|
|
||||||
@ -244,7 +484,7 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
|
|
||||||
v.next_event.text = nextEvent.title
|
v.next_event.text = nextEvent.title
|
||||||
|
|
||||||
if (Preferences.showDiffTime && now.timeInMillis < (nextEvent.startDate - 1000 * 60 * 60)) {
|
if (Preferences.showDiffTime && now.timeInMillis < nextEvent.startDate) {
|
||||||
v.next_event_difference_time.text = if (!nextEvent.allDay) {
|
v.next_event_difference_time.text = if (!nextEvent.allDay) {
|
||||||
SettingsStringHelper.getDifferenceText(
|
SettingsStringHelper.getDifferenceText(
|
||||||
context,
|
context,
|
||||||
@ -266,8 +506,8 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
} 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).format(nextEvent.startDate)
|
val startHour = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault()).format(nextEvent.startDate)
|
||||||
val endHour = DateFormat.getTimeInstance(DateFormat.SHORT).format(nextEvent.endDate)
|
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)
|
||||||
|
|
||||||
@ -290,45 +530,133 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
val flags: Int = DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
val flags: Int = DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
||||||
v.next_event_date.text = DateUtils.formatDateTime(context, now.timeInMillis, flags).getCapWordString()
|
v.next_event_date.text = 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
|
||||||
} else if (Preferences.showNextAlarm && nextAlarm != "") {
|
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
|
||||||
|
v.second_row_icon.isVisible = true
|
||||||
|
var showSomething = false
|
||||||
|
loop@ for (provider:Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(context)) {
|
||||||
|
when (provider) {
|
||||||
|
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||||
|
if (MediaPlayerHelper.isSomeonePlaying(context)) {
|
||||||
|
v.second_row_icon.setImageDrawable(
|
||||||
|
ContextCompat.getDrawable(
|
||||||
|
context,
|
||||||
|
R.drawable.round_music_note
|
||||||
|
)
|
||||||
|
)
|
||||||
|
v.next_event_date.text = MediaPlayerHelper.getMediaInfo()
|
||||||
|
showSomething = true
|
||||||
|
break@loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
||||||
|
if (Preferences.showNextAlarm && nextAlarm != "") {
|
||||||
v.second_row_icon.setImageDrawable(
|
v.second_row_icon.setImageDrawable(
|
||||||
ContextCompat.getDrawable(
|
ContextCompat.getDrawable(
|
||||||
context,
|
context,
|
||||||
R.drawable.round_alarm
|
R.drawable.round_alarm
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
v.next_event.text = DateHelper.getDateText(context, now)
|
|
||||||
v.next_event_date.text = AlarmHelper.getNextAlarm(context)
|
v.next_event_date.text = AlarmHelper.getNextAlarm(context)
|
||||||
|
showSomething = true
|
||||||
|
break@loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
||||||
|
if (Preferences.showBatteryCharging) {
|
||||||
|
BatteryHelper.updateBatteryInfo(context)
|
||||||
|
if (Preferences.isCharging) {
|
||||||
|
v.second_row_icon.isVisible = false
|
||||||
|
val batteryLevel = BatteryHelper.getBatteryLevel(context)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
showSomething = true
|
||||||
|
break@loop
|
||||||
|
} else if (Preferences.isBatteryLevelLow) {
|
||||||
|
v.second_row_icon.isVisible = false
|
||||||
|
v.next_event_date.text =
|
||||||
|
context.getString(R.string.battery_low_warning)
|
||||||
|
showSomething = true
|
||||||
|
break@loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
||||||
|
if (Preferences.customNotes.isNotEmpty()) {
|
||||||
|
v.second_row_icon.isVisible = false
|
||||||
|
v.next_event_date.text = Preferences.customNotes
|
||||||
|
v.next_event_date.gravity
|
||||||
|
v.next_event_date.maxLines = 2
|
||||||
|
showSomething = true
|
||||||
|
break@loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||||
|
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
|
||||||
|
v.second_row_icon.isVisible = false
|
||||||
|
v.next_event_date.text = context.getString(R.string.daily_steps_counter).format(Preferences.googleFitSteps)
|
||||||
|
showSomething = true
|
||||||
|
break@loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showSomething) {
|
||||||
|
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
|
||||||
|
} else {
|
||||||
|
v.second_row_icon.isVisible = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
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).forEach {
|
listOf<TextView>(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())
|
it.setTextColor(ColorHelper.getFontColor())
|
||||||
}
|
}
|
||||||
|
|
||||||
listOf<ImageView>(v.second_row_icon, v.action_next, v.action_previous).forEach {
|
if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) {
|
||||||
|
listOf<ImageView>(v.action_next, v.action_previous)
|
||||||
|
} else {
|
||||||
|
listOf<ImageView>(v.action_next, v.action_previous, v.empty_weather_icon, v.special_weather_icon)
|
||||||
|
}.forEach {
|
||||||
it.setColorFilter(ColorHelper.getFontColor())
|
it.setColorFilter(ColorHelper.getFontColor())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listOf<TextView>(v.next_event_date, v.divider2, v.calendar_temp).forEach {
|
||||||
|
it.setTextColor(ColorHelper.getSecondaryFontColor())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Preferences.weatherIconPack == Constants.WeatherIconPack.DEFAULT.value) {
|
||||||
|
listOf<ImageView>(v.second_row_icon)
|
||||||
|
} else {
|
||||||
|
listOf<ImageView>(v.second_row_icon, v.weather_icon)
|
||||||
|
}.forEach {
|
||||||
|
it.setColorFilter(ColorHelper.getSecondaryFontColor())
|
||||||
|
}
|
||||||
|
|
||||||
// Text Size
|
// Text Size
|
||||||
listOf<Pair<TextView, Float>>(
|
listOf<Pair<TextView, Float>>(
|
||||||
v.empty_date to Preferences.textMainSize,
|
v.empty_date to Preferences.textMainSize,
|
||||||
v.divider1 to Preferences.textMainSize,
|
v.divider1 to (Preferences.textMainSize - 2),
|
||||||
v.temp to Preferences.textMainSize,
|
v.temp to Preferences.textMainSize,
|
||||||
v.next_event to Preferences.textMainSize,
|
v.next_event to Preferences.textMainSize,
|
||||||
v.next_event_difference_time to Preferences.textMainSize,
|
v.next_event_difference_time to Preferences.textMainSize,
|
||||||
v.next_event_date to Preferences.textSecondSize,
|
v.next_event_date to Preferences.textSecondSize,
|
||||||
v.divider2 to Preferences.textSecondSize,
|
v.divider2 to (Preferences.textSecondSize - 2),
|
||||||
v.calendar_temp to Preferences.textSecondSize
|
v.calendar_temp to Preferences.textSecondSize,
|
||||||
|
v.divider3 to (Preferences.textMainSize - 2),
|
||||||
|
v.special_temp to Preferences.textMainSize
|
||||||
).forEach {
|
).forEach {
|
||||||
it.first.setTextSize(TypedValue.COMPLEX_UNIT_SP, it.second)
|
it.first.setTextSize(TypedValue.COMPLEX_UNIT_SP, it.second)
|
||||||
}
|
}
|
||||||
@ -337,11 +665,11 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
v.second_row_icon.scaleX = Preferences.textSecondSize / 18f
|
v.second_row_icon.scaleX = Preferences.textSecondSize / 18f
|
||||||
v.second_row_icon.scaleY = Preferences.textSecondSize / 18f
|
v.second_row_icon.scaleY = Preferences.textSecondSize / 18f
|
||||||
|
|
||||||
v.weather_icon.scaleX = Preferences.textSecondSize / 16f
|
v.weather_icon.scaleX = Preferences.textSecondSize / 14f
|
||||||
v.weather_icon.scaleY = Preferences.textSecondSize / 16f
|
v.weather_icon.scaleY = Preferences.textSecondSize / 14f
|
||||||
|
|
||||||
v.empty_weather_icon.scaleX = Preferences.textMainSize / 20f
|
v.empty_weather_icon.scaleX = Preferences.textMainSize / 18f
|
||||||
v.empty_weather_icon.scaleY = Preferences.textMainSize / 20f
|
v.empty_weather_icon.scaleY = Preferences.textMainSize / 18f
|
||||||
|
|
||||||
v.action_next.scaleX = Preferences.textMainSize / 28f
|
v.action_next.scaleX = Preferences.textMainSize / 28f
|
||||||
v.action_next.scaleY = Preferences.textMainSize / 28f
|
v.action_next.scaleY = Preferences.textMainSize / 28f
|
||||||
@ -349,6 +677,9 @@ 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.scaleY = Preferences.textMainSize / 20f
|
||||||
|
|
||||||
|
|
||||||
// Shadows
|
// Shadows
|
||||||
val shadowRadius = when (Preferences.textShadow) {
|
val shadowRadius = when (Preferences.textShadow) {
|
||||||
@ -370,14 +701,14 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
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).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)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom Font
|
// Custom Font
|
||||||
if (Preferences.customFont == Constants.CUSTOM_FONT_PRODUCT_SANS) {
|
if (Preferences.customFont == Constants.CUSTOM_FONT_PRODUCT_SANS) {
|
||||||
val productSans: Typeface = Typeface.createFromAsset(context.assets, "fonts/product_sans_regular.ttf")
|
val productSans: Typeface = Typeface.createFromAsset(context.assets, "fonts/product_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).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.typeface = productSans
|
it.typeface = productSans
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -386,26 +717,45 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
if (Preferences.showWeather && Preferences.weatherIcon != "") {
|
if (Preferences.showWeather && Preferences.weatherIcon != "") {
|
||||||
v.weather.visibility = View.VISIBLE
|
v.weather.visibility = View.VISIBLE
|
||||||
v.calendar_weather.visibility = View.VISIBLE
|
v.calendar_weather.visibility = View.VISIBLE
|
||||||
val currentTemp = String.format(Locale.getDefault(), "%.0f °%s", Preferences.weatherTemp, Preferences.weatherRealTempUnit)
|
v.special_weather.visibility = View.VISIBLE
|
||||||
|
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 == "") {
|
||||||
v.weather_icon.visibility = View.GONE
|
v.weather_icon.visibility = View.GONE
|
||||||
v.empty_weather_icon.visibility = View.GONE
|
v.empty_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(icon))
|
||||||
v.empty_weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(icon))
|
v.empty_weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(icon))
|
||||||
|
v.special_weather_icon.setImageResource(WeatherHelper.getWeatherIconResource(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.temp.text = currentTemp
|
v.temp.text = currentTemp
|
||||||
v.calendar_temp.text = currentTemp
|
v.calendar_temp.text = currentTemp
|
||||||
|
v.special_temp.text = currentTemp
|
||||||
|
|
||||||
|
if (GlanceProviderHelper.showGlanceProviders(context)) {
|
||||||
|
v.calendar_weather.visibility = View.GONE
|
||||||
|
} else {
|
||||||
|
v.special_weather.visibility = View.GONE
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
v.weather.visibility = View.GONE
|
v.weather.visibility = View.GONE
|
||||||
v.calendar_weather.visibility = View.GONE
|
v.calendar_weather.visibility = View.GONE
|
||||||
|
v.special_weather.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dividers
|
||||||
|
arrayOf(v.divider1, v.divider2, v.divider3).forEach {
|
||||||
|
it.isVisible = Preferences.showDividers
|
||||||
|
}
|
||||||
|
|
||||||
|
eventRepository.close()
|
||||||
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,8 @@ import java.util.*
|
|||||||
|
|
||||||
fun PackageManager.missingSystemFeature(name: String): Boolean = !hasSystemFeature(name)
|
fun PackageManager.missingSystemFeature(name: String): Boolean = !hasSystemFeature(name)
|
||||||
|
|
||||||
fun Context.toast(message: String) {
|
fun Context.toast(message: String, long: Boolean = false) {
|
||||||
val toast = Toast.makeText(this, message, Toast.LENGTH_SHORT)
|
val toast = Toast.makeText(this, message, if (long) Toast.LENGTH_LONG else Toast.LENGTH_SHORT)
|
||||||
// toast.setGravity(Gravity.CENTER, 0, 0)
|
// toast.setGravity(Gravity.CENTER, 0, 0)
|
||||||
toast.show()
|
toast.show()
|
||||||
}
|
}
|
||||||
@ -213,3 +213,12 @@ fun String.getCapWordString(): String {
|
|||||||
this
|
this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Context.checkIfFitInstalled(): Boolean {
|
||||||
|
return try {
|
||||||
|
packageManager.getPackageInfo("com.google.android.apps.fitness", PackageManager.GET_ACTIVITIES)
|
||||||
|
true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
BIN
app/src/main/res/drawable-hdpi/round_access_alarm.png
Normal file
After Width: | Height: | Size: 868 B |
BIN
app/src/main/res/drawable-hdpi/round_access_alarm_black_18.png
Normal file
After Width: | Height: | Size: 459 B |
BIN
app/src/main/res/drawable-hdpi/round_access_alarm_black_24.png
Normal file
After Width: | Height: | Size: 601 B |
BIN
app/src/main/res/drawable-hdpi/round_access_alarm_black_48.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-hdpi/round_all_inclusive.png
Normal file
After Width: | Height: | Size: 465 B |
BIN
app/src/main/res/drawable-hdpi/round_all_inclusive_black_18.png
Normal file
After Width: | Height: | Size: 399 B |
BIN
app/src/main/res/drawable-hdpi/round_all_inclusive_black_36.png
Normal file
After Width: | Height: | Size: 665 B |
BIN
app/src/main/res/drawable-hdpi/round_all_inclusive_black_48.png
Normal file
After Width: | Height: | Size: 867 B |
BIN
app/src/main/res/drawable-hdpi/round_arrow_back.png
Normal file
After Width: | Height: | Size: 183 B |
BIN
app/src/main/res/drawable-hdpi/round_aspect_ratio.png
Normal file
After Width: | Height: | Size: 295 B |
BIN
app/src/main/res/drawable-hdpi/round_aspect_ratio_black_18.png
Normal file
After Width: | Height: | Size: 275 B |
BIN
app/src/main/res/drawable-hdpi/round_aspect_ratio_black_36.png
Normal file
After Width: | Height: | Size: 399 B |
BIN
app/src/main/res/drawable-hdpi/round_aspect_ratio_black_48.png
Normal file
After Width: | Height: | Size: 428 B |
BIN
app/src/main/res/drawable-hdpi/round_battery_charging_full.png
Normal file
After Width: | Height: | Size: 426 B |
After Width: | Height: | Size: 238 B |
After Width: | Height: | Size: 263 B |
After Width: | Height: | Size: 355 B |
After Width: | Height: | Size: 186 B |
After Width: | Height: | Size: 184 B |
After Width: | Height: | Size: 241 B |
After Width: | Height: | Size: 248 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_4.png
Normal file
After Width: | Height: | Size: 616 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_4_black_18.png
Normal file
After Width: | Height: | Size: 324 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_4_black_24.png
Normal file
After Width: | Height: | Size: 372 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_4_black_36.png
Normal file
After Width: | Height: | Size: 517 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_5.png
Normal file
After Width: | Height: | Size: 361 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_5_black_18.png
Normal file
After Width: | Height: | Size: 333 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_5_black_36.png
Normal file
After Width: | Height: | Size: 509 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_5_black_48.png
Normal file
After Width: | Height: | Size: 642 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_7.png
Normal file
After Width: | Height: | Size: 393 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_7_black_24.png
Normal file
After Width: | Height: | Size: 441 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_7_black_36.png
Normal file
After Width: | Height: | Size: 628 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_7_black_48.png
Normal file
After Width: | Height: | Size: 802 B |
BIN
app/src/main/res/drawable-hdpi/round_brightness_low.png
Normal file
After Width: | Height: | Size: 399 B |