Compare commits
64 Commits
v2.3.1
...
v2.3.3-pat
Author | SHA1 | Date | |
---|---|---|---|
183901534c | |||
6d7d90e762 | |||
e89b377b68 | |||
e0eb6f77da | |||
43c08204c3 | |||
6f125573e0 | |||
380dc96c40 | |||
821980e938 | |||
9f47d626a9 | |||
d3b623cf13 | |||
1389ddbfc0 | |||
0dbbe0e5d2 | |||
818b4ec0ba | |||
8c84913cd8 | |||
43f085b13c | |||
3ab42fd163 | |||
ea0be72478 | |||
c744d3c7f8 | |||
7b93548b0b | |||
260e36b305 | |||
00af2159ea | |||
c26021de03 | |||
218dae8cc2 | |||
b3e2d8d843 | |||
80d1077dab | |||
dd2a74aaf6 | |||
fb1953d513 | |||
b081b9adbb | |||
fd398faf42 | |||
e14662c534 | |||
4224562512 | |||
f13d426831 | |||
5dc7a1b30d | |||
6538cdebc2 | |||
78709ed018 | |||
c0e87047c2 | |||
1a2c97d61f | |||
4335751749 | |||
9bbc816bea | |||
e8a6743dc4 | |||
5d8ceb98cc | |||
dfff4c5e1b | |||
13f8814480 | |||
8608f9adf3 | |||
ad65cf0e84 | |||
1ecaf7a11a | |||
2578566659 | |||
61fc0da8d0 | |||
285b754dd5 | |||
194a2ab456 | |||
bca22d5aa8 | |||
35536a89a0 | |||
6780a470e9 | |||
6ca6b5ab95 | |||
7edb0635a7 | |||
d72ddd6d85 | |||
5d07cc8d73 | |||
1ac53e09a8 | |||
3412e044df | |||
80023da430 | |||
e2a2d17506 | |||
b93443b736 | |||
9842ba3ea9 | |||
75aba66987 |
180
.idea/assetWizardSettings.xml
generated
@ -19,6 +19,29 @@
|
|||||||
<option name="children">
|
<option name="children">
|
||||||
<map>
|
<map>
|
||||||
<entry key="clipArt">
|
<entry key="clipArt">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="color" value="000000" />
|
||||||
|
<entry key="imagePath" value="/private/var/folders/cw/tkrg0g5j6lzcqwr0tfkph8w80000gn/T/ic_android_black_24dp.xml" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="text">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="color" value="000000" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="textAsset">
|
||||||
<value>
|
<value>
|
||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="values">
|
<option name="values">
|
||||||
@ -45,14 +68,47 @@
|
|||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="children">
|
<option name="children">
|
||||||
<map>
|
<map>
|
||||||
|
<entry key="foregroundClipArt">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="imagePath" value="/private/var/folders/cw/tkrg0g5j6lzcqwr0tfkph8w80000gn/T/ic_android_black_24dp.xml" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="foregroundImage">
|
<entry key="foregroundImage">
|
||||||
<value>
|
<value>
|
||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="values">
|
<option name="values">
|
||||||
<map>
|
<map>
|
||||||
<entry key="color" value="000000" />
|
<entry key="color" value="000000" />
|
||||||
|
<entry key="imagePath" value="$USER_HOME$/Desktop/logo-white.png" />
|
||||||
<entry key="scalingPercent" value="70" />
|
<entry key="scalingPercent" value="70" />
|
||||||
<entry key="trimmed" value="true" />
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="foregroundText">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="color" value="000000" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="foregroundTextAsset">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="color" value="000000" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</PersistentState>
|
</PersistentState>
|
||||||
@ -64,7 +120,6 @@
|
|||||||
<map>
|
<map>
|
||||||
<entry key="backgroundAssetType" value="COLOR" />
|
<entry key="backgroundAssetType" value="COLOR" />
|
||||||
<entry key="backgroundColor" value="ffffff" />
|
<entry key="backgroundColor" value="ffffff" />
|
||||||
<entry key="foregroundImage" value="$USER_HOME$/Desktop/Artboard Copy 3.png" />
|
|
||||||
<entry key="legacyIconShape" value="CIRCLE" />
|
<entry key="legacyIconShape" value="CIRCLE" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
@ -77,6 +132,29 @@
|
|||||||
<option name="children">
|
<option name="children">
|
||||||
<map>
|
<map>
|
||||||
<entry key="clipArt">
|
<entry key="clipArt">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="color" value="000000" />
|
||||||
|
<entry key="imagePath" value="/private/var/folders/cw/tkrg0g5j6lzcqwr0tfkph8w80000gn/T/ic_android_black_24dp.xml" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="text">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="color" value="000000" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="textAsset">
|
||||||
<value>
|
<value>
|
||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="values">
|
<option name="values">
|
||||||
@ -98,6 +176,104 @@
|
|||||||
<option name="children">
|
<option name="children">
|
||||||
<map>
|
<map>
|
||||||
<entry key="clipArt">
|
<entry key="clipArt">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="color" value="000000" />
|
||||||
|
<entry key="imagePath" value="/private/var/folders/cw/tkrg0g5j6lzcqwr0tfkph8w80000gn/T/ic_android_black_24dp.xml" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="text">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="color" value="000000" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="textAsset">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="color" value="000000" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="tvBanner">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="children">
|
||||||
|
<map>
|
||||||
|
<entry key="foregroundText">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="color" value="000000" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="tvChannel">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="children">
|
||||||
|
<map>
|
||||||
|
<entry key="foregroundClipArt">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="imagePath" value="/private/var/folders/cw/tkrg0g5j6lzcqwr0tfkph8w80000gn/T/ic_android_black_24dp.xml" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="foregroundImage">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="color" value="000000" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="foregroundText">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="color" value="000000" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
<entry key="foregroundTextAsset">
|
||||||
<value>
|
<value>
|
||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="values">
|
<option name="values">
|
||||||
|
BIN
.idea/caches/build_file_checksums.ser
generated
2
.idea/misc.xml
generated
@ -61,7 +61,7 @@
|
|||||||
</profile-state>
|
</profile-state>
|
||||||
</entry>
|
</entry>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
1
.idea/runConfigurations.xml
generated
@ -3,6 +3,7 @@
|
|||||||
<component name="RunConfigurationProducerService">
|
<component name="RunConfigurationProducerService">
|
||||||
<option name="ignoredProducers">
|
<option name="ignoredProducers">
|
||||||
<set>
|
<set>
|
||||||
|
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||||
|
@ -22,8 +22,8 @@ android {
|
|||||||
applicationId "com.tommasoberlose.anotherwidget"
|
applicationId "com.tommasoberlose.anotherwidget"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode 130
|
versionCode 139
|
||||||
versionName "2.3.1"
|
versionName "2.3.3"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY'])
|
buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY'])
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
<uses-permission android:name="android.permission.READ_CALENDAR" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_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" />
|
||||||
@ -13,6 +14,7 @@
|
|||||||
<uses-permission android:name="android.gms.permission.ACTIVITY_RECOGNITION"/>
|
<uses-permission android:name="android.gms.permission.ACTIVITY_RECOGNITION"/>
|
||||||
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
|
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
@ -24,24 +26,24 @@
|
|||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
tools:ignore="LockedOrientationActivity">
|
tools:ignore="LockedOrientationActivity">
|
||||||
<activity android:name=".ui.activities.MainActivity" android:launchMode="singleInstance" android:theme="@style/AppTheme.Main" android:screenOrientation="portrait">
|
<activity android:name=".ui.activities.MainActivity" 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.tabs.ChooseApplicationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.ChooseApplicationActivity" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.CustomFontActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.CustomFontActivity" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.CustomLocationActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.CustomLocationActivity" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.WeatherProviderActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.WeatherProviderActivity" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.settings.SupportDevActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.settings.SupportDevActivity" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.CustomDateActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.CustomDateActivity" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.settings.IntegrationsActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.settings.IntegrationsActivity" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.MusicPlayersFilterActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.MusicPlayersFilterActivity" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.AppNotificationsFilterActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.AppNotificationsFilterActivity" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.MediaInfoFormatActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.MediaInfoFormatActivity" android:screenOrientation="portrait" />
|
||||||
<activity android:name=".ui.activities.tabs.TimeZoneSelectorActivity" android:launchMode="singleInstance" android:screenOrientation="portrait" />
|
<activity android:name=".ui.activities.tabs.TimeZoneSelectorActivity" android:screenOrientation="portrait" />
|
||||||
|
|
||||||
<receiver android:name=".ui.widgets.MainWidget">
|
<receiver android:name=".ui.widgets.MainWidget">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 45 KiB |
@ -31,22 +31,5 @@ class AWApplication : Application() {
|
|||||||
.deleteRealmIfMigrationNeeded()
|
.deleteRealmIfMigrationNeeded()
|
||||||
.build()
|
.build()
|
||||||
Realm.setDefaultConfiguration(config)
|
Realm.setDefaultConfiguration(config)
|
||||||
|
|
||||||
calibrateVersions()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun calibrateVersions() {
|
|
||||||
// 2.0 Tolerance
|
|
||||||
if (Preferences.clockTextSize > 50f) {
|
|
||||||
Preferences.clockTextSize = 32f
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Preferences.textMainSize > 36f) {
|
|
||||||
Preferences.textMainSize = 32f
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Preferences.textSecondSize > 28f) {
|
|
||||||
Preferences.textSecondSize = 24f
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,40 +3,30 @@ package com.tommasoberlose.anotherwidget.components
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.text.Editable
|
|
||||||
import android.text.TextWatcher
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.GridLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.SeekBar
|
|
||||||
import androidx.annotation.ColorInt
|
|
||||||
import androidx.appcompat.widget.AppCompatImageView
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.widget.addTextChangedListener
|
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.databinding.BottomSheetMenuHorBinding
|
import com.tommasoberlose.anotherwidget.databinding.BottomSheetMenuHorBinding
|
||||||
import com.tommasoberlose.anotherwidget.databinding.BottomSheetMenuListBinding
|
import com.tommasoberlose.anotherwidget.databinding.BottomSheetMenuListBinding
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.copyToClipboard
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isClipboardColor
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||||
import com.tommasoberlose.anotherwidget.utils.expand
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.pasteFromClipboard
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||||
import com.tommasoberlose.anotherwidget.utils.reveal
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
|
||||||
import com.warkiz.widget.IndicatorSeekBar
|
import com.warkiz.widget.IndicatorSeekBar
|
||||||
import com.warkiz.widget.OnSeekChangeListener
|
import com.warkiz.widget.OnSeekChangeListener
|
||||||
import com.warkiz.widget.SeekParams
|
import com.warkiz.widget.SeekParams
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import net.idik.lib.slimadapter.SlimAdapter
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
import java.lang.Exception
|
|
||||||
import java.util.prefs.Preferences
|
|
||||||
|
|
||||||
class BottomSheetColorPicker(
|
class BottomSheetColorPicker(
|
||||||
context: Context,
|
context: Context,
|
||||||
@ -46,20 +36,45 @@ class BottomSheetColorPicker(
|
|||||||
private val onColorSelected: ((selectedValue: Int) -> Unit)? = null,
|
private val onColorSelected: ((selectedValue: Int) -> Unit)? = null,
|
||||||
private val showAlphaSelector: Boolean = false,
|
private val showAlphaSelector: Boolean = false,
|
||||||
private val alpha: Int = 0,
|
private val alpha: Int = 0,
|
||||||
private val onAlphaChangeListener: ((alpha: Int) -> Unit)? = null
|
private val onAlphaChangeListener: ((alpha: Int) -> Unit)? = null,
|
||||||
|
private val hideCopyPaste: Boolean = false,
|
||||||
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||||
|
|
||||||
private var loadingJobs: ArrayList<Job> = ArrayList()
|
private var loadingJobs: ArrayList<Job> = ArrayList()
|
||||||
private lateinit var adapter: SlimAdapter
|
private lateinit var adapter: SlimAdapter
|
||||||
|
private var alphaDebouncing: Job? = null
|
||||||
|
|
||||||
private var binding: BottomSheetMenuHorBinding = BottomSheetMenuHorBinding.inflate(LayoutInflater.from(context))
|
private var binding: BottomSheetMenuHorBinding = BottomSheetMenuHorBinding.inflate(LayoutInflater.from(context))
|
||||||
private var listBinding: BottomSheetMenuListBinding = BottomSheetMenuListBinding.inflate(LayoutInflater.from(context))
|
private var listBinding: BottomSheetMenuListBinding = BottomSheetMenuListBinding.inflate(LayoutInflater.from(context))
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {
|
||||||
|
window?.setDimAmount(0f)
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
binding.header.isVisible = header != null
|
binding.header.isVisible = header != null
|
||||||
binding.headerText.text = header ?: ""
|
binding.headerText.text = header ?: ""
|
||||||
|
|
||||||
|
if (hideCopyPaste) {
|
||||||
|
binding.actionContainer.isVisible = false
|
||||||
|
} else {
|
||||||
|
binding.actionContainer.isVisible = true
|
||||||
|
binding.actionCopy.setOnClickListener {
|
||||||
|
context.copyToClipboard(getSelected?.invoke(), alpha)
|
||||||
|
}
|
||||||
|
binding.actionPaste.setOnClickListener {
|
||||||
|
context.pasteFromClipboard { color, alpha ->
|
||||||
|
binding.alphaSelector.setProgress(alpha.toIntValue().toFloat())
|
||||||
|
|
||||||
|
adapter.notifyItemChanged(adapter.data.indexOf(getSelected?.invoke()))
|
||||||
|
onColorSelected?.invoke(Color.parseColor(color))
|
||||||
|
val idx = colors.toList().indexOf(getSelected?.invoke())
|
||||||
|
adapter.notifyItemChanged(idx)
|
||||||
|
(listBinding.root.layoutManager as GridLayoutManager).scrollToPositionWithOffset(idx,0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.actionPaste.isVisible = context.isClipboardColor()
|
||||||
|
}
|
||||||
|
|
||||||
// Alpha
|
// Alpha
|
||||||
binding.alphaSelectorContainer.isVisible = showAlphaSelector
|
binding.alphaSelectorContainer.isVisible = showAlphaSelector
|
||||||
binding.alphaSelector.setProgress(alpha.toFloat())
|
binding.alphaSelector.setProgress(alpha.toFloat())
|
||||||
@ -67,8 +82,15 @@ class BottomSheetColorPicker(
|
|||||||
binding.alphaSelector.onSeekChangeListener = object : OnSeekChangeListener {
|
binding.alphaSelector.onSeekChangeListener = object : OnSeekChangeListener {
|
||||||
override fun onSeeking(seekParams: SeekParams?) {
|
override fun onSeeking(seekParams: SeekParams?) {
|
||||||
seekParams?.let {
|
seekParams?.let {
|
||||||
binding.textAlpha.text = "%s: %s%%".format(context.getString(R.string.alpha), it.progress)
|
binding.textAlpha.text =
|
||||||
onAlphaChangeListener?.invoke(it.progress)
|
"%s: %s%%".format(context.getString(R.string.alpha), it.progress)
|
||||||
|
alphaDebouncing?.cancel()
|
||||||
|
alphaDebouncing = GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
delay(150)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
onAlphaChangeListener?.invoke(it.progress)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override fun onStartTrackingTouch(seekBar: IndicatorSeekBar?) {
|
override fun onStartTrackingTouch(seekBar: IndicatorSeekBar?) {
|
||||||
@ -78,7 +100,6 @@ class BottomSheetColorPicker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List
|
// List
|
||||||
|
|
||||||
adapter = SlimAdapter.create()
|
adapter = SlimAdapter.create()
|
||||||
|
|
||||||
loadingJobs.add(GlobalScope.launch(Dispatchers.IO) {
|
loadingJobs.add(GlobalScope.launch(Dispatchers.IO) {
|
||||||
@ -120,14 +141,20 @@ class BottomSheetColorPicker(
|
|||||||
adapter.updateData(colors.toList())
|
adapter.updateData(colors.toList())
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
binding.colorLoader.isVisible = false
|
binding.loader.isVisible = false
|
||||||
binding.listContainer.addView(listBinding.root)
|
binding.listContainer.addView(listBinding.root)
|
||||||
this@BottomSheetColorPicker.behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
|
||||||
binding.listContainer.isVisible = true
|
binding.listContainer.isVisible = true
|
||||||
|
|
||||||
|
val idx = colors.toList().indexOf(getSelected?.invoke())
|
||||||
|
(listBinding.root.layoutManager as GridLayoutManager).scrollToPositionWithOffset(idx,0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
behavior.run {
|
||||||
|
skipCollapsed = true
|
||||||
|
state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
super.show()
|
super.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import android.view.View
|
|||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
@ -107,6 +108,10 @@ open class BottomSheetMenu<T>(context: Context, private val header: String? = nu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
behavior.run {
|
||||||
|
skipCollapsed = true
|
||||||
|
state = com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
super.show()
|
super.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,111 @@
|
|||||||
|
package com.tommasoberlose.anotherwidget.components
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.ColorStateList
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.widget.AppCompatImageView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.view.isVisible
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
import com.google.android.material.card.MaterialCardView
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
|
import com.tommasoberlose.anotherwidget.databinding.BottomSheetMenuHorBinding
|
||||||
|
import com.tommasoberlose.anotherwidget.databinding.BottomSheetMenuListBinding
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.copyToClipboard
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isClipboardColor
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.pasteFromClipboard
|
||||||
|
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||||
|
import com.warkiz.widget.IndicatorSeekBar
|
||||||
|
import com.warkiz.widget.OnSeekChangeListener
|
||||||
|
import com.warkiz.widget.SeekParams
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import net.idik.lib.slimadapter.SlimAdapter
|
||||||
|
|
||||||
|
class BottomSheetPicker<T>(
|
||||||
|
context: Context,
|
||||||
|
private val items: List<MenuItem<T>> = arrayListOf(),
|
||||||
|
private val getSelected: (() -> T)? = null,
|
||||||
|
private val header: String? = null,
|
||||||
|
private val onItemSelected: ((selectedValue: T?) -> Unit)? = null,
|
||||||
|
) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
|
||||||
|
|
||||||
|
private var loadingJobs: ArrayList<Job> = ArrayList()
|
||||||
|
private lateinit var adapter: SlimAdapter
|
||||||
|
|
||||||
|
private var binding: BottomSheetMenuHorBinding = BottomSheetMenuHorBinding.inflate(
|
||||||
|
LayoutInflater.from(context))
|
||||||
|
private var listBinding: BottomSheetMenuListBinding = BottomSheetMenuListBinding.inflate(
|
||||||
|
LayoutInflater.from(context))
|
||||||
|
|
||||||
|
override fun show() {
|
||||||
|
window?.setDimAmount(0f)
|
||||||
|
|
||||||
|
// Header
|
||||||
|
binding.header.isVisible = header != null
|
||||||
|
binding.headerText.text = header ?: ""
|
||||||
|
|
||||||
|
// Alpha
|
||||||
|
binding.alphaSelectorContainer.isVisible = false
|
||||||
|
binding.actionContainer.isVisible = false
|
||||||
|
|
||||||
|
// List
|
||||||
|
adapter = SlimAdapter.create()
|
||||||
|
|
||||||
|
loadingJobs.add(GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
listBinding.root.setHasFixedSize(true)
|
||||||
|
val mLayoutManager = LinearLayoutManager(context)
|
||||||
|
listBinding.root.layoutManager = mLayoutManager
|
||||||
|
|
||||||
|
adapter
|
||||||
|
.register<Int>(R.layout.bottom_sheet_menu_item) { position, injector ->
|
||||||
|
val item = items[position]
|
||||||
|
val isSelected = item.value == getSelected?.invoke()
|
||||||
|
injector
|
||||||
|
.text(R.id.label, item.title)
|
||||||
|
.textColor(R.id.label, ContextCompat.getColor(context, if (isSelected) R.color.colorAccent else R.color.colorSecondaryText))
|
||||||
|
.selected(R.id.item, isSelected)
|
||||||
|
.clicked(R.id.item) {
|
||||||
|
val oldIdx = items.toList().indexOfFirst { it.value == getSelected?.invoke() }
|
||||||
|
onItemSelected?.invoke(item.value)
|
||||||
|
adapter.notifyItemChanged(position)
|
||||||
|
adapter.notifyItemChanged(oldIdx)
|
||||||
|
(listBinding.root.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(position,0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.attachTo(listBinding.root)
|
||||||
|
|
||||||
|
adapter.updateData((items.indices).toList())
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
binding.loader.isVisible = false
|
||||||
|
binding.listContainer.addView(listBinding.root)
|
||||||
|
binding.listContainer.isVisible = true
|
||||||
|
|
||||||
|
val idx = items.toList().indexOfFirst { it.value == getSelected?.invoke() }
|
||||||
|
(listBinding.root.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(idx,0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
setContentView(binding.root)
|
||||||
|
behavior.run {
|
||||||
|
skipCollapsed = true
|
||||||
|
state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
|
super.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
loadingJobs.forEach { it.cancel() }
|
||||||
|
super.onStop()
|
||||||
|
}
|
||||||
|
|
||||||
|
class MenuItem<T>(val title: String, val value: T? = null)
|
||||||
|
|
||||||
|
}
|
@ -61,5 +61,9 @@ class BottomSheetWeatherProviderSettings(context: Context, callback: () -> Unit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
behavior.run {
|
||||||
|
skipCollapsed = true
|
||||||
|
state = com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,5 +26,9 @@ class CustomNotesDialog(context: Context, callback: (() -> Unit)?) : BottomSheet
|
|||||||
binding.notes.requestFocus()
|
binding.notes.requestFocus()
|
||||||
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
behavior.run {
|
||||||
|
skipCollapsed = true
|
||||||
|
state = com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -51,6 +51,7 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_title)
|
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_title)
|
||||||
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_title)
|
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_title)
|
||||||
Constants.GlanceProviderId.EVENTS -> context.getString(R.string.settings_show_events_as_glance_provider_title)
|
Constants.GlanceProviderId.EVENTS -> context.getString(R.string.settings_show_events_as_glance_provider_title)
|
||||||
|
Constants.GlanceProviderId.WEATHER -> context.getString(R.string.settings_show_weather_as_glance_provider_title)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SUBTITLE*/
|
/* SUBTITLE*/
|
||||||
@ -63,6 +64,7 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_subtitle)
|
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_subtitle)
|
||||||
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_subtitle)
|
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_subtitle)
|
||||||
Constants.GlanceProviderId.EVENTS -> context.getString(R.string.settings_show_events_as_glance_provider_subtitle)
|
Constants.GlanceProviderId.EVENTS -> context.getString(R.string.settings_show_events_as_glance_provider_subtitle)
|
||||||
|
Constants.GlanceProviderId.WEATHER -> context.getString(R.string.settings_show_weather_as_glance_provider_subtitle)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SONG */
|
/* SONG */
|
||||||
@ -140,6 +142,13 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
checkCalendarConfig()
|
checkCalendarConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* WEATHER */
|
||||||
|
if (provider == Constants.GlanceProviderId.WEATHER) {
|
||||||
|
binding.header.isVisible = false
|
||||||
|
binding.divider.isVisible = false
|
||||||
|
checkWeatherConfig()
|
||||||
|
}
|
||||||
|
|
||||||
/* TOGGLE */
|
/* TOGGLE */
|
||||||
binding.providerSwitch.setCheckedImmediatelyNoEvent(when (provider) {
|
binding.providerSwitch.setCheckedImmediatelyNoEvent(when (provider) {
|
||||||
Constants.GlanceProviderId.PLAYING_SONG -> Preferences.showMusic
|
Constants.GlanceProviderId.PLAYING_SONG -> Preferences.showMusic
|
||||||
@ -150,6 +159,7 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
Constants.GlanceProviderId.NOTIFICATIONS -> Preferences.showNotifications
|
Constants.GlanceProviderId.NOTIFICATIONS -> Preferences.showNotifications
|
||||||
Constants.GlanceProviderId.GREETINGS -> Preferences.showGreetings
|
Constants.GlanceProviderId.GREETINGS -> Preferences.showGreetings
|
||||||
Constants.GlanceProviderId.EVENTS -> Preferences.showEventsAsGlanceProvider
|
Constants.GlanceProviderId.EVENTS -> Preferences.showEventsAsGlanceProvider
|
||||||
|
Constants.GlanceProviderId.WEATHER -> Preferences.showWeatherAsGlanceProvider
|
||||||
})
|
})
|
||||||
|
|
||||||
var job: Job? = null
|
var job: Job? = null
|
||||||
@ -208,6 +218,9 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
Constants.GlanceProviderId.EVENTS -> {
|
Constants.GlanceProviderId.EVENTS -> {
|
||||||
Preferences.showEventsAsGlanceProvider = isChecked
|
Preferences.showEventsAsGlanceProvider = isChecked
|
||||||
}
|
}
|
||||||
|
Constants.GlanceProviderId.WEATHER -> {
|
||||||
|
Preferences.showWeatherAsGlanceProvider = isChecked
|
||||||
|
}
|
||||||
else -> {
|
else -> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,10 +230,16 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
}
|
}
|
||||||
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
behavior.run {
|
||||||
|
skipCollapsed = true
|
||||||
|
state = com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
super.show()
|
super.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkNextAlarm() {
|
private fun checkNextAlarm() {
|
||||||
|
if (!Preferences.showNextAlarm)
|
||||||
|
AlarmHelper.clearTimeout(context)
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
val alarm = nextAlarmClock
|
val alarm = nextAlarmClock
|
||||||
if (alarm != null && alarm.showIntent != null) {
|
if (alarm != null && alarm.showIntent != null) {
|
||||||
@ -255,6 +274,19 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkWeatherConfig() {
|
||||||
|
if (!Preferences.showWeather || (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-") || Preferences.weatherProviderLocationError != "") {
|
||||||
|
binding.warningContainer.isVisible = true
|
||||||
|
binding.warningTitle.text = context.getString(R.string.settings_show_weather_as_glance_provider_error)
|
||||||
|
binding.warningContainer.setOnClickListener {
|
||||||
|
dismiss()
|
||||||
|
EventBus.getDefault().post(MainFragment.ChangeTabEvent(1))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
binding.warningContainer.isVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkNotificationPermission() {
|
private fun checkNotificationPermission() {
|
||||||
when {
|
when {
|
||||||
ActiveNotificationsHelper.checkNotificationAccess(context) -> {
|
ActiveNotificationsHelper.checkNotificationAccess(context) -> {
|
||||||
|
@ -50,6 +50,10 @@ class IconPackSelector(context: Context, private val header: String? = null) : B
|
|||||||
binding.menu.addView(itemBinding.root)
|
binding.menu.addView(itemBinding.root)
|
||||||
}
|
}
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
behavior.run {
|
||||||
|
skipCollapsed = true
|
||||||
|
state = com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
super.show()
|
super.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -57,6 +57,10 @@ class MaterialBottomSheetDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
behavior.run {
|
||||||
|
skipCollapsed = true
|
||||||
|
state = com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
super.show()
|
super.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ class EventRepository(val context: Context) {
|
|||||||
else -> add(Calendar.HOUR, 6)
|
else -> add(Calendar.HOUR, 6)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val event = if (nextEvent != null && nextEvent.endDate > now && nextEvent.startDate < limit.timeInMillis) {
|
val event = if (nextEvent != null && nextEvent.endDate > now && nextEvent.startDate <= limit.timeInMillis) {
|
||||||
nextEvent
|
nextEvent
|
||||||
} else {
|
} else {
|
||||||
val events = getEvents()
|
val events = getEvents()
|
||||||
@ -105,8 +105,10 @@ class EventRepository(val context: Context) {
|
|||||||
} else {
|
} else {
|
||||||
resetNextEventData()
|
resetNextEventData()
|
||||||
}
|
}
|
||||||
UpdatesReceiver.setUpdates(context)
|
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
|
org.greenrobot.eventbus.EventBus.getDefault().post(
|
||||||
|
com.tommasoberlose.anotherwidget.ui.fragments.MainFragment.UpdateUiMessageEvent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun goToPreviousEvent() {
|
fun goToPreviousEvent() {
|
||||||
@ -121,8 +123,10 @@ class EventRepository(val context: Context) {
|
|||||||
} else {
|
} else {
|
||||||
resetNextEventData()
|
resetNextEventData()
|
||||||
}
|
}
|
||||||
UpdatesReceiver.setUpdates(context)
|
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
|
org.greenrobot.eventbus.EventBus.getDefault().post(
|
||||||
|
com.tommasoberlose.anotherwidget.ui.fragments.MainFragment.UpdateUiMessageEvent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFutureEvents(): List<Event> {
|
fun getFutureEvents(): List<Event> {
|
||||||
|
@ -23,6 +23,13 @@ object Constants {
|
|||||||
LARGE(3)
|
LARGE(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class Dimension(val rawValue: Float) {
|
||||||
|
NONE(0f),
|
||||||
|
SMALL(8f),
|
||||||
|
MEDIUM(16f),
|
||||||
|
LARGE(24f)
|
||||||
|
}
|
||||||
|
|
||||||
enum class GlanceProviderId(val id: String) {
|
enum class GlanceProviderId(val id: String) {
|
||||||
PLAYING_SONG("PLAYING_SONG"),
|
PLAYING_SONG("PLAYING_SONG"),
|
||||||
NEXT_CLOCK_ALARM("NEXT_CLOCK_ALARM"),
|
NEXT_CLOCK_ALARM("NEXT_CLOCK_ALARM"),
|
||||||
@ -31,7 +38,8 @@ object Constants {
|
|||||||
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS"),
|
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS"),
|
||||||
NOTIFICATIONS("NOTIFICATIONS"),
|
NOTIFICATIONS("NOTIFICATIONS"),
|
||||||
GREETINGS("GREETINGS"),
|
GREETINGS("GREETINGS"),
|
||||||
EVENTS("EVENTS");
|
EVENTS("EVENTS"),
|
||||||
|
WEATHER("WEATHER");
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val map = GlanceProviderId.values().associateBy(GlanceProviderId::id)
|
private val map = GlanceProviderId.values().associateBy(GlanceProviderId::id)
|
||||||
@ -83,7 +91,7 @@ object Constants {
|
|||||||
|
|
||||||
enum class WidgetAlign(val rawValue: Int) {
|
enum class WidgetAlign(val rawValue: Int) {
|
||||||
LEFT(0),
|
LEFT(0),
|
||||||
// RIGHT(1),
|
RIGHT(1),
|
||||||
CENTER(2)
|
CENTER(2)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -84,14 +84,18 @@ object Preferences : KotprefModel() {
|
|||||||
|
|
||||||
var weatherIconPack by intPref(default = Constants.WeatherIconPack.DEFAULT.rawValue)
|
var weatherIconPack by intPref(default = Constants.WeatherIconPack.DEFAULT.rawValue)
|
||||||
|
|
||||||
|
// UI
|
||||||
|
var widgetMargin by floatPref(default = Constants.Dimension.SMALL.rawValue)
|
||||||
|
var widgetPadding by floatPref(default = Constants.Dimension.SMALL.rawValue)
|
||||||
|
|
||||||
// Clock
|
// Clock
|
||||||
var altTimezoneLabel by stringPref(default = "")
|
var altTimezoneLabel by stringPref(default = "")
|
||||||
var altTimezoneId by stringPref(default = "")
|
var altTimezoneId by stringPref(default = "")
|
||||||
|
|
||||||
// Global
|
// Global
|
||||||
var textMainSize by floatPref(key = "PREF_TEXT_MAIN_SIZE", default = 26f)
|
var textMainSize by floatPref(key = "PREF_TEXT_MAIN_SIZE", default = 24f)
|
||||||
var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 18f)
|
var textSecondSize by floatPref(key = "PREF_TEXT_SECOND_SIZE", default = 16f)
|
||||||
var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 90f)
|
var clockTextSize by floatPref(key = "PREF_TEXT_CLOCK_SIZE", default = 72f)
|
||||||
var clockBottomMargin by intPref(default = Constants.ClockBottomMargin.MEDIUM.rawValue)
|
var clockBottomMargin by intPref(default = Constants.ClockBottomMargin.MEDIUM.rawValue)
|
||||||
var secondRowTopMargin by intPref(default = Constants.SecondRowTopMargin.NONE.rawValue)
|
var secondRowTopMargin by intPref(default = Constants.SecondRowTopMargin.NONE.rawValue)
|
||||||
var showClock by booleanPref(key = "PREF_SHOW_CLOCK", default = false)
|
var showClock by booleanPref(key = "PREF_SHOW_CLOCK", default = false)
|
||||||
@ -110,6 +114,7 @@ object Preferences : KotprefModel() {
|
|||||||
var customFontName by stringPref(default = "")
|
var customFontName by stringPref(default = "")
|
||||||
var customFontVariant by stringPref(default = "regular")
|
var customFontVariant by stringPref(default = "regular")
|
||||||
var showNextEvent by booleanPref(key = "PREF_SHOW_NEXT_EVENT", default = true)
|
var showNextEvent by booleanPref(key = "PREF_SHOW_NEXT_EVENT", default = true)
|
||||||
|
var showNextEventOnMultipleLines by booleanPref(default = false)
|
||||||
|
|
||||||
var showDividers by booleanPref(default = true)
|
var showDividers by booleanPref(default = true)
|
||||||
|
|
||||||
@ -148,6 +153,7 @@ object Preferences : KotprefModel() {
|
|||||||
var appNotificationsFilter by stringPref(default = "")
|
var appNotificationsFilter by stringPref(default = "")
|
||||||
|
|
||||||
var showEventsAsGlanceProvider by booleanPref(default = false)
|
var showEventsAsGlanceProvider by booleanPref(default = false)
|
||||||
|
var showWeatherAsGlanceProvider by booleanPref(default = false)
|
||||||
|
|
||||||
// Integrations
|
// Integrations
|
||||||
var installedIntegrations by intPref(default = 0)
|
var installedIntegrations by intPref(default = 0)
|
||||||
|
@ -44,7 +44,6 @@ object AlarmHelper {
|
|||||||
val intent = Intent(context, UpdatesReceiver::class.java).apply {
|
val intent = Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
action = Actions.ACTION_ALARM_UPDATE
|
action = Actions.ACTION_ALARM_UPDATE
|
||||||
}
|
}
|
||||||
cancel(PendingIntent.getBroadcast(context, ALARM_UPDATE_ID, intent, 0))
|
|
||||||
setExact(
|
setExact(
|
||||||
AlarmManager.RTC,
|
AlarmManager.RTC,
|
||||||
trigger,
|
trigger,
|
||||||
@ -58,5 +57,14 @@ object AlarmHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun clearTimeout(context: Context) {
|
||||||
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
|
val intent = Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_ALARM_UPDATE
|
||||||
|
}
|
||||||
|
cancel(PendingIntent.getBroadcast(context, ALARM_UPDATE_ID, intent, 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private const val ALARM_UPDATE_ID = 24953
|
private const val ALARM_UPDATE_ID = 24953
|
||||||
}
|
}
|
@ -44,8 +44,8 @@ object BitmapHelper {
|
|||||||
FirebaseCrashlytics.getInstance().setCustomKey("HEIGHT SPEC", measuredHeight)
|
FirebaseCrashlytics.getInstance().setCustomKey("HEIGHT SPEC", measuredHeight)
|
||||||
FirebaseCrashlytics.getInstance().setCustomKey("VIEW measuredWidth", view.measuredWidth)
|
FirebaseCrashlytics.getInstance().setCustomKey("VIEW measuredWidth", view.measuredWidth)
|
||||||
FirebaseCrashlytics.getInstance().setCustomKey("VIEW measuredHeight", view.measuredHeight)
|
FirebaseCrashlytics.getInstance().setCustomKey("VIEW measuredHeight", view.measuredHeight)
|
||||||
FirebaseCrashlytics.getInstance().setCustomKey("WIDGET final width", measuredWidth)
|
FirebaseCrashlytics.getInstance().setCustomKey("WIDGET final width", widgetWidth)
|
||||||
FirebaseCrashlytics.getInstance().setCustomKey("WIDGET final height", view.measuredHeight)
|
FirebaseCrashlytics.getInstance().setCustomKey("WIDGET final height", widgetHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
@ -58,7 +58,7 @@ object BitmapHelper {
|
|||||||
//Bind a canvas to it
|
//Bind a canvas to it
|
||||||
val canvas = Canvas(btm)
|
val canvas = Canvas(btm)
|
||||||
// draw the view on the canvas
|
// draw the view on the canvas
|
||||||
view.layout(0, 0, measuredWidth, measuredHeight)
|
view.layout(0, 0, widgetWidth, widgetHeight)
|
||||||
view.draw(canvas)
|
view.draw(canvas)
|
||||||
//return the bitmap
|
//return the bitmap
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,20 @@
|
|||||||
package com.tommasoberlose.anotherwidget.helpers
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Context.CLIPBOARD_SERVICE
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.toast
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
||||||
object ColorHelper {
|
object ColorHelper {
|
||||||
fun getFontColor(isDark: Boolean): Int {
|
fun getFontColor(isDark: Boolean): Int {
|
||||||
return try {
|
return try {
|
||||||
@ -144,4 +154,40 @@ object ColorHelper {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("DefaultLocale")
|
||||||
|
fun Context.copyToClipboard(color: Int?, alpha: Int) {
|
||||||
|
if (color == null) return toast(getString(R.string.error_copy_color))
|
||||||
|
with(getSystemService(CLIPBOARD_SERVICE) as ClipboardManager) {
|
||||||
|
try {
|
||||||
|
val colorString = Integer.toHexString(color)
|
||||||
|
val clip = "#%s%s".format(
|
||||||
|
alpha.toHexValue(),
|
||||||
|
if (colorString.length > 6) colorString.substring(2) else colorString
|
||||||
|
).toUpperCase()
|
||||||
|
setPrimaryClip(ClipData.newPlainText(clip, clip))
|
||||||
|
toast(getString(R.string.color_copied))
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
toast(getString(R.string.error_copy_color))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.isClipboardColor(): Boolean {
|
||||||
|
with(getSystemService(CLIPBOARD_SERVICE) as ClipboardManager) {
|
||||||
|
return try { primaryClip?.getItemAt(0)?.text?.toString()?.isColor() ?: false } catch (ex: Exception) { false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.pasteFromClipboard(pasteColor: (color: String, alpha: String) -> Unit) {
|
||||||
|
with(getSystemService(CLIPBOARD_SERVICE) as ClipboardManager) {
|
||||||
|
primaryClip?.let {
|
||||||
|
val item = it.getItemAt(0).text.toString().replace("#", "")
|
||||||
|
val color = if (item.length > 6) item.substring(2) else item
|
||||||
|
val alpha = if (item.length > 6) item.substring(0, 2) else "00"
|
||||||
|
pasteColor("#$color", alpha)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -90,6 +90,12 @@ object GlanceProviderHelper {
|
|||||||
R.drawable.round_event_note_24
|
R.drawable.round_event_note_24
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Constants.GlanceProviderId.WEATHER -> {
|
||||||
|
GlanceProvider(providerId.id,
|
||||||
|
context.getString(R.string.settings_show_weather_as_glance_provider_title),
|
||||||
|
R.drawable.round_brightness_5_24
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,10 +114,11 @@ object GlanceProviderHelper {
|
|||||||
(MediaPlayerHelper.isSomeonePlaying(context)) ||
|
(MediaPlayerHelper.isSomeonePlaying(context)) ||
|
||||||
(Preferences.showBatteryCharging && Preferences.isCharging || Preferences.isBatteryLevelLow) ||
|
(Preferences.showBatteryCharging && Preferences.isCharging || Preferences.isBatteryLevelLow) ||
|
||||||
(Preferences.customNotes.isNotEmpty()) ||
|
(Preferences.customNotes.isNotEmpty()) ||
|
||||||
|
(Preferences.showWeatherAsGlanceProvider && Preferences.showWeather && Preferences.weatherIcon != "") ||
|
||||||
(Preferences.showDailySteps && Preferences.googleFitSteps > 0) ||
|
(Preferences.showDailySteps && Preferences.googleFitSteps > 0) ||
|
||||||
(Preferences.showGreetings && GreetingsHelper.showGreetings()) ||
|
(Preferences.showGreetings && GreetingsHelper.showGreetings()) ||
|
||||||
(Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(
|
(Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(
|
||||||
Manifest.permission.READ_CALENDAR) && eventRepository.getNextEvent() != null)
|
Manifest.permission.READ_CALENDAR) && eventRepository.getNextEvent() != null)
|
||||||
)
|
)
|
||||||
eventRepository.close()
|
eventRepository.close()
|
||||||
return showGlance
|
return showGlance
|
||||||
|
@ -73,6 +73,9 @@ object ImageHelper {
|
|||||||
|
|
||||||
allocationIn.destroy()
|
allocationIn.destroy()
|
||||||
allocationOut.destroy()
|
allocationOut.destroy()
|
||||||
|
colorMatrixScript.destroy()
|
||||||
|
blurScript.destroy()
|
||||||
|
//rs.destroy()
|
||||||
|
|
||||||
return bitmap
|
return bitmap
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.tommasoberlose.anotherwidget.helpers
|
package com.tommasoberlose.anotherwidget.helpers
|
||||||
|
|
||||||
|
import android.app.PendingIntent
|
||||||
import android.appwidget.AppWidgetManager
|
import android.appwidget.AppWidgetManager
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.ContentUris
|
import android.content.ContentUris
|
||||||
@ -27,6 +28,13 @@ object IntentHelper {
|
|||||||
const val DO_NOTHING_OPTION = "DO_NOTHING"
|
const val DO_NOTHING_OPTION = "DO_NOTHING"
|
||||||
const val REFRESH_WIDGET_OPTION = "REFRESH_WIDGET"
|
const val REFRESH_WIDGET_OPTION = "REFRESH_WIDGET"
|
||||||
|
|
||||||
|
fun getPendingIntent(context: Context, requestCode: Int, intent: Intent, flags: Int): PendingIntent {
|
||||||
|
return if (intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK == Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
PendingIntent.getActivity(context, requestCode, intent, flags)
|
||||||
|
else
|
||||||
|
PendingIntent.getBroadcast(context, requestCode, intent, 0)
|
||||||
|
}
|
||||||
|
|
||||||
fun getWidgetUpdateIntent(context: Context): Intent {
|
fun getWidgetUpdateIntent(context: Context): Intent {
|
||||||
val widgetManager = AppWidgetManager.getInstance(context)
|
val widgetManager = AppWidgetManager.getInstance(context)
|
||||||
val widgetComponent = ComponentName(context, MainWidget::class.java)
|
val widgetComponent = ComponentName(context, MainWidget::class.java)
|
||||||
@ -40,21 +48,19 @@ object IntentHelper {
|
|||||||
private fun getWidgetRefreshIntent(context: Context): Intent {
|
private fun getWidgetRefreshIntent(context: Context): Intent {
|
||||||
return Intent(context, UpdatesReceiver::class.java).apply {
|
return Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
action = Actions.ACTION_REFRESH
|
action = Actions.ACTION_REFRESH
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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=${Uri.encode(address)}")
|
||||||
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
|
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
|
||||||
mapIntent.`package` = "com.google.android.apps.maps"
|
//mapIntent.`package` = "com.google.android.apps.maps"
|
||||||
|
|
||||||
return if (mapIntent.resolveActivity(context.packageManager) != null) {
|
return if (mapIntent.resolveActivity(context.packageManager) != null) {
|
||||||
mapIntent
|
mapIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
} else {
|
} else {
|
||||||
val map = "http://maps.google.co.in/maps?q=$address"
|
val map = "https://www.google.com/maps/search/?api=1&query=${Uri.encode(address)}"
|
||||||
val i = Intent(Intent.ACTION_VIEW, Uri.parse(map));
|
Intent(Intent.ACTION_VIEW, Uri.parse(map)).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
i
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +68,6 @@ object IntentHelper {
|
|||||||
return when (Preferences.weatherAppPackage) {
|
return when (Preferences.weatherAppPackage) {
|
||||||
DEFAULT_OPTION -> {
|
DEFAULT_OPTION -> {
|
||||||
Intent(Intent.ACTION_VIEW).apply {
|
Intent(Intent.ACTION_VIEW).apply {
|
||||||
addCategory(Intent.CATEGORY_DEFAULT)
|
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
data = Uri.parse("dynact://velour/weather/ProxyActivity")
|
data = Uri.parse("dynact://velour/weather/ProxyActivity")
|
||||||
component = ComponentName("com.google.android.googlequicksearchbox", "com.google.android.apps.gsa.velour.DynamicActivityTrampoline")
|
component = ComponentName("com.google.android.googlequicksearchbox", "com.google.android.apps.gsa.velour.DynamicActivityTrampoline")
|
||||||
@ -89,15 +94,16 @@ object IntentHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCalendarIntent(context: Context): Intent {
|
fun getCalendarIntent(context: Context, time: Long? = null): Intent {
|
||||||
val calendarUri = CalendarContract.CONTENT_URI
|
val calendarUri = CalendarContract.CONTENT_URI
|
||||||
.buildUpon()
|
.buildUpon()
|
||||||
.appendPath("time")
|
.appendPath("time")
|
||||||
.appendPath(Calendar.getInstance().timeInMillis.toString())
|
.appendPath((time ?: Calendar.getInstance().timeInMillis).toString())
|
||||||
.build()
|
.build()
|
||||||
return when (Preferences.calendarAppPackage) {
|
return when (Preferences.calendarAppPackage) {
|
||||||
DEFAULT_OPTION -> {
|
DEFAULT_OPTION -> {
|
||||||
Intent(Intent.ACTION_VIEW).apply {
|
Intent(Intent.ACTION_VIEW).apply {
|
||||||
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
data = calendarUri
|
data = calendarUri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,6 +117,8 @@ object IntentHelper {
|
|||||||
val pm: PackageManager = context.packageManager
|
val pm: PackageManager = context.packageManager
|
||||||
try {
|
try {
|
||||||
pm.getLaunchIntentForPackage(Preferences.calendarAppPackage)!!.apply {
|
pm.getLaunchIntentForPackage(Preferences.calendarAppPackage)!!.apply {
|
||||||
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
action = Intent.ACTION_VIEW
|
action = Intent.ACTION_VIEW
|
||||||
data = calendarUri
|
data = calendarUri
|
||||||
}
|
}
|
||||||
@ -177,7 +185,7 @@ object IntentHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
false -> {
|
false -> {
|
||||||
getCalendarIntent(context)
|
getCalendarIntent(context, e.startDate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,7 +217,7 @@ object IntentHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getBatteryIntent(): Intent {
|
fun getBatteryIntent(): Intent {
|
||||||
return Intent(Intent.ACTION_POWER_USAGE_SUMMARY)
|
return Intent(Intent.ACTION_POWER_USAGE_SUMMARY).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMusicIntent(context: Context): Intent {
|
fun getMusicIntent(context: Context): Intent {
|
||||||
@ -222,6 +230,7 @@ object IntentHelper {
|
|||||||
try {
|
try {
|
||||||
pm.getLaunchIntentForPackage(Preferences.mediaPlayerPackage)!!.apply {
|
pm.getLaunchIntentForPackage(Preferences.mediaPlayerPackage)!!.apply {
|
||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Intent()
|
Intent()
|
||||||
@ -235,6 +244,7 @@ object IntentHelper {
|
|||||||
return try {
|
return try {
|
||||||
pm.getLaunchIntentForPackage("com.google.android.apps.fitness")!!.apply {
|
pm.getLaunchIntentForPackage("com.google.android.apps.fitness")!!.apply {
|
||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Intent()
|
Intent()
|
||||||
@ -246,6 +256,7 @@ object IntentHelper {
|
|||||||
return try {
|
return try {
|
||||||
pm.getLaunchIntentForPackage(Preferences.lastNotificationPackage)!!.apply {
|
pm.getLaunchIntentForPackage(Preferences.lastNotificationPackage)!!.apply {
|
||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Intent()
|
Intent()
|
||||||
|
@ -12,6 +12,7 @@ import com.chibatching.kotpref.bulk
|
|||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.receivers.NotificationListener
|
import com.tommasoberlose.anotherwidget.receivers.NotificationListener
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.ignoreExceptions
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
|
|
||||||
object MediaPlayerHelper {
|
object MediaPlayerHelper {
|
||||||
@ -69,15 +70,24 @@ object MediaPlayerHelper {
|
|||||||
isSomeonePlaying = true
|
isSomeonePlaying = true
|
||||||
if (metadata != null) {
|
if (metadata != null) {
|
||||||
Preferences.bulk {
|
Preferences.bulk {
|
||||||
mediaPlayerTitle =
|
ignoreExceptions {
|
||||||
metadata.getText(MediaMetadata.METADATA_KEY_TITLE)?.toString()
|
mediaPlayerTitle =
|
||||||
?: ""
|
metadata.getText(MediaMetadata.METADATA_KEY_TITLE)
|
||||||
mediaPlayerArtist =
|
?.toString()
|
||||||
metadata.getText(MediaMetadata.METADATA_KEY_ARTIST)?.toString()
|
?: ""
|
||||||
?: ""
|
}
|
||||||
mediaPlayerAlbum =
|
ignoreExceptions {
|
||||||
metadata.getText(MediaMetadata.METADATA_KEY_ALBUM)?.toString()
|
mediaPlayerArtist =
|
||||||
?: ""
|
metadata.getText(MediaMetadata.METADATA_KEY_ARTIST)
|
||||||
|
?.toString()
|
||||||
|
?: ""
|
||||||
|
}
|
||||||
|
ignoreExceptions {
|
||||||
|
mediaPlayerAlbum =
|
||||||
|
metadata.getText(MediaMetadata.METADATA_KEY_ALBUM)
|
||||||
|
?.toString()
|
||||||
|
?: ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,19 +88,17 @@ object SettingsStringHelper {
|
|||||||
fun getDifferenceText(context: Context, now: Long, start: Long): String {
|
fun getDifferenceText(context: Context, now: Long, start: Long): String {
|
||||||
val nowDate = DateTime(now)
|
val nowDate = DateTime(now)
|
||||||
val eventDate = DateTime(start)
|
val eventDate = DateTime(start)
|
||||||
|
val difference = start - now
|
||||||
var difference = start - now
|
|
||||||
difference += 60 * 1000 - (difference % (60 * 1000))
|
|
||||||
|
|
||||||
when {
|
when {
|
||||||
difference <= 0 -> {
|
difference <= 0 -> {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.HIGH.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> {
|
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.HIGH.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) >= 5 -> {
|
||||||
return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 5), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - TimeUnit.MILLISECONDS.toMinutes(difference) % 5), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
||||||
}
|
}
|
||||||
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.DEFAULT.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> {
|
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.DEFAULT.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) >= 15 -> {
|
||||||
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()
|
return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - TimeUnit.MILLISECONDS.toMinutes(difference) % 15), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
||||||
}
|
}
|
||||||
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.LOW.rawValue -> {
|
TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.LOW.rawValue -> {
|
||||||
return context.getString(R.string.soon)
|
return context.getString(R.string.soon)
|
||||||
@ -109,22 +107,7 @@ object SettingsStringHelper {
|
|||||||
return context.getString(R.string.now)
|
return context.getString(R.string.now)
|
||||||
}
|
}
|
||||||
TimeUnit.MILLISECONDS.toHours(difference) < 12 -> {
|
TimeUnit.MILLISECONDS.toHours(difference) < 12 -> {
|
||||||
val minutes = TimeUnit.MILLISECONDS.toMinutes(difference) - 60 * TimeUnit.MILLISECONDS.toHours(difference)
|
return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.HOUR_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString()
|
||||||
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))
|
||||||
@ -143,9 +126,6 @@ object SettingsStringHelper {
|
|||||||
val nowDate = DateTime(now)
|
val nowDate = DateTime(now)
|
||||||
val eventDate = DateTime(start)
|
val eventDate = DateTime(start)
|
||||||
|
|
||||||
var difference = start - now
|
|
||||||
difference += 60 * 1000 - (difference % (60 * 1000))
|
|
||||||
|
|
||||||
return when (eventDate.dayOfYear) {
|
return when (eventDate.dayOfYear) {
|
||||||
nowDate.dayOfYear -> {
|
nowDate.dayOfYear -> {
|
||||||
""
|
""
|
||||||
|
@ -21,11 +21,20 @@ object WeatherHelper {
|
|||||||
|
|
||||||
suspend fun updateWeather(context: Context) {
|
suspend fun updateWeather(context: Context) {
|
||||||
Kotpref.init(context)
|
Kotpref.init(context)
|
||||||
val networkApi = WeatherNetworkApi(context)
|
|
||||||
if (Preferences.customLocationAdd != "") {
|
if (Preferences.customLocationAdd != "") {
|
||||||
networkApi.updateWeather()
|
WeatherNetworkApi(context).updateWeather()
|
||||||
} else if (context.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
|
} else if (context.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) &&
|
||||||
|
(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R ||
|
||||||
|
context.checkGrantedPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION))
|
||||||
|
) {
|
||||||
LocationService.requestNewLocation(context)
|
LocationService.requestNewLocation(context)
|
||||||
|
} else {
|
||||||
|
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_missing_location)
|
||||||
|
Preferences.weatherProviderError = ""
|
||||||
|
removeWeather(context)
|
||||||
|
org.greenrobot.eventbus.EventBus.getDefault().post(
|
||||||
|
com.tommasoberlose.anotherwidget.ui.fragments.MainFragment.UpdateUiMessageEvent()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,6 +322,23 @@ object WeatherHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getWeatherLabel(context: Context, icon: String): String {
|
||||||
|
return when (icon) {
|
||||||
|
"01d", "01n" -> context.getString(R.string.weather_label_clear)
|
||||||
|
"02d", "02n" -> context.getString(R.string.weather_label_partly_cloudy)
|
||||||
|
"03d", "03n" -> context.getString(R.string.weather_label_mostly_cloudy)
|
||||||
|
"04d", "04n" -> context.getString(R.string.weather_label_cloudy_weather)
|
||||||
|
"09d", "09n" -> context.getString(R.string.weather_label_storm_weather)
|
||||||
|
"10d", "10n" -> context.getString(R.string.weather_label_rainy)
|
||||||
|
"11d", "11n" -> context.getString(R.string.weather_label_thunder)
|
||||||
|
"13d", "13n" -> context.getString(R.string.weather_label_snow)
|
||||||
|
"50d", "50n", "82d", "82n" -> context.getString(R.string.weather_label_haze)
|
||||||
|
"80d", "80n" -> context.getString(R.string.weather_label_windy)
|
||||||
|
"81d", "81n" -> context.getString(R.string.weather_label_rain_snow)
|
||||||
|
else -> context.getString(R.string.weather_label_unknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getWeatherGovIcon(iconString: String, isDaytime: Boolean): String = when {
|
fun getWeatherGovIcon(iconString: String, isDaytime: Boolean): String = when {
|
||||||
iconString.contains("skc") -> "01"
|
iconString.contains("skc") -> "01"
|
||||||
iconString.contains("few") -> "02"
|
iconString.contains("few") -> "02"
|
||||||
|
@ -25,8 +25,15 @@ object WidgetHelper {
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
fun getWidgetsSize(widgetId: Int): Pair<Int, Int> {
|
fun getWidgetsSize(widgetId: Int): Pair<Int, Int> {
|
||||||
val width = getWidgetWidth(widgetId)
|
val portrait = context.resources.configuration.orientation == ORIENTATION_PORTRAIT
|
||||||
val height = getWidgetHeight(widgetId)
|
val width = getWidgetSizeInDp(
|
||||||
|
widgetId,
|
||||||
|
if (portrait) AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH else AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH
|
||||||
|
)
|
||||||
|
val height = getWidgetSizeInDp(
|
||||||
|
widgetId,
|
||||||
|
if (portrait) AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT else AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT
|
||||||
|
)
|
||||||
val widthInPx = context.dip(width)
|
val widthInPx = context.dip(width)
|
||||||
val heightInPx = context.dip(height)
|
val heightInPx = context.dip(height)
|
||||||
FirebaseCrashlytics.getInstance().setCustomKey("widthInPx", widthInPx)
|
FirebaseCrashlytics.getInstance().setCustomKey("widthInPx", widthInPx)
|
||||||
@ -63,21 +70,23 @@ object WidgetHelper {
|
|||||||
R.array.com_google_android_gms_fonts_certs
|
R.array.com_google_android_gms_fonts_certs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val handlerThread = HandlerThread("generateView")
|
||||||
val callback = object : FontsContractCompat.FontRequestCallback() {
|
val callback = object : FontsContractCompat.FontRequestCallback() {
|
||||||
override fun onTypefaceRetrieved(typeface: Typeface) {
|
override fun onTypefaceRetrieved(typeface: Typeface) {
|
||||||
|
handlerThread.quit()
|
||||||
function.invoke(typeface)
|
function.invoke(typeface)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTypefaceRequestFailed(reason: Int) {
|
override fun onTypefaceRequestFailed(reason: Int) {
|
||||||
|
handlerThread.quit()
|
||||||
function.invoke(null)
|
function.invoke(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val handlerThread = HandlerThread("generateView")
|
|
||||||
handlerThread.start()
|
handlerThread.start()
|
||||||
if (Looper.myLooper() == null) {
|
//if (Looper.myLooper() == null) {
|
||||||
Looper.prepare()
|
// Looper.prepare()
|
||||||
}
|
//}
|
||||||
|
|
||||||
Handler(handlerThread.looper).run {
|
Handler(handlerThread.looper).run {
|
||||||
FontsContractCompat.requestFont(context, request, callback, this)
|
FontsContractCompat.requestFont(context, request, callback, this)
|
||||||
|
@ -42,6 +42,13 @@ class WeatherNetworkApi(val context: Context) {
|
|||||||
Constants.WeatherProvider.YR -> useYrProvider(context)
|
Constants.WeatherProvider.YR -> useYrProvider(context)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (!Preferences.showWeather)
|
||||||
|
Preferences.weatherProviderError = context.getString(R.string.show_weather_not_visible)
|
||||||
|
else {
|
||||||
|
Preferences.weatherProviderLocationError = context.getString(R.string.weather_provider_error_missing_location)
|
||||||
|
Preferences.weatherProviderError = ""
|
||||||
|
}
|
||||||
|
|
||||||
WeatherHelper.removeWeather(
|
WeatherHelper.removeWeather(
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
@ -13,8 +13,7 @@ class NewCalendarEventReceiver : BroadcastReceiver() {
|
|||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
val eventRepository = EventRepository(context)
|
val eventRepository = EventRepository(context)
|
||||||
when (intent.action) {
|
when (intent.action) {
|
||||||
Intent.ACTION_PROVIDER_CHANGED,
|
Intent.ACTION_PROVIDER_CHANGED -> {
|
||||||
Intent.ACTION_TIME_CHANGED -> {
|
|
||||||
CalendarHelper.updateEventList(context)
|
CalendarHelper.updateEventList(context)
|
||||||
}
|
}
|
||||||
Actions.ACTION_GO_TO_NEXT_EVENT -> {
|
Actions.ACTION_GO_TO_NEXT_EVENT -> {
|
||||||
|
@ -38,6 +38,7 @@ class UpdatesReceiver : BroadcastReceiver() {
|
|||||||
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
|
"com.sec.android.widgetapp.APPWIDGET_RESIZE",
|
||||||
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
|
AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED,
|
||||||
Actions.ACTION_ALARM_UPDATE,
|
Actions.ACTION_ALARM_UPDATE,
|
||||||
|
Actions.ACTION_UPDATE_GREETINGS,
|
||||||
Actions.ACTION_TIME_UPDATE -> {
|
Actions.ACTION_TIME_UPDATE -> {
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
if (intent.hasExtra(EVENT_ID)) {
|
if (intent.hasExtra(EVENT_ID)) {
|
||||||
@ -49,9 +50,6 @@ class UpdatesReceiver : BroadcastReceiver() {
|
|||||||
ActiveNotificationsHelper.clearLastNotification(context)
|
ActiveNotificationsHelper.clearLastNotification(context)
|
||||||
MainWidget.updateWidget(context)
|
MainWidget.updateWidget(context)
|
||||||
}
|
}
|
||||||
Actions.ACTION_UPDATE_GREETINGS -> {
|
|
||||||
MainWidget.updateWidget(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
Actions.ACTION_REFRESH -> {
|
Actions.ACTION_REFRESH -> {
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
@ -67,9 +65,31 @@ class UpdatesReceiver : BroadcastReceiver() {
|
|||||||
const val EVENT_ID = "EVENT_ID"
|
const val EVENT_ID = "EVENT_ID"
|
||||||
|
|
||||||
fun setUpdates(context: Context, eventId: Long? = null) {
|
fun setUpdates(context: Context, eventId: Long? = null) {
|
||||||
|
if (!Preferences.showEvents)
|
||||||
|
return
|
||||||
val eventRepository = EventRepository(context)
|
val eventRepository = EventRepository(context)
|
||||||
if (eventId == null) {
|
if (eventId == null) {
|
||||||
removeUpdates(context)
|
// schedule ACTION_CALENDAR_UPDATE at midnight (ACTION_DATE_CHANGED no longer works)
|
||||||
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
|
setExact(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
Calendar.getInstance().apply {
|
||||||
|
set(Calendar.MILLISECOND, 0)
|
||||||
|
set(Calendar.SECOND, 0)
|
||||||
|
set(Calendar.MINUTE, 0)
|
||||||
|
set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
add(Calendar.DATE, 1)
|
||||||
|
}.timeInMillis,
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
0,
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_CALENDAR_UPDATE
|
||||||
|
},
|
||||||
|
0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
eventRepository.getFutureEvents().forEach { event ->
|
eventRepository.getFutureEvents().forEach { event ->
|
||||||
setEventUpdate(context, event)
|
setEventUpdate(context, event)
|
||||||
@ -84,109 +104,90 @@ class UpdatesReceiver : BroadcastReceiver() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setEventUpdate(context: Context, event: Event) {
|
private fun setEventUpdate(context: Context, event: Event) {
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
val now = Calendar.getInstance().apply {
|
||||||
val now = Calendar.getInstance().apply {
|
set(Calendar.SECOND, 0)
|
||||||
set(Calendar.SECOND, 0)
|
set(Calendar.MILLISECOND, 0)
|
||||||
set(Calendar.MILLISECOND, 0)
|
}
|
||||||
}
|
val diff = Period(now.timeInMillis, event.startDate, org.joda.time.PeriodType.time())
|
||||||
val diff = Period(now.timeInMillis, event.startDate)
|
val limit = when (Preferences.showUntil) {
|
||||||
val limit = when (Preferences.showUntil) {
|
0 -> 1000 * 60 * 60 * 3
|
||||||
0 -> 1000 * 60 * 60 * 3
|
1 -> 1000 * 60 * 60 * 6
|
||||||
1 -> 1000 * 60 * 60 * 6
|
2 -> 1000 * 60 * 60 * 12
|
||||||
2 -> 1000 * 60 * 60 * 12
|
3 -> 1000 * 60 * 60 * 24
|
||||||
3 -> 1000 * 60 * 60 * 24
|
4 -> 1000 * 60 * 60 * 24 * 3
|
||||||
4 -> 1000 * 60 * 60 * 24 * 3
|
5 -> 1000 * 60 * 60 * 24 * 7
|
||||||
5 -> 1000 * 60 * 60 * 24 * 7
|
6 -> 1000 * 60 * 30
|
||||||
6 -> 1000 * 60 * 30
|
7 -> 1000 * 60 * 60
|
||||||
7 -> 1000 * 60 * 60
|
else -> 1000 * 60 * 60 * 6
|
||||||
else -> 1000 * 60 * 60 * 6
|
}
|
||||||
}
|
val fireTime = when {
|
||||||
if (event.startDate <= limit) {
|
event.startDate <= now.timeInMillis
|
||||||
if (event.startDate > now.timeInMillis) {
|
-> event.endDate
|
||||||
// Update the widget every hour till the event
|
event.startDate > now.timeInMillis + limit
|
||||||
if (diff.hours == 0) {
|
-> event.startDate - limit
|
||||||
var minutes = 0
|
!Preferences.showDiffTime
|
||||||
when (Preferences.widgetUpdateFrequency) {
|
-> return
|
||||||
Constants.WidgetUpdateFrequency.DEFAULT.rawValue -> {
|
event.allDay
|
||||||
minutes = when {
|
-> event.startDate
|
||||||
diff.minutes > 50 -> 50
|
diff.hours > 12
|
||||||
diff.minutes > 30 -> 30
|
-> event.startDate - 12 * 1000 * 60 * 60 + 1000 * 60
|
||||||
diff.minutes > 15 -> 15
|
diff.hours > 0
|
||||||
else -> 0
|
-> event.startDate - diff.hours * 1000 * 60 * 60 + 1000 * 60
|
||||||
}
|
else
|
||||||
}
|
-> event.startDate - 1000 * 60 * when (Preferences.widgetUpdateFrequency) {
|
||||||
Constants.WidgetUpdateFrequency.HIGH.rawValue -> {
|
Constants.WidgetUpdateFrequency.DEFAULT.rawValue -> {
|
||||||
minutes = diff.minutes - (diff.minutes % 5)
|
when {
|
||||||
}
|
diff.minutes >= 45 -> 44
|
||||||
|
diff.minutes >= 30 -> 29
|
||||||
|
diff.minutes >= 15 -> 14
|
||||||
|
else -> 0
|
||||||
}
|
}
|
||||||
setExact(
|
|
||||||
AlarmManager.RTC,
|
|
||||||
if (event.startDate - minutes * 1000 * 60 > (now.timeInMillis + 120 * 1000)) event.startDate - 60 * 1000 * minutes else now.timeInMillis + 120000,
|
|
||||||
PendingIntent.getBroadcast(
|
|
||||||
context,
|
|
||||||
event.eventID.toInt(),
|
|
||||||
Intent(context, UpdatesReceiver::class.java).apply {
|
|
||||||
action = Actions.ACTION_TIME_UPDATE
|
|
||||||
putExtra(EVENT_ID, event.eventID)
|
|
||||||
},
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
setExact(
|
|
||||||
AlarmManager.RTC,
|
|
||||||
event.startDate - diff.hours * 1000 * 60 * 60 + if (diff.minutes > 30) (-30) else (+30),
|
|
||||||
PendingIntent.getBroadcast(
|
|
||||||
context,
|
|
||||||
event.eventID.toInt(),
|
|
||||||
Intent(context, UpdatesReceiver::class.java).apply {
|
|
||||||
action = Actions.ACTION_TIME_UPDATE
|
|
||||||
putExtra(EVENT_ID, event.eventID)
|
|
||||||
},
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
Constants.WidgetUpdateFrequency.HIGH.rawValue -> {
|
||||||
// Update the widget one second after the event is finished
|
when {
|
||||||
val fireTime =
|
diff.minutes >= 5 -> diff.minutes - diff.minutes % 5 - 1
|
||||||
if (event.endDate > now.timeInMillis + 120 * 1000) event.endDate else now.timeInMillis + 120000
|
else -> 0
|
||||||
setExact(
|
}
|
||||||
AlarmManager.RTC,
|
}
|
||||||
fireTime,
|
else -> 0
|
||||||
PendingIntent.getBroadcast(
|
|
||||||
context,
|
|
||||||
event.eventID.toInt(),
|
|
||||||
Intent(context, UpdatesReceiver::class.java).apply {
|
|
||||||
action = Actions.ACTION_TIME_UPDATE
|
|
||||||
},
|
|
||||||
0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
setExact(
|
// no need to schedule updates after the next ACTION_CALENDAR_UPDATE
|
||||||
AlarmManager.RTC,
|
if (Calendar.getInstance().apply {
|
||||||
if (event.startDate - limit > now.timeInMillis + 120 * 1000) event.startDate - limit else now.timeInMillis + 120000,
|
set(Calendar.MILLISECOND, 0)
|
||||||
PendingIntent.getBroadcast(
|
set(Calendar.SECOND, 0)
|
||||||
context,
|
set(Calendar.MINUTE, 0)
|
||||||
event.eventID.toInt(),
|
set(Calendar.HOUR_OF_DAY, 0)
|
||||||
Intent(context, UpdatesReceiver::class.java).apply {
|
add(Calendar.DATE, 1)
|
||||||
action = Actions.ACTION_TIME_UPDATE
|
}.timeInMillis <= fireTime) return
|
||||||
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
|
setExact(
|
||||||
|
AlarmManager.RTC,
|
||||||
|
fireTime.coerceAtLeast(now.timeInMillis + 1000 * 60),
|
||||||
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
event.eventID.toInt(),
|
||||||
|
Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_TIME_UPDATE
|
||||||
|
if (event.startDate > now.timeInMillis)
|
||||||
putExtra(EVENT_ID, event.eventID)
|
putExtra(EVENT_ID, event.eventID)
|
||||||
},
|
},
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
PendingIntent.FLAG_UPDATE_CURRENT
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeUpdates(context: Context) {
|
fun removeUpdates(context: Context) {
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
|
cancel(PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_CALENDAR_UPDATE
|
||||||
|
}, 0))
|
||||||
val eventRepository = EventRepository(context)
|
val eventRepository = EventRepository(context)
|
||||||
eventRepository.getFutureEvents().forEach {
|
eventRepository.getFutureEvents().forEach {
|
||||||
cancel(PendingIntent.getBroadcast(context, it.eventID.toInt(), Intent(context, UpdatesReceiver::class.java), 0))
|
cancel(PendingIntent.getBroadcast(context, it.eventID.toInt(), Intent(context, UpdatesReceiver::class.java).apply {
|
||||||
|
action = Actions.ACTION_TIME_UPDATE
|
||||||
|
}, 0))
|
||||||
}
|
}
|
||||||
eventRepository.close()
|
eventRepository.close()
|
||||||
}
|
}
|
||||||
|
@ -22,21 +22,14 @@ class WeatherReceiver : BroadcastReceiver() {
|
|||||||
Intent.ACTION_MY_PACKAGE_REPLACED,
|
Intent.ACTION_MY_PACKAGE_REPLACED,
|
||||||
Intent.ACTION_TIMEZONE_CHANGED,
|
Intent.ACTION_TIMEZONE_CHANGED,
|
||||||
Intent.ACTION_LOCALE_CHANGED,
|
Intent.ACTION_LOCALE_CHANGED,
|
||||||
Intent.ACTION_TIME_CHANGED -> setUpdates(context)
|
Intent.ACTION_TIME_CHANGED,
|
||||||
|
Actions.ACTION_WEATHER_UPDATE -> setUpdates(context)
|
||||||
Actions.ACTION_WEATHER_UPDATE -> {
|
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
|
||||||
WeatherHelper.updateWeather(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val MINUTE = 60 * 1000L
|
private const val MINUTE = 60 * 1000L
|
||||||
fun setUpdates(context: Context) {
|
fun setUpdates(context: Context) {
|
||||||
removeUpdates(context)
|
|
||||||
|
|
||||||
if (Preferences.showWeather) {
|
if (Preferences.showWeather) {
|
||||||
val interval = MINUTE * when (Preferences.weatherRefreshPeriod) {
|
val interval = MINUTE * when (Preferences.weatherRefreshPeriod) {
|
||||||
0 -> 30
|
0 -> 30
|
||||||
@ -48,13 +41,15 @@ class WeatherReceiver : BroadcastReceiver() {
|
|||||||
else -> 60
|
else -> 60
|
||||||
}
|
}
|
||||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||||
setRepeating(
|
setExact(
|
||||||
AlarmManager.RTC,
|
AlarmManager.RTC,
|
||||||
Calendar.getInstance().timeInMillis,
|
System.currentTimeMillis() + interval,
|
||||||
interval,
|
|
||||||
PendingIntent.getBroadcast(context, 0, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0)
|
PendingIntent.getBroadcast(context, 0, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
WeatherHelper.updateWeather(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,14 +16,15 @@ class WidgetClickListenerReceiver : BroadcastReceiver() {
|
|||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
if (intent.action == Actions.ACTION_OPEN_WEATHER_INTENT) {
|
if (intent.action == Actions.ACTION_OPEN_WEATHER_INTENT) {
|
||||||
try {
|
try {
|
||||||
if (Preferences.weatherAppPackage == IntentHelper.REFRESH_WIDGET_OPTION) {
|
IntentHelper.getWeatherIntent(context).run {
|
||||||
context.sendBroadcast(IntentHelper.getWeatherIntent(context))
|
if (flags and Intent.FLAG_ACTIVITY_NEW_TASK == Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
} else {
|
context.startActivity(this)
|
||||||
context.startActivity(IntentHelper.getWeatherIntent(context))
|
else
|
||||||
|
context.sendBroadcast(this)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
val uri = Uri.parse("http://www.google.com/search?q=weather")
|
val uri = Uri.parse("https://www.google.com/search?q=weather")
|
||||||
val i = Intent(Intent.ACTION_VIEW, uri)
|
val i = Intent(Intent.ACTION_VIEW, uri)
|
||||||
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
i.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
try {
|
try {
|
||||||
|
@ -18,6 +18,7 @@ import com.tommasoberlose.anotherwidget.global.Preferences
|
|||||||
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import java.lang.Exception
|
import java.lang.Exception
|
||||||
@ -37,12 +38,31 @@ class LocationService : Service() {
|
|||||||
startForeground(LOCATION_ACCESS_NOTIFICATION_ID, getLocationAccessNotification())
|
startForeground(LOCATION_ACCESS_NOTIFICATION_ID, getLocationAccessNotification())
|
||||||
job?.cancel()
|
job?.cancel()
|
||||||
job = GlobalScope.launch(Dispatchers.IO) {
|
job = GlobalScope.launch(Dispatchers.IO) {
|
||||||
if (ActivityCompat.checkSelfPermission(
|
if (checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) &&
|
||||||
this@LocationService,
|
(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R ||
|
||||||
Manifest.permission.ACCESS_FINE_LOCATION
|
checkGrantedPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION))
|
||||||
) == PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
) {
|
||||||
LocationServices.getFusedLocationProviderClient(this@LocationService).lastLocation.addOnCompleteListener { task ->
|
if (com.google.android.gms.common.GoogleApiAvailability.getInstance()
|
||||||
|
.isGooglePlayServicesAvailable(this@LocationService)
|
||||||
|
== com.google.android.gms.common.ConnectionResult.SUCCESS
|
||||||
|
) {
|
||||||
|
LocationServices.getFusedLocationProviderClient(this@LocationService).lastLocation
|
||||||
|
} else {
|
||||||
|
val lm = getSystemService(LOCATION_SERVICE) as android.location.LocationManager
|
||||||
|
var location: android.location.Location? = null
|
||||||
|
for (provider in arrayOf(
|
||||||
|
"fused", // LocationManager.FUSED_PROVIDER,
|
||||||
|
android.location.LocationManager.GPS_PROVIDER,
|
||||||
|
android.location.LocationManager.NETWORK_PROVIDER,
|
||||||
|
android.location.LocationManager.PASSIVE_PROVIDER
|
||||||
|
)) {
|
||||||
|
if (lm.isProviderEnabled(provider)) {
|
||||||
|
location = lm.getLastKnownLocation(provider)
|
||||||
|
if (location != null) break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
com.google.android.gms.tasks.Tasks.forResult(location)
|
||||||
|
}.addOnCompleteListener { task ->
|
||||||
val networkApi = WeatherNetworkApi(this@LocationService)
|
val networkApi = WeatherNetworkApi(this@LocationService)
|
||||||
if (task.isSuccessful) {
|
if (task.isSuccessful) {
|
||||||
val location = task.result
|
val location = task.result
|
||||||
|
@ -55,18 +55,20 @@ class UpdateCalendarService : Service() {
|
|||||||
job?.cancel()
|
job?.cancel()
|
||||||
job = GlobalScope.launch(Dispatchers.IO) {
|
job = GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
|
||||||
|
UpdatesReceiver.removeUpdates(this@UpdateCalendarService)
|
||||||
|
|
||||||
val eventRepository = EventRepository(this@UpdateCalendarService)
|
val eventRepository = EventRepository(this@UpdateCalendarService)
|
||||||
if (Preferences.showEvents) {
|
if (Preferences.showEvents) {
|
||||||
val eventList = ArrayList<Event>()
|
val eventList = ArrayList<Event>()
|
||||||
|
|
||||||
|
// fetch all events from now to next ACTION_CALENDAR_UPDATE + limit
|
||||||
val now = Calendar.getInstance()
|
val now = Calendar.getInstance()
|
||||||
val begin = Calendar.getInstance().apply {
|
val limit = Calendar.getInstance().apply {
|
||||||
set(Calendar.MILLISECOND, 0)
|
set(Calendar.MILLISECOND, 0)
|
||||||
set(Calendar.SECOND, 0)
|
set(Calendar.SECOND, 0)
|
||||||
set(Calendar.MINUTE, 0)
|
set(Calendar.MINUTE, 0)
|
||||||
set(Calendar.HOUR_OF_DAY, 0)
|
set(Calendar.HOUR_OF_DAY, 0)
|
||||||
}
|
add(Calendar.DATE, 1)
|
||||||
val limit = Calendar.getInstance().apply {
|
|
||||||
when (Preferences.showUntil) {
|
when (Preferences.showUntil) {
|
||||||
0 -> add(Calendar.HOUR, 3)
|
0 -> add(Calendar.HOUR, 3)
|
||||||
1 -> add(Calendar.HOUR, 6)
|
1 -> add(Calendar.HOUR, 6)
|
||||||
@ -85,29 +87,37 @@ class UpdateCalendarService : Service() {
|
|||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
eventRepository.resetNextEventData()
|
eventRepository.resetNextEventData()
|
||||||
|
eventRepository.clearEvents()
|
||||||
|
Preferences.showEvents = false
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
val provider = CalendarProvider(this@UpdateCalendarService)
|
val provider = CalendarProvider(this@UpdateCalendarService)
|
||||||
val data = provider.getInstances(begin.timeInMillis, limit.timeInMillis)
|
// apply time zone offset to correctly fetch all-day events
|
||||||
|
val data = provider.getInstances(
|
||||||
|
now.timeInMillis + now.timeZone.getOffset(now.timeInMillis).coerceAtMost(0),
|
||||||
|
limit.timeInMillis + limit.timeZone.getOffset(limit.timeInMillis).coerceAtLeast(0)
|
||||||
|
)
|
||||||
if (data != null) {
|
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 && now.timeInMillis < instance.end && !CalendarHelper.getFilteredCalendarIdList()
|
if (e == null || e.deleted || CalendarHelper.getFilteredCalendarIdList().contains(e.calendarId))
|
||||||
.contains(e.calendarId)
|
continue
|
||||||
) {
|
if (e.allDay) {
|
||||||
if (e.allDay) {
|
val start = Calendar.getInstance()
|
||||||
val start = Calendar.getInstance()
|
start.timeInMillis = instance.begin
|
||||||
start.timeInMillis = instance.begin
|
val end = Calendar.getInstance()
|
||||||
val end = Calendar.getInstance()
|
end.timeInMillis = instance.end
|
||||||
end.timeInMillis = instance.end
|
instance.begin =
|
||||||
instance.begin =
|
start.timeInMillis - start.timeZone.getOffset(start.timeInMillis)
|
||||||
start.timeInMillis - start.timeZone.getOffset(start.timeInMillis)
|
instance.end =
|
||||||
instance.end =
|
end.timeInMillis - end.timeZone.getOffset(end.timeInMillis)
|
||||||
end.timeInMillis - end.timeZone.getOffset(end.timeInMillis)
|
}
|
||||||
}
|
if (instance.begin <= limit.timeInMillis && now.timeInMillis < instance.end) {
|
||||||
|
/* Following check may result in "fake" all-day events with
|
||||||
|
* non-UTC start/end time, and therefore cannot be found by
|
||||||
|
* Calendar when tapped to open details.
|
||||||
// Check all day events
|
// Check all day events
|
||||||
val startDate = Calendar.getInstance()
|
val startDate = Calendar.getInstance()
|
||||||
startDate.timeInMillis = instance.begin
|
startDate.timeInMillis = instance.begin
|
||||||
@ -124,6 +134,7 @@ class UpdateCalendarService : Service() {
|
|||||||
&& endDate.get(Calendar.MINUTE) == 0
|
&& endDate.get(Calendar.MINUTE) == 0
|
||||||
&& endDate.get(Calendar.HOUR_OF_DAY) == 0
|
&& endDate.get(Calendar.HOUR_OF_DAY) == 0
|
||||||
)
|
)
|
||||||
|
*/
|
||||||
|
|
||||||
eventList.add(
|
eventList.add(
|
||||||
Event(
|
Event(
|
||||||
@ -133,7 +144,7 @@ class UpdateCalendarService : Service() {
|
|||||||
startDate = instance.begin,
|
startDate = instance.begin,
|
||||||
endDate = instance.end,
|
endDate = instance.end,
|
||||||
calendarID = e.calendarId.toInt(),
|
calendarID = e.calendarId.toInt(),
|
||||||
allDay = isAllDay,
|
allDay = e.allDay,
|
||||||
address = e.eventLocation ?: "",
|
address = e.eventLocation ?: "",
|
||||||
selfAttendeeStatus = e.selfAttendeeStatus.toInt(),
|
selfAttendeeStatus = e.selfAttendeeStatus.toInt(),
|
||||||
availability = e.availability
|
availability = e.availability
|
||||||
@ -164,13 +175,14 @@ class UpdateCalendarService : Service() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eventRepository.resetNextEventData()
|
eventRepository.resetNextEventData()
|
||||||
|
eventRepository.clearEvents()
|
||||||
}
|
}
|
||||||
|
eventRepository.close()
|
||||||
|
|
||||||
UpdatesReceiver.setUpdates(this@UpdateCalendarService)
|
UpdatesReceiver.setUpdates(this@UpdateCalendarService)
|
||||||
MainWidget.updateWidget(this@UpdateCalendarService)
|
MainWidget.updateWidget(this@UpdateCalendarService)
|
||||||
|
|
||||||
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
|
||||||
eventRepository.close()
|
|
||||||
|
|
||||||
stopSelf()
|
stopSelf()
|
||||||
}
|
}
|
||||||
|
@ -140,6 +140,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh
|
|||||||
|
|
||||||
if (Preferences.showEvents && !checkGrantedPermission(Manifest.permission.READ_CALENDAR)) {
|
if (Preferences.showEvents && !checkGrantedPermission(Manifest.permission.READ_CALENDAR)) {
|
||||||
Preferences.showEvents = false
|
Preferences.showEvents = false
|
||||||
|
com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver.removeUpdates(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,12 +38,15 @@ class CustomFontActivity : AppCompatActivity() {
|
|||||||
private lateinit var adapter: SlimAdapter
|
private lateinit var adapter: SlimAdapter
|
||||||
private lateinit var viewModel: CustomFontViewModel
|
private lateinit var viewModel: CustomFontViewModel
|
||||||
private lateinit var binding: ActivityCustomFontBinding
|
private lateinit var binding: ActivityCustomFontBinding
|
||||||
|
private lateinit var handlerThread: HandlerThread
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
viewModel = ViewModelProvider(this).get(CustomFontViewModel::class.java)
|
viewModel = ViewModelProvider(this).get(CustomFontViewModel::class.java)
|
||||||
binding = ActivityCustomFontBinding.inflate(layoutInflater)
|
binding = ActivityCustomFontBinding.inflate(layoutInflater)
|
||||||
|
handlerThread = HandlerThread("listCustomFonts")
|
||||||
|
handlerThread.start()
|
||||||
|
|
||||||
binding.listView.setHasFixedSize(true)
|
binding.listView.setHasFixedSize(true)
|
||||||
val mLayoutManager = LinearLayoutManager(this)
|
val mLayoutManager = LinearLayoutManager(this)
|
||||||
@ -64,14 +67,17 @@ class CustomFontActivity : AppCompatActivity() {
|
|||||||
injector
|
injector
|
||||||
.text(R.id.text, item)
|
.text(R.id.text, item)
|
||||||
.with<TextView>(R.id.text) {
|
.with<TextView>(R.id.text) {
|
||||||
val googleSans: Typeface = when (Preferences.customFontVariant) {
|
val googleSans: Typeface? = androidx.core.content.res.ResourcesCompat.getFont(
|
||||||
"100" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_thin.ttf")
|
this,
|
||||||
"200" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_light.ttf")
|
when (Preferences.customFontVariant) {
|
||||||
"500" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_medium.ttf")
|
"100" -> R.font.google_sans_thin
|
||||||
"700" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_bold.ttf")
|
"200" -> R.font.google_sans_light
|
||||||
"800" -> Typeface.createFromAsset(this.assets, "fonts/google_sans_black.ttf")
|
"500" -> R.font.google_sans_medium
|
||||||
else -> Typeface.createFromAsset(this.assets, "fonts/google_sans_regular.ttf")
|
"700" -> R.font.google_sans_bold
|
||||||
}
|
"800" -> R.font.google_sans_black
|
||||||
|
else -> R.font.google_sans_regular
|
||||||
|
}
|
||||||
|
)
|
||||||
it.typeface = googleSans
|
it.typeface = googleSans
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,32 +103,49 @@ class CustomFontActivity : AppCompatActivity() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
val callback = object : FontsContractCompat.FontRequestCallback() {
|
class Callback : FontsContractCompat.FontRequestCallback() {
|
||||||
override fun onTypefaceRetrieved(typeface: Typeface) {
|
var handler: Handler? = Handler(handlerThread.looper)
|
||||||
it.typeface = typeface
|
|
||||||
it.isVisible = true
|
|
||||||
|
|
||||||
it.measure(
|
fun cancel() {
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
if (handler != null) {
|
||||||
ViewGroup.LayoutParams.WRAP_CONTENT
|
handler!!.removeCallbacksAndMessages(null)
|
||||||
)
|
handler = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun finalize() {
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTypefaceRetrieved(typeface: Typeface) {
|
||||||
|
if (it.tag == this) {
|
||||||
|
it.tag = null
|
||||||
|
it.typeface = typeface
|
||||||
|
it.setTextColor(getColor(R.color.colorPrimaryText))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTypefaceRequestFailed(reason: Int) {
|
override fun onTypefaceRequestFailed(reason: Int) {
|
||||||
it.isVisible = false
|
if (it.tag == this) {
|
||||||
it.layoutParams = it.layoutParams.apply {
|
it.tag = null
|
||||||
height = 0
|
//it.text = item.fontFamily + " ($reason)"
|
||||||
|
it.setTextColor(getColor(R.color.errorColorText))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val handlerThread = HandlerThread(item.fontFamily)
|
(it.tag as Callback?)?.cancel()
|
||||||
handlerThread.start()
|
val callback = Callback()
|
||||||
val mHandler = Handler(handlerThread.looper)
|
it.tag = callback
|
||||||
|
it.typeface = null
|
||||||
|
it.setTextColor(getColor(R.color.colorSecondaryText))
|
||||||
|
|
||||||
|
val mHandler = callback.handler!!
|
||||||
FontsContractCompat.requestFont(this, request, callback, mHandler)
|
FontsContractCompat.requestFont(this, request, callback, mHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
injector.clicked(R.id.text) {
|
injector.clicked(R.id.text) {
|
||||||
|
if ((it as TextView).typeface == null) return@clicked
|
||||||
val dialog = BottomSheetMenu<Int>(this, header = item.fontFamily)
|
val dialog = BottomSheetMenu<Int>(this, header = item.fontFamily)
|
||||||
if (item.fontVariants.isEmpty()) {
|
if (item.fontVariants.isEmpty()) {
|
||||||
dialog.addItem(SettingsStringHelper.getVariantLabel(this, "regular"), -1)
|
dialog.addItem(SettingsStringHelper.getVariantLabel(this, "regular"), -1)
|
||||||
@ -147,6 +170,12 @@ class CustomFontActivity : AppCompatActivity() {
|
|||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
handlerThread.quit()
|
||||||
|
filterJob?.cancel()
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
private var filterJob: Job? = null
|
private var filterJob: Job? = null
|
||||||
|
|
||||||
private fun subscribeUi(binding: ActivityCustomFontBinding, viewModel: CustomFontViewModel) {
|
private fun subscribeUi(binding: ActivityCustomFontBinding, viewModel: CustomFontViewModel) {
|
||||||
@ -204,6 +233,13 @@ class CustomFontActivity : AppCompatActivity() {
|
|||||||
adapter.updateData(filteredList)
|
adapter.updateData(filteredList)
|
||||||
binding.loader.visibility = View.INVISIBLE
|
binding.loader.visibility = View.INVISIBLE
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
delay(200)
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
adapter.updateData(listOf(getString(R.string.custom_font_subtitle_1)).filter {
|
||||||
|
it.contains(search ?: "", ignoreCase = true)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,22 +46,27 @@ class CustomLocationActivity : AppCompatActivity() {
|
|||||||
adapter = SlimAdapter.create()
|
adapter = SlimAdapter.create()
|
||||||
adapter
|
adapter
|
||||||
.register<String>(R.layout.custom_location_item) { _, injector ->
|
.register<String>(R.layout.custom_location_item) { _, injector ->
|
||||||
injector
|
injector.text(R.id.text, getString(R.string.custom_location_gps))
|
||||||
.text(R.id.text, getString(R.string.custom_location_gps))
|
injector.clicked(R.id.text) {
|
||||||
.clicked(R.id.text) {
|
Preferences.bulk {
|
||||||
requirePermission()
|
remove(Preferences::customLocationLat)
|
||||||
|
remove(Preferences::customLocationLon)
|
||||||
|
remove(Preferences::customLocationAdd)
|
||||||
}
|
}
|
||||||
|
setResult(Activity.RESULT_OK)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.register<Address>(R.layout.custom_location_item) { item, injector ->
|
.register<Address>(R.layout.custom_location_item) { item, injector ->
|
||||||
injector.text(R.id.text, item.getAddressLine(0))
|
injector.text(R.id.text, item.getAddressLine(0) ?: "")
|
||||||
injector.clicked(R.id.item) {
|
injector.clicked(R.id.item) {
|
||||||
Preferences.bulk {
|
Preferences.bulk {
|
||||||
customLocationLat = item.latitude.toString()
|
customLocationLat = item.latitude.toString()
|
||||||
customLocationLon = item.longitude.toString()
|
customLocationLon = item.longitude.toString()
|
||||||
customLocationAdd = item.getAddressLine(0)
|
customLocationAdd = item.getAddressLine(0) ?: ""
|
||||||
setResult(Activity.RESULT_OK)
|
|
||||||
finish()
|
|
||||||
}
|
}
|
||||||
|
setResult(Activity.RESULT_OK)
|
||||||
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.attachTo(binding.listView)
|
.attachTo(binding.listView)
|
||||||
@ -115,36 +120,6 @@ class CustomLocationActivity : AppCompatActivity() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun requirePermission() {
|
|
||||||
Dexter.withContext(this)
|
|
||||||
.withPermissions(
|
|
||||||
Manifest.permission.ACCESS_FINE_LOCATION
|
|
||||||
).withListener(object: MultiplePermissionsListener {
|
|
||||||
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
|
|
||||||
report?.let {
|
|
||||||
if (report.areAllPermissionsGranted()){
|
|
||||||
Preferences.bulk {
|
|
||||||
remove(Preferences::customLocationLat)
|
|
||||||
remove(Preferences::customLocationLon)
|
|
||||||
remove(Preferences::customLocationAdd)
|
|
||||||
}
|
|
||||||
setResult(Activity.RESULT_OK)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
override fun onPermissionRationaleShouldBeShown(
|
|
||||||
permissions: MutableList<PermissionRequest>?,
|
|
||||||
token: PermissionToken?
|
|
||||||
) {
|
|
||||||
// Remember to invoke this method when the custom rationale is closed
|
|
||||||
// or just by default if you don't want to use any custom rationale.
|
|
||||||
token?.continuePermissionRequest()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.check()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
binding.actionBack.setOnClickListener {
|
binding.actionBack.setOnClickListener {
|
||||||
onBackPressed()
|
onBackPressed()
|
||||||
|
@ -74,7 +74,11 @@ class TimeZoneSelectorActivity : AppCompatActivity() {
|
|||||||
if (id != null) {
|
if (id != null) {
|
||||||
Preferences.bulk {
|
Preferences.bulk {
|
||||||
altTimezoneId = id
|
altTimezoneId = id
|
||||||
altTimezoneLabel = item.locality
|
altTimezoneLabel = try {
|
||||||
|
item.locality
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
item.getAddressLine(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MainWidget.updateWidget(this@TimeZoneSelectorActivity)
|
MainWidget.updateWidget(this@TimeZoneSelectorActivity)
|
||||||
setResult(Activity.RESULT_OK)
|
setResult(Activity.RESULT_OK)
|
||||||
|
@ -127,11 +127,11 @@ class WeatherProviderActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
private fun subscribeUi(viewModel: WeatherProviderViewModel) {
|
private fun subscribeUi(viewModel: WeatherProviderViewModel) {
|
||||||
viewModel.weatherProviderError.observe(this) {
|
viewModel.weatherProviderError.observe(this) {
|
||||||
updateListItem()
|
binding.listView.postDelayed({ updateListItem() }, 300)
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.weatherProviderLocationError.observe(this) {
|
viewModel.weatherProviderLocationError.observe(this) {
|
||||||
updateListItem()
|
binding.listView.postDelayed({ updateListItem() }, 300)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,15 +8,10 @@ import android.os.Bundle
|
|||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.Gravity
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.RemoteViews
|
||||||
import android.widget.RelativeLayout
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@ -29,23 +24,20 @@ import com.tommasoberlose.anotherwidget.databinding.FragmentAppMainBinding
|
|||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.helpers.*
|
import com.tommasoberlose.anotherwidget.helpers.*
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
|
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||||
import com.tommasoberlose.anotherwidget.ui.widgets.StandardWidget
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.*
|
import com.tommasoberlose.anotherwidget.utils.*
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
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 MainFragment : Fragment() {
|
class MainFragment : Fragment() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun newInstance() = MainFragment()
|
fun newInstance() = MainFragment()
|
||||||
private val PREVIEW_BASE_HEIGHT: Int
|
|
||||||
get() = if (Preferences.widgetAlign == Constants.WidgetAlign.CENTER.rawValue) 120 else 180
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var viewModel: MainViewModel
|
private lateinit var viewModel: MainViewModel
|
||||||
@ -97,13 +89,7 @@ class MainFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.actionSettings.setOnSingleClickListener {
|
binding.actionSettings.setOnSingleClickListener {
|
||||||
Navigation.findNavController(it).navigate(R.id.action_appMainFragment_to_appSettingsFragment,)
|
Navigation.findNavController(it).navigate(R.id.action_appMainFragment_to_appSettingsFragment)
|
||||||
}
|
|
||||||
|
|
||||||
binding.preview.layoutParams = binding.preview.layoutParams.apply {
|
|
||||||
height = PREVIEW_BASE_HEIGHT.toPixel(requireContext()) + if (Preferences.showClock) 100.toPixel(
|
|
||||||
requireContext()
|
|
||||||
) else 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subscribeUi(viewModel)
|
subscribeUi(viewModel)
|
||||||
@ -155,186 +141,56 @@ class MainFragment : Fragment() {
|
|||||||
binding.toolbar.cardElevation = if (it > 0) 24f else 0f
|
binding.toolbar.cardElevation = if (it > 0) 24f else 0f
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.widgetAlign.observe(viewLifecycleOwner) {
|
|
||||||
updatePreviewVisibility()
|
|
||||||
lifecycleScope.launch {
|
|
||||||
delay(350)
|
|
||||||
updateClock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.showPreview.observe(viewLifecycleOwner) {
|
|
||||||
updatePreviewVisibility()
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.clockPreferencesUpdate.observe(viewLifecycleOwner) {
|
|
||||||
updateClock()
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.widgetPreferencesUpdate.observe(viewLifecycleOwner) {
|
viewModel.widgetPreferencesUpdate.observe(viewLifecycleOwner) {
|
||||||
onUpdateUiEvent(null)
|
onUpdateUiEvent(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.showClock.observe(viewLifecycleOwner) {
|
|
||||||
updateClockVisibility(it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private var uiJob: Job? = null
|
private var uiJob: Job? = null
|
||||||
|
|
||||||
private fun updateUI() {
|
private fun updateUI() {
|
||||||
uiJob?.cancel()
|
|
||||||
|
|
||||||
if (Preferences.showPreview) {
|
if (Preferences.showPreview) {
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
|
||||||
val bgColor: Int = ContextCompat.getColor(
|
|
||||||
requireContext(),
|
|
||||||
if (ColorHelper.getFontColor(requireActivity().isDarkTheme())
|
|
||||||
.isColorDark()
|
|
||||||
) android.R.color.white else R.color.colorAccent
|
|
||||||
)
|
|
||||||
|
|
||||||
val wallpaperDrawable = BitmapHelper.getTintedDrawable(
|
|
||||||
requireContext(),
|
|
||||||
R.drawable.card_background,
|
|
||||||
ColorHelper.getBackgroundColor(requireActivity().isDarkTheme())
|
|
||||||
)
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
binding.preview.setCardBackgroundColor(bgColor)
|
|
||||||
binding.widgetDetail.widgetShapeBackground.setImageDrawable(wallpaperDrawable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WidgetHelper.runWithCustomTypeface(requireContext()) { typeface ->
|
WidgetHelper.runWithCustomTypeface(requireContext()) { typeface ->
|
||||||
|
uiJob?.cancel()
|
||||||
uiJob = lifecycleScope.launch(Dispatchers.IO) {
|
uiJob = lifecycleScope.launch(Dispatchers.IO) {
|
||||||
val generatedView = MainWidget.getWidgetView(requireContext(), typeface).root
|
val generatedView = MainWidget.getWidgetView(
|
||||||
|
requireContext(),
|
||||||
withContext(Dispatchers.Main) {
|
binding.widget.width - binding.widget.paddingStart - binding.widget.paddingEnd,
|
||||||
generatedView.measure(0, 0)
|
typeface
|
||||||
binding.preview.measure(0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
val bitmap = BitmapHelper.getBitmapFromView(
|
|
||||||
generatedView,
|
|
||||||
if (binding.preview.width > 0) binding.preview.width else generatedView.measuredWidth,
|
|
||||||
generatedView.measuredHeight
|
|
||||||
)
|
)
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
if (generatedView != null) {
|
||||||
binding.widgetDetail.bitmapContainer.apply {
|
withContext(Dispatchers.Main) {
|
||||||
setImageBitmap(bitmap)
|
val view: View = generatedView.apply(requireActivity().applicationContext, binding.widget)
|
||||||
}
|
view.measure(0, 0)
|
||||||
|
|
||||||
binding.widgetLoader.animate().scaleX(0f).scaleY(0f).alpha(0f)
|
binding.widgetLoader.animate().scaleX(1f).scaleY(1f).alpha(1f)
|
||||||
.setDuration(200L).start()
|
.setDuration(200L).start()
|
||||||
binding.widget.animate().alpha(1f).start()
|
binding.widget.animate().alpha(0f).setDuration(200L).withEndAction {
|
||||||
|
binding.widget.removeAllViews()
|
||||||
|
binding.widget.addView(view)
|
||||||
|
|
||||||
|
updatePreviewVisibility(view.measuredHeight)
|
||||||
|
binding.widgetLoader.animate().scaleX(0f).scaleY(0f).alpha(0f)
|
||||||
|
.setDuration(200L).start()
|
||||||
|
binding.widget.animate().alpha(1f).start()
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateClock() {
|
private fun updatePreviewVisibility(widgetHeight: Int) {
|
||||||
// Clock
|
val newHeight = widgetHeight + 32f.convertDpToPixel(requireContext()).toInt()
|
||||||
binding.widgetDetail.time.setTextColor(ColorHelper.getClockFontColor(requireActivity().isDarkTheme()))
|
if (binding.preview.layoutParams.height != newHeight) {
|
||||||
binding.widgetDetail.timeAmPm.setTextColor(ColorHelper.getClockFontColor(requireActivity().isDarkTheme()))
|
binding.preview.clearAnimation()
|
||||||
binding.widgetDetail.time.setTextSize(
|
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
|
||||||
Preferences.clockTextSize.toPixel(requireContext())
|
|
||||||
)
|
|
||||||
binding.widgetDetail.timeAmPm.setTextSize(
|
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
|
||||||
Preferences.clockTextSize.toPixel(requireContext()) / 5 * 2
|
|
||||||
)
|
|
||||||
binding.widgetDetail.timeAmPm.isVisible = Preferences.showAMPMIndicator
|
|
||||||
|
|
||||||
// Timezones
|
|
||||||
if (Preferences.altTimezoneId != "" && Preferences.altTimezoneLabel != "") {
|
|
||||||
// Clock
|
|
||||||
binding.widgetDetail.altTimezoneTime.timeZone = Preferences.altTimezoneId
|
|
||||||
binding.widgetDetail.altTimezoneTimeAmPm.timeZone = Preferences.altTimezoneId
|
|
||||||
binding.widgetDetail.altTimezoneLabel.text = Preferences.altTimezoneLabel
|
|
||||||
binding.widgetDetail.altTimezoneTime.setTextColor(ColorHelper.getClockFontColor(requireActivity().isDarkTheme()))
|
|
||||||
binding.widgetDetail.altTimezoneTimeAmPm.setTextColor(ColorHelper.getClockFontColor(requireActivity().isDarkTheme()))
|
|
||||||
binding.widgetDetail.altTimezoneLabel.setTextColor(ColorHelper.getClockFontColor(requireActivity().isDarkTheme()))
|
|
||||||
binding.widgetDetail.altTimezoneTime.setTextSize(
|
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
|
||||||
Preferences.clockTextSize.toPixel(requireContext()) / 3
|
|
||||||
)
|
|
||||||
binding.widgetDetail.altTimezoneTimeAmPm.setTextSize(
|
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
|
||||||
(Preferences.clockTextSize.toPixel(requireContext()) / 3) / 5 * 2
|
|
||||||
)
|
|
||||||
binding.widgetDetail.altTimezoneLabel.setTextSize(
|
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
|
||||||
(Preferences.clockTextSize.toPixel(requireContext()) / 3) / 5 * 2
|
|
||||||
)
|
|
||||||
binding.widgetDetail.timezonesContainer.isVisible = true
|
|
||||||
} else {
|
|
||||||
binding.widgetDetail.timezonesContainer.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clock bottom margin
|
|
||||||
binding.widgetDetail.clockBottomMarginNone.isVisible =
|
|
||||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.NONE.rawValue
|
|
||||||
binding.widgetDetail.clockBottomMarginSmall.isVisible =
|
|
||||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.SMALL.rawValue
|
|
||||||
binding.widgetDetail.clockBottomMarginMedium.isVisible =
|
|
||||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.MEDIUM.rawValue
|
|
||||||
binding.widgetDetail.clockBottomMarginLarge.isVisible =
|
|
||||||
Preferences.showClock && Preferences.clockBottomMargin == Constants.ClockBottomMargin.LARGE.rawValue
|
|
||||||
|
|
||||||
// Align
|
|
||||||
binding.widgetDetail.timeContainer.layoutParams = (binding.widgetDetail.timeContainer.layoutParams as LinearLayout.LayoutParams).apply {
|
|
||||||
gravity = if (Preferences.widgetAlign == Constants.WidgetAlign.CENTER.rawValue) Gravity.CENTER_HORIZONTAL else Gravity.NO_GRAVITY
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateClockVisibility(showClock: Boolean) {
|
|
||||||
binding.widgetDetail.timeContainer.clearAnimation()
|
|
||||||
binding.widgetDetail.time.clearAnimation()
|
|
||||||
|
|
||||||
updatePreviewVisibility()
|
|
||||||
|
|
||||||
if (showClock) {
|
|
||||||
binding.widgetDetail.timeContainer.layoutParams = (binding.widgetDetail.timeContainer.layoutParams as LinearLayout.LayoutParams).apply {
|
|
||||||
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
|
||||||
}
|
|
||||||
binding.widgetDetail.timeContainer.measure(0, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((Preferences.showClock && binding.widgetDetail.time.alpha != 1f) || (!Preferences.showClock && binding.widgetDetail.time.alpha != 0f)) {
|
|
||||||
val initialHeight = binding.widgetDetail.timeContainer.measuredHeight
|
|
||||||
ValueAnimator.ofFloat(
|
|
||||||
if (showClock) 0f else 1f,
|
|
||||||
if (showClock) 1f else 0f
|
|
||||||
).apply {
|
|
||||||
duration = 300L
|
|
||||||
addUpdateListener {
|
|
||||||
val animatedValue = animatedValue as Float
|
|
||||||
binding.widgetDetail.timeContainer.layoutParams =
|
|
||||||
binding.widgetDetail.timeContainer.layoutParams.apply {
|
|
||||||
height = (initialHeight * animatedValue).toInt()
|
|
||||||
}
|
|
||||||
binding.widgetDetail.time.alpha = animatedValue
|
|
||||||
}
|
|
||||||
}.start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updatePreviewVisibility() {
|
|
||||||
binding.preview.clearAnimation()
|
|
||||||
if (binding.preview.layoutParams.height != (if (Preferences.showPreview) PREVIEW_BASE_HEIGHT.toPixel(requireContext()) else 0) + (if (Preferences.showClock) 100.toPixel(
|
|
||||||
requireContext()
|
|
||||||
) else 0)) {
|
|
||||||
ValueAnimator.ofInt(
|
ValueAnimator.ofInt(
|
||||||
binding.preview.height,
|
binding.preview.height,
|
||||||
(if (Preferences.showPreview) PREVIEW_BASE_HEIGHT.toPixel(requireContext()) else 0) + (if (Preferences.showClock) 100.toPixel(
|
newHeight
|
||||||
requireContext()
|
|
||||||
) else 0)
|
|
||||||
).apply {
|
).apply {
|
||||||
duration = 300L
|
duration = 500L
|
||||||
addUpdateListener {
|
addUpdateListener {
|
||||||
val animatedValue = animatedValue as Int
|
val animatedValue = animatedValue as Int
|
||||||
val layoutParams = binding.preview.layoutParams
|
val layoutParams = binding.preview.layoutParams
|
||||||
|
@ -35,6 +35,7 @@ import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
|||||||
import com.tommasoberlose.anotherwidget.ui.activities.settings.SupportDevActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.settings.SupportDevActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||||
|
import com.tommasoberlose.anotherwidget.utils.ignoreExceptions
|
||||||
import com.tommasoberlose.anotherwidget.utils.openURI
|
import com.tommasoberlose.anotherwidget.utils.openURI
|
||||||
import com.tommasoberlose.anotherwidget.utils.setOnSingleClickListener
|
import com.tommasoberlose.anotherwidget.utils.setOnSingleClickListener
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -206,10 +207,14 @@ class SettingsFragment : Fragment() {
|
|||||||
.rotation((binding.actionRefreshIcon.rotation - binding.actionRefreshIcon.rotation % 360f) + 360f)
|
.rotation((binding.actionRefreshIcon.rotation - binding.actionRefreshIcon.rotation % 360f) + 360f)
|
||||||
.withEndAction {
|
.withEndAction {
|
||||||
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
|
viewLifecycleOwner.lifecycleScope.launch(Dispatchers.IO) {
|
||||||
WeatherHelper.updateWeather(requireContext())
|
try {
|
||||||
CalendarHelper.updateEventList(requireContext())
|
WeatherHelper.updateWeather(requireContext())
|
||||||
MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
|
CalendarHelper.updateEventList(requireContext())
|
||||||
ActiveNotificationsHelper.clearLastNotification(requireContext())
|
MediaPlayerHelper.updatePlayingMediaInfo(requireContext())
|
||||||
|
ActiveNotificationsHelper.clearLastNotification(requireContext())
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.start()
|
.start()
|
||||||
|
@ -63,6 +63,7 @@ class CalendarFragment : Fragment() {
|
|||||||
binding.showAllDayToggle.setCheckedImmediatelyNoEvent(Preferences.calendarAllDay)
|
binding.showAllDayToggle.setCheckedImmediatelyNoEvent(Preferences.calendarAllDay)
|
||||||
binding.showOnlyBusyEventsToggle.setCheckedImmediatelyNoEvent(Preferences.showOnlyBusyEvents)
|
binding.showOnlyBusyEventsToggle.setCheckedImmediatelyNoEvent(Preferences.showOnlyBusyEvents)
|
||||||
binding.showDiffTimeToggle.setCheckedImmediatelyNoEvent(Preferences.showDiffTime)
|
binding.showDiffTimeToggle.setCheckedImmediatelyNoEvent(Preferences.showDiffTime)
|
||||||
|
binding.showNextEventOnMultipleLinesToggle.setCheckedImmediatelyNoEvent(Preferences.showNextEventOnMultipleLines)
|
||||||
|
|
||||||
setupListener()
|
setupListener()
|
||||||
|
|
||||||
@ -90,6 +91,12 @@ class CalendarFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewModel.showNextEventOnMultipleLines.observe(viewLifecycleOwner) {
|
||||||
|
maintainScrollPosition {
|
||||||
|
binding.showNextEventOnMultipleLinesLabel.text = if (it) getString(R.string.settings_enabled) else getString(R.string.settings_disabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
viewModel.showDiffTime.observe(viewLifecycleOwner) {
|
viewModel.showDiffTime.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.showDiffTimeLabel.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
binding.showDiffTimeLabel.text = if (it) getString(R.string.settings_visible) else getString(R.string.settings_not_visible)
|
||||||
@ -175,7 +182,7 @@ class CalendarFragment : Fragment() {
|
|||||||
|
|
||||||
binding.showAllDayToggle.setOnCheckedChangeListener { _, isChecked ->
|
binding.showAllDayToggle.setOnCheckedChangeListener { _, isChecked ->
|
||||||
Preferences.calendarAllDay = isChecked
|
Preferences.calendarAllDay = isChecked
|
||||||
MainWidget.updateWidget(requireContext())
|
updateCalendar()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionChangeAttendeeFilter.setOnClickListener {
|
binding.actionChangeAttendeeFilter.setOnClickListener {
|
||||||
@ -220,7 +227,7 @@ class CalendarFragment : Fragment() {
|
|||||||
|
|
||||||
binding.showOnlyBusyEventsToggle.setOnCheckedChangeListener { _, isChecked ->
|
binding.showOnlyBusyEventsToggle.setOnCheckedChangeListener { _, isChecked ->
|
||||||
Preferences.showOnlyBusyEvents = isChecked
|
Preferences.showOnlyBusyEvents = isChecked
|
||||||
MainWidget.updateWidget(requireContext())
|
updateCalendar()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionShowDiffTime.setOnClickListener {
|
binding.actionShowDiffTime.setOnClickListener {
|
||||||
@ -229,6 +236,15 @@ class CalendarFragment : Fragment() {
|
|||||||
|
|
||||||
binding.showDiffTimeToggle.setOnCheckedChangeListener { _, isChecked ->
|
binding.showDiffTimeToggle.setOnCheckedChangeListener { _, isChecked ->
|
||||||
Preferences.showDiffTime = isChecked
|
Preferences.showDiffTime = isChecked
|
||||||
|
updateCalendar()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.actionShowNextEventOnMultipleLines.setOnClickListener {
|
||||||
|
binding.showNextEventOnMultipleLinesToggle.isChecked = !binding.showNextEventOnMultipleLinesToggle.isChecked
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.showNextEventOnMultipleLinesToggle.setOnCheckedChangeListener { _, isChecked ->
|
||||||
|
Preferences.showNextEventOnMultipleLines = isChecked
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionWidgetUpdateFrequency.setOnClickListener {
|
binding.actionWidgetUpdateFrequency.setOnClickListener {
|
||||||
@ -239,6 +255,7 @@ class CalendarFragment : Fragment() {
|
|||||||
.addItem(getString(R.string.settings_widget_update_frequency_low), Constants.WidgetUpdateFrequency.LOW.rawValue)
|
.addItem(getString(R.string.settings_widget_update_frequency_low), Constants.WidgetUpdateFrequency.LOW.rawValue)
|
||||||
.addOnSelectItemListener { value ->
|
.addOnSelectItemListener { value ->
|
||||||
Preferences.widgetUpdateFrequency = value
|
Preferences.widgetUpdateFrequency = value
|
||||||
|
updateCalendar()
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import com.chibatching.kotpref.bulk
|
|||||||
import com.google.android.material.transition.MaterialSharedAxis
|
import com.google.android.material.transition.MaterialSharedAxis
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
import com.tommasoberlose.anotherwidget.components.BottomSheetPicker
|
||||||
import com.tommasoberlose.anotherwidget.databinding.FragmentTabClockBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentTabClockBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
@ -144,16 +144,15 @@ class ClockFragment : Fragment() {
|
|||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
|
|
||||||
binding.actionClockTextSize.setOnClickListener {
|
binding.actionClockTextSize.setOnClickListener {
|
||||||
val dialog = BottomSheetMenu<Float>(
|
BottomSheetPicker(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
header = getString(R.string.settings_clock_text_size_title)
|
items = (120 downTo 30).filter { it % 2 == 0 }.map { BottomSheetPicker.MenuItem("${it}sp", it.toFloat()) },
|
||||||
).setSelectedValue(Preferences.clockTextSize)
|
getSelected = { Preferences.clockTextSize },
|
||||||
(46 downTo 12).filter { it % 2 == 0 }.forEach {
|
header = getString(R.string.settings_clock_text_size_title),
|
||||||
dialog.addItem("${it}sp", it.toFloat())
|
onItemSelected = {value ->
|
||||||
}
|
if (value != null) Preferences.clockTextSize = value
|
||||||
dialog.addOnSelectItemListener { value ->
|
}
|
||||||
Preferences.clockTextSize = value
|
).show()
|
||||||
}.show()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionAltTimezoneClock.setOnClickListener {
|
binding.actionAltTimezoneClock.setOnClickListener {
|
||||||
|
@ -102,15 +102,7 @@ class GesturesFragment : Fragment() {
|
|||||||
it == IntentHelper.DO_NOTHING_OPTION -> getString(R.string.gestures_do_nothing)
|
it == IntentHelper.DO_NOTHING_OPTION -> getString(R.string.gestures_do_nothing)
|
||||||
it == IntentHelper.REFRESH_WIDGET_OPTION -> getString(R.string.gestures_refresh_widget)
|
it == IntentHelper.REFRESH_WIDGET_OPTION -> getString(R.string.gestures_refresh_widget)
|
||||||
it != IntentHelper.DEFAULT_OPTION -> it
|
it != IntentHelper.DEFAULT_OPTION -> it
|
||||||
else -> {
|
else -> getString(R.string.default_calendar_app)
|
||||||
if (IntentHelper.getCalendarIntent(requireContext()).isDefaultSet(requireContext())) {
|
|
||||||
getString(
|
|
||||||
R.string.default_calendar_app
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
getString(R.string.gestures_do_nothing)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,15 +119,7 @@ class GesturesFragment : Fragment() {
|
|||||||
it == IntentHelper.DO_NOTHING_OPTION -> getString(R.string.gestures_do_nothing)
|
it == IntentHelper.DO_NOTHING_OPTION -> getString(R.string.gestures_do_nothing)
|
||||||
it == IntentHelper.REFRESH_WIDGET_OPTION -> getString(R.string.gestures_refresh_widget)
|
it == IntentHelper.REFRESH_WIDGET_OPTION -> getString(R.string.gestures_refresh_widget)
|
||||||
it != IntentHelper.DEFAULT_OPTION -> it
|
it != IntentHelper.DEFAULT_OPTION -> it
|
||||||
else -> {
|
else -> getString(R.string.default_clock_app)
|
||||||
if (IntentHelper.getClockIntent(requireContext()).isDefaultSet(requireContext())) {
|
|
||||||
getString(
|
|
||||||
R.string.default_clock_app
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
getString(R.string.gestures_do_nothing)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,9 +157,12 @@ class GesturesFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.actionCalendarApp.setOnClickListener {
|
binding.actionCalendarApp.setOnClickListener {
|
||||||
startActivityForResult(Intent(requireContext(), ChooseApplicationActivity::class.java).apply {
|
startActivityForResult(
|
||||||
putExtra(Constants.RESULT_APP_PACKAGE, Preferences.calendarAppPackage)
|
Intent(requireContext(), ChooseApplicationActivity::class.java).apply {
|
||||||
}, RequestCode.CALENDAR_APP_REQUEST_CODE.code)
|
putExtra(Constants.RESULT_APP_PACKAGE, Preferences.calendarAppPackage)
|
||||||
|
},
|
||||||
|
RequestCode.CALENDAR_APP_REQUEST_CODE.code
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionClockApp.setOnClickListener {
|
binding.actionClockApp.setOnClickListener {
|
||||||
|
@ -293,6 +293,25 @@ class GlanceTabFragment : Fragment() {
|
|||||||
if (!(isVisible && hasError)) View.VISIBLE else View.GONE
|
if (!(isVisible && hasError)) View.VISIBLE else View.GONE
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Constants.GlanceProviderId.WEATHER -> {
|
||||||
|
isVisible =
|
||||||
|
Preferences.showWeatherAsGlanceProvider
|
||||||
|
val hasError = !Preferences.showWeather || (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-") || Preferences.weatherProviderLocationError != ""
|
||||||
|
injector.text(
|
||||||
|
R.id.label,
|
||||||
|
if (isVisible && !hasError) getString(R.string.settings_visible) else getString(
|
||||||
|
R.string.settings_not_visible
|
||||||
|
)
|
||||||
|
)
|
||||||
|
injector.visibility(
|
||||||
|
R.id.error_icon,
|
||||||
|
if (isVisible && hasError) View.VISIBLE else View.GONE
|
||||||
|
)
|
||||||
|
injector.visibility(
|
||||||
|
R.id.info_icon,
|
||||||
|
if (!(isVisible && hasError)) View.VISIBLE else View.GONE
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
injector.alpha(R.id.title, if (isVisible) 1f else .25f)
|
injector.alpha(R.id.title, if (isVisible) 1f else .25f)
|
||||||
|
@ -86,6 +86,28 @@ class LayoutFragment : Fragment() {
|
|||||||
viewModel: MainViewModel
|
viewModel: MainViewModel
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
viewModel.widgetMargin.observe(viewLifecycleOwner) {
|
||||||
|
maintainScrollPosition {
|
||||||
|
binding.widgetMarginLabel.text = when (it) {
|
||||||
|
Constants.Dimension.NONE.rawValue -> getString(R.string.settings_widget_dim_none)
|
||||||
|
Constants.Dimension.SMALL.rawValue -> getString(R.string.settings_widget_dim_small)
|
||||||
|
Constants.Dimension.LARGE.rawValue -> getString(R.string.settings_widget_dim_large)
|
||||||
|
else -> getString(R.string.settings_widget_dim_medium)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel.widgetPadding.observe(viewLifecycleOwner) {
|
||||||
|
maintainScrollPosition {
|
||||||
|
binding.widgetPaddingLabel.text = when (it) {
|
||||||
|
Constants.Dimension.NONE.rawValue -> getString(R.string.settings_widget_dim_none)
|
||||||
|
Constants.Dimension.SMALL.rawValue -> getString(R.string.settings_widget_dim_small)
|
||||||
|
Constants.Dimension.LARGE.rawValue -> getString(R.string.settings_widget_dim_large)
|
||||||
|
else -> getString(R.string.settings_widget_dim_medium)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
viewModel.secondRowTopMargin.observe(viewLifecycleOwner) {
|
viewModel.secondRowTopMargin.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.secondRowTopMarginLabel.text = when (it) {
|
binding.secondRowTopMarginLabel.text = when (it) {
|
||||||
@ -101,12 +123,14 @@ class LayoutFragment : Fragment() {
|
|||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.widgetAlignIcon.setImageDrawable(when (it) {
|
binding.widgetAlignIcon.setImageDrawable(when (it) {
|
||||||
Constants.WidgetAlign.LEFT.rawValue -> ContextCompat.getDrawable(requireContext(), R.drawable.round_align_horizontal_left_24)
|
Constants.WidgetAlign.LEFT.rawValue -> ContextCompat.getDrawable(requireContext(), R.drawable.round_align_horizontal_left_24)
|
||||||
|
Constants.WidgetAlign.RIGHT.rawValue -> ContextCompat.getDrawable(requireContext(), R.drawable.round_align_horizontal_right_24)
|
||||||
Constants.WidgetAlign.CENTER.rawValue -> ContextCompat.getDrawable(requireContext(), R.drawable.round_align_horizontal_center_24)
|
Constants.WidgetAlign.CENTER.rawValue -> ContextCompat.getDrawable(requireContext(), R.drawable.round_align_horizontal_center_24)
|
||||||
else -> ContextCompat.getDrawable(requireContext(), R.drawable.round_align_horizontal_center_24)
|
else -> ContextCompat.getDrawable(requireContext(), R.drawable.round_align_horizontal_center_24)
|
||||||
})
|
})
|
||||||
|
|
||||||
binding.widgetAlignLabel.text = when (it) {
|
binding.widgetAlignLabel.text = when (it) {
|
||||||
Constants.WidgetAlign.LEFT.rawValue -> getString(R.string.settings_widget_align_left_subtitle)
|
Constants.WidgetAlign.LEFT.rawValue -> getString(R.string.settings_widget_align_left_subtitle)
|
||||||
|
Constants.WidgetAlign.RIGHT.rawValue -> getString(R.string.settings_widget_align_right_subtitle)
|
||||||
Constants.WidgetAlign.CENTER.rawValue -> getString(R.string.settings_widget_align_center_subtitle)
|
Constants.WidgetAlign.CENTER.rawValue -> getString(R.string.settings_widget_align_center_subtitle)
|
||||||
else -> getString(R.string.settings_widget_align_center_subtitle)
|
else -> getString(R.string.settings_widget_align_center_subtitle)
|
||||||
}
|
}
|
||||||
@ -145,6 +169,58 @@ class LayoutFragment : Fragment() {
|
|||||||
|
|
||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
|
|
||||||
|
binding.actionWidgetMargin.setOnClickListener {
|
||||||
|
BottomSheetMenu<Float>(
|
||||||
|
requireContext(),
|
||||||
|
header = getString(R.string.settings_widget_margin_title)
|
||||||
|
).setSelectedValue(Preferences.widgetMargin)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_widget_dim_none),
|
||||||
|
Constants.Dimension.NONE.rawValue
|
||||||
|
)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_widget_dim_small),
|
||||||
|
Constants.Dimension.SMALL.rawValue
|
||||||
|
)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_widget_dim_medium),
|
||||||
|
Constants.Dimension.MEDIUM.rawValue
|
||||||
|
)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_widget_dim_large),
|
||||||
|
Constants.Dimension.LARGE.rawValue
|
||||||
|
)
|
||||||
|
.addOnSelectItemListener { value ->
|
||||||
|
Preferences.widgetMargin = value
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.actionWidgetPadding.setOnClickListener {
|
||||||
|
BottomSheetMenu<Float>(
|
||||||
|
requireContext(),
|
||||||
|
header = getString(R.string.settings_widget_padding_title)
|
||||||
|
).setSelectedValue(Preferences.widgetPadding)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_widget_dim_none),
|
||||||
|
Constants.Dimension.NONE.rawValue
|
||||||
|
)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_widget_dim_small),
|
||||||
|
Constants.Dimension.SMALL.rawValue
|
||||||
|
)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_widget_dim_medium),
|
||||||
|
Constants.Dimension.MEDIUM.rawValue
|
||||||
|
)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_widget_dim_large),
|
||||||
|
Constants.Dimension.LARGE.rawValue
|
||||||
|
)
|
||||||
|
.addOnSelectItemListener { value ->
|
||||||
|
Preferences.widgetPadding = value
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
|
||||||
binding.actionSecondRowTopMarginSize.setOnClickListener {
|
binding.actionSecondRowTopMarginSize.setOnClickListener {
|
||||||
BottomSheetMenu<Int>(
|
BottomSheetMenu<Int>(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
@ -210,6 +286,10 @@ class LayoutFragment : Fragment() {
|
|||||||
getString(R.string.settings_widget_align_left_subtitle),
|
getString(R.string.settings_widget_align_left_subtitle),
|
||||||
Constants.WidgetAlign.LEFT.rawValue
|
Constants.WidgetAlign.LEFT.rawValue
|
||||||
)
|
)
|
||||||
|
.addItem(
|
||||||
|
getString(R.string.settings_widget_align_right_subtitle),
|
||||||
|
Constants.WidgetAlign.RIGHT.rawValue
|
||||||
|
)
|
||||||
.addOnSelectItemListener { value ->
|
.addOnSelectItemListener { value ->
|
||||||
Preferences.widgetAlign = value
|
Preferences.widgetAlign = value
|
||||||
}.show()
|
}.show()
|
||||||
|
@ -23,6 +23,7 @@ import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog
|
|||||||
import com.tommasoberlose.anotherwidget.databinding.FragmentPreferencesBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentPreferencesBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||||
|
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||||
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
|
import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver
|
||||||
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
|
||||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||||
@ -123,6 +124,7 @@ class PreferencesFragment : Fragment() {
|
|||||||
requireCalendarPermission()
|
requireCalendarPermission()
|
||||||
} else {
|
} else {
|
||||||
Preferences.showEvents = enabled
|
Preferences.showEvents = enabled
|
||||||
|
UpdatesReceiver.removeUpdates(requireContext())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,6 +135,8 @@ class PreferencesFragment : Fragment() {
|
|||||||
binding.showWeatherSwitch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
binding.showWeatherSwitch.setOnCheckedChangeListener { _, enabled: Boolean ->
|
||||||
Preferences.showWeather = enabled
|
Preferences.showWeather = enabled
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
|
Preferences.weatherProviderError = ""
|
||||||
|
Preferences.weatherProviderLocationError = ""
|
||||||
WeatherReceiver.setUpdates(requireContext())
|
WeatherReceiver.setUpdates(requireContext())
|
||||||
} else {
|
} else {
|
||||||
WeatherReceiver.removeUpdates(requireContext())
|
WeatherReceiver.removeUpdates(requireContext())
|
||||||
|
@ -15,6 +15,7 @@ import com.google.android.material.transition.MaterialSharedAxis
|
|||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
import com.tommasoberlose.anotherwidget.components.BottomSheetColorPicker
|
||||||
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
import com.tommasoberlose.anotherwidget.components.BottomSheetMenu
|
||||||
|
import com.tommasoberlose.anotherwidget.components.BottomSheetPicker
|
||||||
import com.tommasoberlose.anotherwidget.databinding.FragmentTabTypographyBinding
|
import com.tommasoberlose.anotherwidget.databinding.FragmentTabTypographyBinding
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
@ -167,25 +168,27 @@ class TypographyFragment : Fragment() {
|
|||||||
|
|
||||||
private fun setupListener() {
|
private fun setupListener() {
|
||||||
binding.actionMainTextSize.setOnClickListener {
|
binding.actionMainTextSize.setOnClickListener {
|
||||||
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.title_main_text_size)).setSelectedValue(
|
BottomSheetPicker(
|
||||||
Preferences.textMainSize)
|
requireContext(),
|
||||||
(40 downTo 10).filter { it % 2 == 0 }.forEach {
|
items = (40 downTo 10).map { BottomSheetPicker.MenuItem("${it}sp", it.toFloat()) },
|
||||||
dialog.addItem("${it}sp", it.toFloat())
|
getSelected = { Preferences.textMainSize },
|
||||||
}
|
header = getString(R.string.title_main_text_size),
|
||||||
dialog.addOnSelectItemListener { value ->
|
onItemSelected = {value ->
|
||||||
Preferences.textMainSize = value
|
if (value != null) Preferences.textMainSize = value
|
||||||
}.show()
|
}
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionSecondTextSize.setOnClickListener {
|
binding.actionSecondTextSize.setOnClickListener {
|
||||||
val dialog = BottomSheetMenu<Float>(requireContext(), header = getString(R.string.title_second_text_size)).setSelectedValue(
|
BottomSheetPicker(
|
||||||
Preferences.textSecondSize)
|
requireContext(),
|
||||||
(40 downTo 10).filter { it % 2 == 0 }.forEach {
|
items = (40 downTo 10).map { BottomSheetPicker.MenuItem("${it}sp", it.toFloat()) },
|
||||||
dialog.addItem("${it}sp", it.toFloat())
|
getSelected = { Preferences.textSecondSize },
|
||||||
}
|
header = getString(R.string.title_second_text_size),
|
||||||
dialog.addOnSelectItemListener { value ->
|
onItemSelected = {value ->
|
||||||
Preferences.textSecondSize = value
|
if (value != null) Preferences.textSecondSize = value
|
||||||
}.show()
|
}
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.actionFontColor.setOnClickListener {
|
binding.actionFontColor.setOnClickListener {
|
||||||
@ -209,7 +212,7 @@ class TypographyFragment : Fragment() {
|
|||||||
} else {
|
} else {
|
||||||
Preferences.textGlobalAlpha = alpha.toHexValue()
|
Preferences.textGlobalAlpha = alpha.toHexValue()
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +239,7 @@ class TypographyFragment : Fragment() {
|
|||||||
} else {
|
} else {
|
||||||
Preferences.textSecondaryAlpha = alpha.toHexValue()
|
Preferences.textSecondaryAlpha = alpha.toHexValue()
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,7 +276,7 @@ class TypographyFragment : Fragment() {
|
|||||||
Intent(requireContext(), CustomFontActivity::class.java),
|
Intent(requireContext(), CustomFontActivity::class.java),
|
||||||
RequestCode.CUSTOM_FONT_CHOOSER_REQUEST_CODE.code
|
RequestCode.CUSTOM_FONT_CHOOSER_REQUEST_CODE.code
|
||||||
)
|
)
|
||||||
} else if (value != Constants.CUSTOM_FONT_DOWNLOADED) {
|
} else if (value != Preferences.customFont) {
|
||||||
Preferences.bulk {
|
Preferences.bulk {
|
||||||
customFont = value
|
customFont = value
|
||||||
customFontFile = ""
|
customFontFile = ""
|
||||||
@ -314,6 +317,17 @@ class TypographyFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
|
if (resultCode == android.app.Activity.RESULT_OK) {
|
||||||
|
when (requestCode) {
|
||||||
|
RequestCode.CUSTOM_FONT_CHOOSER_REQUEST_CODE.code -> {
|
||||||
|
com.tommasoberlose.anotherwidget.ui.widgets.MainWidget.updateWidget(requireContext())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
|
}
|
||||||
|
|
||||||
private fun maintainScrollPosition(callback: () -> Unit) {
|
private fun maintainScrollPosition(callback: () -> Unit) {
|
||||||
binding.scrollView.isScrollable = false
|
binding.scrollView.isScrollable = false
|
||||||
callback.invoke()
|
callback.invoke()
|
||||||
|
@ -91,16 +91,17 @@ class WeatherFragment : Fragment() {
|
|||||||
viewModel.weatherProvider.observe(viewLifecycleOwner) {
|
viewModel.weatherProvider.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.labelWeatherProvider.text = WeatherHelper.getProviderName(requireContext(), Constants.WeatherProvider.fromInt(it)!!)
|
binding.labelWeatherProvider.text = WeatherHelper.getProviderName(requireContext(), Constants.WeatherProvider.fromInt(it)!!)
|
||||||
checkWeatherProviderConfig()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.weatherProviderError.observe(viewLifecycleOwner) {
|
viewModel.weatherProviderError.observe(viewLifecycleOwner) {
|
||||||
checkWeatherProviderConfig()
|
checkWeatherProviderConfig()
|
||||||
|
checkLocationPermission()
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.weatherProviderLocationError.observe(viewLifecycleOwner) {
|
viewModel.weatherProviderLocationError.observe(viewLifecycleOwner) {
|
||||||
checkWeatherProviderConfig()
|
checkWeatherProviderConfig()
|
||||||
|
checkLocationPermission()
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.customLocationAdd.observe(viewLifecycleOwner) {
|
viewModel.customLocationAdd.observe(viewLifecycleOwner) {
|
||||||
@ -108,6 +109,7 @@ class WeatherFragment : Fragment() {
|
|||||||
binding.labelCustomLocation.text =
|
binding.labelCustomLocation.text =
|
||||||
if (it == "") getString(R.string.custom_location_gps) else it
|
if (it == "") getString(R.string.custom_location_gps) else it
|
||||||
}
|
}
|
||||||
|
checkWeatherProviderConfig()
|
||||||
checkLocationPermission()
|
checkLocationPermission()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,43 +118,50 @@ class WeatherFragment : Fragment() {
|
|||||||
binding.tempUnit.text =
|
binding.tempUnit.text =
|
||||||
if (it == "F") getString(R.string.fahrenheit) else getString(R.string.celsius)
|
if (it == "F") getString(R.string.fahrenheit) else getString(R.string.celsius)
|
||||||
}
|
}
|
||||||
checkLocationPermission()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.weatherRefreshPeriod.observe(viewLifecycleOwner) {
|
viewModel.weatherRefreshPeriod.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.labelWeatherRefreshPeriod.text = getString(SettingsStringHelper.getRefreshPeriodString(it))
|
binding.labelWeatherRefreshPeriod.text = getString(SettingsStringHelper.getRefreshPeriodString(it))
|
||||||
}
|
}
|
||||||
checkLocationPermission()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.weatherIconPack.observe(viewLifecycleOwner) {
|
viewModel.weatherIconPack.observe(viewLifecycleOwner) {
|
||||||
maintainScrollPosition {
|
maintainScrollPosition {
|
||||||
binding.labelWeatherIconPack.text = getString(R.string.settings_weather_icon_pack_default).format((it + 1))
|
binding.labelWeatherIconPack.text = getString(R.string.settings_weather_icon_pack_default).format((it + 1))
|
||||||
}
|
}
|
||||||
checkLocationPermission()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkLocationPermission() {
|
private fun checkLocationPermission() {
|
||||||
if (requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
|
if (requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) &&
|
||||||
|
(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R ||
|
||||||
|
requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION))
|
||||||
|
) {
|
||||||
binding.locationPermissionAlert.isVisible = false
|
binding.locationPermissionAlert.isVisible = false
|
||||||
WeatherReceiver.setUpdates(requireContext())
|
} else if (Preferences.customLocationAdd == "") {
|
||||||
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
|
|
||||||
binding.locationPermissionAlert.isVisible = true
|
binding.locationPermissionAlert.isVisible = true
|
||||||
binding.locationPermissionAlert.setOnClickListener {
|
binding.locationPermissionAlert.setOnClickListener {
|
||||||
requirePermission()
|
requirePermission()
|
||||||
}
|
}
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R &&
|
||||||
|
requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)
|
||||||
|
) {
|
||||||
|
val text = getString(R.string.action_grant_permission) + " - " +
|
||||||
|
requireContext().packageManager.backgroundPermissionOptionLabel
|
||||||
|
binding.locationPermissionAlert.text = text
|
||||||
|
}
|
||||||
|
binding.weatherProviderLocationError.isVisible = false
|
||||||
} else {
|
} else {
|
||||||
binding.locationPermissionAlert.isVisible = false
|
binding.locationPermissionAlert.isVisible = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkWeatherProviderConfig() {
|
private fun checkWeatherProviderConfig() {
|
||||||
binding.weatherProviderError.isVisible = Preferences.showWeather && Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-"
|
binding.weatherProviderError.isVisible = Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-"
|
||||||
binding.weatherProviderError.text = Preferences.weatherProviderError
|
binding.weatherProviderError.text = Preferences.weatherProviderError
|
||||||
|
|
||||||
binding.weatherProviderLocationError.isVisible = Preferences.showWeather && Preferences.weatherProviderLocationError != ""
|
binding.weatherProviderLocationError.isVisible = Preferences.weatherProviderLocationError != ""
|
||||||
binding.weatherProviderLocationError.text = Preferences.weatherProviderLocationError
|
binding.weatherProviderLocationError.text = Preferences.weatherProviderLocationError
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,11 +186,11 @@ class WeatherFragment : Fragment() {
|
|||||||
.addItem(getString(R.string.celsius), "C")
|
.addItem(getString(R.string.celsius), "C")
|
||||||
.addOnSelectItemListener { value ->
|
.addOnSelectItemListener { value ->
|
||||||
if (value != Preferences.weatherTempUnit) {
|
if (value != Preferences.weatherTempUnit) {
|
||||||
|
Preferences.weatherTempUnit = value
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
WeatherHelper.updateWeather(requireContext())
|
WeatherHelper.updateWeather(requireContext())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Preferences.weatherTempUnit = value
|
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +202,10 @@ class WeatherFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
dialog
|
dialog
|
||||||
.addOnSelectItemListener { value ->
|
.addOnSelectItemListener { value ->
|
||||||
Preferences.weatherRefreshPeriod = value
|
if (value != Preferences.weatherRefreshPeriod) {
|
||||||
|
Preferences.weatherRefreshPeriod = value
|
||||||
|
WeatherReceiver.setUpdates(requireContext())
|
||||||
|
}
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,12 +218,12 @@ class WeatherFragment : Fragment() {
|
|||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
when (requestCode) {
|
when (requestCode) {
|
||||||
Constants.RESULT_CODE_CUSTOM_LOCATION -> {
|
Constants.RESULT_CODE_CUSTOM_LOCATION -> {
|
||||||
WeatherReceiver.setUpdates(requireContext())
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
checkLocationPermission()
|
WeatherHelper.updateWeather(requireContext())
|
||||||
}
|
}
|
||||||
RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> {
|
|
||||||
checkLocationPermission()
|
|
||||||
}
|
}
|
||||||
|
//RequestCode.WEATHER_PROVIDER_REQUEST_CODE.code -> {
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
@ -220,12 +232,19 @@ class WeatherFragment : Fragment() {
|
|||||||
private fun requirePermission() {
|
private fun requirePermission() {
|
||||||
Dexter.withContext(requireContext())
|
Dexter.withContext(requireContext())
|
||||||
.withPermissions(
|
.withPermissions(
|
||||||
Manifest.permission.ACCESS_FINE_LOCATION
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R &&
|
||||||
|
requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION))
|
||||||
|
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 {
|
||||||
if (report.areAllPermissionsGranted()){
|
if (report.areAllPermissionsGranted()) {
|
||||||
checkLocationPermission()
|
checkLocationPermission()
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
WeatherHelper.updateWeather(requireContext())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,8 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
val showDividers = Preferences.asLiveData(Preferences::showDividers)
|
val showDividers = Preferences.asLiveData(Preferences::showDividers)
|
||||||
val secondRowTopMargin = Preferences.asLiveData(Preferences::secondRowTopMargin)
|
val secondRowTopMargin = Preferences.asLiveData(Preferences::secondRowTopMargin)
|
||||||
val widgetAlign = Preferences.asLiveData(Preferences::widgetAlign)
|
val widgetAlign = Preferences.asLiveData(Preferences::widgetAlign)
|
||||||
|
val widgetMargin = Preferences.asLiveData(Preferences::widgetMargin)
|
||||||
|
val widgetPadding = Preferences.asLiveData(Preferences::widgetPadding)
|
||||||
|
|
||||||
// Calendar Settings
|
// Calendar Settings
|
||||||
val showEvents = Preferences.asLiveData(Preferences::showEvents)
|
val showEvents = Preferences.asLiveData(Preferences::showEvents)
|
||||||
@ -57,6 +59,7 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
val showUntil = Preferences.asLiveData(Preferences::showUntil)
|
val showUntil = Preferences.asLiveData(Preferences::showUntil)
|
||||||
val showDiffTime = Preferences.asLiveData(Preferences::showDiffTime)
|
val showDiffTime = Preferences.asLiveData(Preferences::showDiffTime)
|
||||||
val showNextEvent = Preferences.asLiveData(Preferences::showNextEvent)
|
val showNextEvent = Preferences.asLiveData(Preferences::showNextEvent)
|
||||||
|
val showNextEventOnMultipleLines = Preferences.asLiveData(Preferences::showNextEventOnMultipleLines)
|
||||||
val openEventDetails = Preferences.asLiveData(Preferences::openEventDetails)
|
val openEventDetails = Preferences.asLiveData(Preferences::openEventDetails)
|
||||||
val calendarAppName = Preferences.asLiveData(Preferences::calendarAppName)
|
val calendarAppName = Preferences.asLiveData(Preferences::calendarAppName)
|
||||||
val widgetUpdateFrequency = Preferences.asLiveData(Preferences::widgetUpdateFrequency)
|
val widgetUpdateFrequency = Preferences.asLiveData(Preferences::widgetUpdateFrequency)
|
||||||
@ -101,7 +104,8 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
|
|
||||||
// UI
|
// UI
|
||||||
val fragmentScrollY = MutableLiveData<Int>()
|
val fragmentScrollY = MutableLiveData<Int>()
|
||||||
val clockPreferencesUpdate = MediatorLiveData<Boolean>().apply {
|
val widgetPreferencesUpdate = MediatorLiveData<Boolean>().apply {
|
||||||
|
addSource(Preferences.asLiveData(Preferences::showClock)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::clockTextSize)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::clockTextSize)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::clockTextColor)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::clockTextColor)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::clockTextAlpha)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::clockTextAlpha)) { value = true }
|
||||||
@ -110,8 +114,6 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
addSource(Preferences.asLiveData(Preferences::showAMPMIndicator)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showAMPMIndicator)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::clockBottomMargin)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::clockBottomMargin)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::altTimezoneLabel)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::altTimezoneLabel)) { value = true }
|
||||||
}
|
|
||||||
val widgetPreferencesUpdate = MediatorLiveData<Boolean>().apply {
|
|
||||||
addSource(Preferences.asLiveData(Preferences::textGlobalColor)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::textGlobalColor)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::textGlobalAlpha)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::textGlobalAlpha)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::textSecondaryColor)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::textSecondaryColor)) { value = true }
|
||||||
@ -135,6 +137,8 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
addSource(Preferences.asLiveData(Preferences::customFontVariant)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::customFontVariant)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::secondRowInformation)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::secondRowInformation)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::widgetAlign)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::widgetAlign)) { value = true }
|
||||||
|
addSource(Preferences.asLiveData(Preferences::widgetMargin)) { value = true }
|
||||||
|
addSource(Preferences.asLiveData(Preferences::widgetPadding)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showDividers)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showDividers)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::secondRowTopMargin)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::secondRowTopMargin)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::isDateCapitalize)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::isDateCapitalize)) { value = true }
|
||||||
@ -144,6 +148,7 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
addSource(Preferences.asLiveData(Preferences::calendarAllDay)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::calendarAllDay)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showDiffTime)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showDiffTime)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showNextEvent)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showNextEvent)) { value = true }
|
||||||
|
addSource(Preferences.asLiveData(Preferences::showNextEventOnMultipleLines)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showDeclinedEvents)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showDeclinedEvents)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showInvitedEvents)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showInvitedEvents)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showAcceptedEvents)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showAcceptedEvents)) { value = true }
|
||||||
@ -169,6 +174,7 @@ class MainViewModel(context: Application) : AndroidViewModel(context) {
|
|||||||
addSource(Preferences.asLiveData(Preferences::musicPlayersFilter)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::musicPlayersFilter)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::appNotificationsFilter)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::appNotificationsFilter)) { value = true }
|
||||||
addSource(Preferences.asLiveData(Preferences::showEventsAsGlanceProvider)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::showEventsAsGlanceProvider)) { value = true }
|
||||||
|
addSource(Preferences.asLiveData(Preferences::showWeatherAsGlanceProvider)) { value = true }
|
||||||
|
|
||||||
addSource(Preferences.asLiveData(Preferences::installedIntegrations)) { value = true }
|
addSource(Preferences.asLiveData(Preferences::installedIntegrations)) { value = true }
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.tommasoberlose.anotherwidget.ui.widgets
|
|||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.RemoteViews
|
import android.widget.RemoteViews
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
@ -24,20 +25,21 @@ class ClockWidget(val context: Context) {
|
|||||||
views.setViewVisibility(R.id.clock_bottom_margin_small, 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_medium, View.GONE)
|
||||||
views.setViewVisibility(R.id.clock_bottom_margin_large, View.GONE)
|
views.setViewVisibility(R.id.clock_bottom_margin_large, View.GONE)
|
||||||
|
views.setViewVisibility(R.id.timezones_container, View.GONE)
|
||||||
} else {
|
} else {
|
||||||
views.setTextColor(R.id.time, ColorHelper.getClockFontColor(context.isDarkTheme()))
|
views.setTextColor(R.id.time, ColorHelper.getClockFontColor(context.isDarkTheme()))
|
||||||
views.setTextColor(R.id.time_am_pm, ColorHelper.getClockFontColor(context.isDarkTheme()))
|
views.setTextColor(R.id.time_am_pm, ColorHelper.getClockFontColor(context.isDarkTheme()))
|
||||||
views.setTextViewTextSize(
|
views.setTextViewTextSize(
|
||||||
R.id.time,
|
R.id.time,
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
Preferences.clockTextSize.toPixel(context)
|
Preferences.clockTextSize
|
||||||
)
|
)
|
||||||
views.setTextViewTextSize(
|
views.setTextViewTextSize(
|
||||||
R.id.time_am_pm,
|
R.id.time_am_pm,
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
Preferences.clockTextSize.toPixel(context) / 5 * 2
|
Preferences.clockTextSize / 5 * 2
|
||||||
)
|
)
|
||||||
val clockPIntent = PendingIntent.getActivity(
|
val clockPIntent = IntentHelper.getPendingIntent(
|
||||||
context,
|
context,
|
||||||
widgetID,
|
widgetID,
|
||||||
IntentHelper.getClockIntent(context),
|
IntentHelper.getClockIntent(context),
|
||||||
@ -78,19 +80,29 @@ class ClockWidget(val context: Context) {
|
|||||||
views.setTextViewTextSize(
|
views.setTextViewTextSize(
|
||||||
R.id.alt_timezone_time,
|
R.id.alt_timezone_time,
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
Preferences.clockTextSize.toPixel(context) / 3
|
Preferences.clockTextSize / 3
|
||||||
)
|
)
|
||||||
views.setTextViewTextSize(
|
views.setTextViewTextSize(
|
||||||
R.id.alt_timezone_time_am_pm,
|
R.id.alt_timezone_time_am_pm,
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
(Preferences.clockTextSize.toPixel(context) / 3) / 5 * 2
|
(Preferences.clockTextSize / 3) / 5 * 2
|
||||||
)
|
)
|
||||||
views.setTextViewTextSize(
|
views.setTextViewTextSize(
|
||||||
R.id.alt_timezone_label,
|
R.id.alt_timezone_label,
|
||||||
TypedValue.COMPLEX_UNIT_SP,
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
(Preferences.clockTextSize.toPixel(context) / 3) / 5 * 2
|
(Preferences.clockTextSize / 3) / 5 * 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val padding = (TypedValue.applyDimension(
|
||||||
|
TypedValue.COMPLEX_UNIT_SP,
|
||||||
|
Preferences.clockTextSize,
|
||||||
|
context.resources.displayMetrics
|
||||||
|
) * 0.2).toInt()
|
||||||
|
if (Preferences.widgetAlign == Constants.WidgetAlign.RIGHT.rawValue)
|
||||||
|
views.setViewPadding(R.id.timezones_container, 0, padding, padding, 0)
|
||||||
|
else
|
||||||
|
views.setViewPadding(R.id.timezones_container, padding, padding, 0,0)
|
||||||
|
|
||||||
views.setOnClickPendingIntent(R.id.timezones_container, clockPIntent)
|
views.setOnClickPendingIntent(R.id.timezones_container, clockPIntent)
|
||||||
views.setViewVisibility(R.id.timezones_container, View.VISIBLE)
|
views.setViewVisibility(R.id.timezones_container, View.VISIBLE)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,890 +0,0 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.widgets
|
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.text.format.DateUtils
|
|
||||||
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.RemoteViews
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.core.view.updateMargins
|
|
||||||
import com.tommasoberlose.anotherwidget.R
|
|
||||||
import com.tommasoberlose.anotherwidget.databinding.LeftAlignedWidgetBinding
|
|
||||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Actions
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.*
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ImageHelper.applyShadow
|
|
||||||
import com.tommasoberlose.anotherwidget.receivers.CrashlyticsReceiver
|
|
||||||
import com.tommasoberlose.anotherwidget.receivers.NewCalendarEventReceiver
|
|
||||||
import com.tommasoberlose.anotherwidget.receivers.WidgetClickListenerReceiver
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.convertDpToPixel
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
|
||||||
import java.text.DateFormat
|
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
class LeftAlignedWidget(val context: Context) {
|
|
||||||
fun generateWidget(appWidgetId: Int, w: Int, typeface: Typeface? = null): RemoteViews {
|
|
||||||
|
|
||||||
var views = RemoteViews(context.packageName, R.layout.left_aligned_widget_sans)
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Background
|
|
||||||
views.setInt(
|
|
||||||
R.id.widget_shape_background,
|
|
||||||
"setColorFilter",
|
|
||||||
ColorHelper.getBackgroundColorRgb(context.isDarkTheme())
|
|
||||||
)
|
|
||||||
views.setInt(
|
|
||||||
R.id.widget_shape_background,
|
|
||||||
"setImageAlpha",
|
|
||||||
ColorHelper.getBackgroundAlpha(context.isDarkTheme())
|
|
||||||
)
|
|
||||||
val refreshIntent = PendingIntent.getActivity(
|
|
||||||
context,
|
|
||||||
appWidgetId,
|
|
||||||
IntentHelper.getWidgetUpdateIntent(context),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.widget_shape_background, refreshIntent)
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
CrashlyticsReceiver.sendCrash(context, ex)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clock
|
|
||||||
views = ClockWidget(context).updateClockView(views, appWidgetId)
|
|
||||||
|
|
||||||
// Setup listener
|
|
||||||
try {
|
|
||||||
val generatedBinding = generateWidgetView(typeface)
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.bitmap_container,
|
|
||||||
BitmapHelper.getBitmapFromView(generatedBinding.root, width = w)
|
|
||||||
)
|
|
||||||
views = updateGridView(generatedBinding, views, appWidgetId)
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
CrashlyticsReceiver.sendCrash(context, ex)
|
|
||||||
}
|
|
||||||
|
|
||||||
return views
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateGridView(bindingView: LeftAlignedWidgetBinding, views: RemoteViews, widgetID: Int): RemoteViews {
|
|
||||||
val eventRepository = EventRepository(context)
|
|
||||||
try {
|
|
||||||
// Weather
|
|
||||||
if (Preferences.showWeather && Preferences.weatherIcon != "") {
|
|
||||||
views.setViewVisibility(R.id.weather_rect, View.VISIBLE)
|
|
||||||
views.setViewVisibility(R.id.weather_sub_line, View.GONE)
|
|
||||||
|
|
||||||
val i = Intent(context, WidgetClickListenerReceiver::class.java)
|
|
||||||
i.action = Actions.ACTION_OPEN_WEATHER_INTENT
|
|
||||||
val weatherPIntent = PendingIntent.getBroadcast(context, widgetID, i, 0)
|
|
||||||
|
|
||||||
views.setOnClickPendingIntent(R.id.weather_rect, weatherPIntent)
|
|
||||||
views.setOnClickPendingIntent(R.id.weather_sub_line_rect, weatherPIntent)
|
|
||||||
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.weather_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(bindingView.weatherDateLine, draw = false)
|
|
||||||
)
|
|
||||||
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.weather_sub_line_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(bindingView.weatherSubLine, draw = false)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
views.setViewVisibility(R.id.weather_rect, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.weather_sub_line, View.GONE)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Calendar
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.date_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(bindingView.date, draw = false)
|
|
||||||
)
|
|
||||||
|
|
||||||
val calPIntent = PendingIntent.getActivity(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getCalendarIntent(context),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.date_rect, calPIntent)
|
|
||||||
views.setViewVisibility(R.id.first_line_rect, View.VISIBLE)
|
|
||||||
|
|
||||||
val nextEvent = eventRepository.getNextEvent()
|
|
||||||
val nextAlarm = AlarmHelper.getNextAlarm(context)
|
|
||||||
|
|
||||||
// Spacing
|
|
||||||
views.setViewVisibility(
|
|
||||||
R.id.sub_line_top_margin_small_sans,
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.rawValue) View.VISIBLE else View.GONE
|
|
||||||
)
|
|
||||||
views.setViewVisibility(
|
|
||||||
R.id.sub_line_top_margin_medium_sans,
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.rawValue) View.VISIBLE else View.GONE
|
|
||||||
)
|
|
||||||
views.setViewVisibility(
|
|
||||||
R.id.sub_line_top_margin_large_sans,
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.rawValue) View.VISIBLE else View.GONE
|
|
||||||
)
|
|
||||||
|
|
||||||
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null && !Preferences.showEventsAsGlanceProvider) {
|
|
||||||
if (Preferences.showNextEvent && eventRepository.getEventsCount() > 1) {
|
|
||||||
|
|
||||||
// Action next event
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.action_next_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(bindingView.actionNext, draw = false)
|
|
||||||
)
|
|
||||||
views.setViewVisibility(R.id.action_next_rect, View.VISIBLE)
|
|
||||||
views.setOnClickPendingIntent(
|
|
||||||
R.id.action_next_rect,
|
|
||||||
PendingIntent.getBroadcast(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
Intent(
|
|
||||||
context,
|
|
||||||
NewCalendarEventReceiver::class.java
|
|
||||||
).apply { action = Actions.ACTION_GO_TO_NEXT_EVENT },
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
views.setViewVisibility(R.id.action_next_rect, View.VISIBLE)
|
|
||||||
} else {
|
|
||||||
views.setViewVisibility(R.id.action_next_rect, View.GONE)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Event intent
|
|
||||||
val eventIntent = PendingIntent.getActivity(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getEventIntent(context, nextEvent),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.next_event_rect, eventIntent)
|
|
||||||
views.setViewVisibility(R.id.next_event_rect, View.VISIBLE)
|
|
||||||
|
|
||||||
// Event time difference
|
|
||||||
if (Preferences.showDiffTime && Calendar.getInstance().timeInMillis < nextEvent.startDate) {
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.next_event_difference_time_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(
|
|
||||||
bindingView.nextEventDifferenceTime,
|
|
||||||
draw = false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
views.setOnClickPendingIntent(R.id.next_event_difference_time_rect, eventIntent)
|
|
||||||
views.setViewVisibility(R.id.next_event_difference_time_rect, View.VISIBLE)
|
|
||||||
} else {
|
|
||||||
views.setViewVisibility(R.id.next_event_difference_time_rect, View.GONE)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Event information
|
|
||||||
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
|
|
||||||
val mapIntent = PendingIntent.getActivity(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getGoogleMapsIntentFromAddress(context, nextEvent.address),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.sub_line_rect, mapIntent)
|
|
||||||
} else {
|
|
||||||
val pIntentDetail = PendingIntent.getActivity(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getEventIntent(
|
|
||||||
context,
|
|
||||||
nextEvent,
|
|
||||||
forceEventDetails = true
|
|
||||||
),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.sub_line_rect, pIntentDetail)
|
|
||||||
}
|
|
||||||
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.next_event_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(bindingView.nextEvent, draw = false)
|
|
||||||
)
|
|
||||||
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
|
||||||
|
|
||||||
views.setViewVisibility(R.id.calendar_layout_rect, View.VISIBLE)
|
|
||||||
views.setViewVisibility(R.id.sub_line_rect, View.VISIBLE)
|
|
||||||
views.setViewVisibility(R.id.weather_sub_line_rect, View.VISIBLE)
|
|
||||||
views.setViewVisibility(R.id.first_line_rect, View.GONE)
|
|
||||||
|
|
||||||
views.setViewVisibility(R.id.sub_line_top_margin_small_sans, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.sub_line_top_margin_medium_sans, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.sub_line_top_margin_large_sans, View.GONE)
|
|
||||||
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
|
|
||||||
var showSomething = false
|
|
||||||
loop@ for (provider: Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(context)) {
|
|
||||||
when (provider) {
|
|
||||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
|
||||||
if (MediaPlayerHelper.isSomeonePlaying(context)) {
|
|
||||||
val musicIntent = PendingIntent.getActivity(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getMusicIntent(context),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.sub_line_rect, musicIntent)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
|
||||||
if (Preferences.showNextAlarm && nextAlarm != "") {
|
|
||||||
val alarmIntent = PendingIntent.getActivity(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getClockIntent(context),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.sub_line_rect, alarmIntent)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
|
||||||
if (Preferences.showBatteryCharging) {
|
|
||||||
BatteryHelper.updateBatteryInfo(context)
|
|
||||||
if (Preferences.isCharging || Preferences.isBatteryLevelLow) {
|
|
||||||
val batteryIntent = PendingIntent.getActivity(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getBatteryIntent(),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.sub_line_rect, batteryIntent)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
|
||||||
if (Preferences.customNotes.isNotEmpty()) {
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
|
||||||
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
|
|
||||||
val fitIntent = PendingIntent.getActivity(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getFitIntent(context),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(R.id.sub_line_rect, fitIntent)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.NOTIFICATIONS -> {
|
|
||||||
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
|
|
||||||
try {
|
|
||||||
if (Preferences.lastNotificationIcon != 0) {
|
|
||||||
val remotePackageContext = context.createPackageContext(
|
|
||||||
Preferences.lastNotificationPackage, 0)
|
|
||||||
ContextCompat.getDrawable(
|
|
||||||
remotePackageContext,
|
|
||||||
Preferences.lastNotificationIcon)
|
|
||||||
}
|
|
||||||
val notificationIntent = PendingIntent.getActivity(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getNotificationIntent(context),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(
|
|
||||||
R.id.sub_line_rect,
|
|
||||||
notificationIntent
|
|
||||||
)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
} catch (ex: Exception) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.GREETINGS -> {
|
|
||||||
if (Preferences.showGreetings && GreetingsHelper.showGreetings() && GreetingsHelper.getRandomString(context).isNotBlank()) {
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.EVENTS -> {
|
|
||||||
if (Preferences.showEventsAsGlanceProvider&& Preferences.showEvents && context.checkGrantedPermission(
|
|
||||||
Manifest.permission.READ_CALENDAR) && nextEvent != null) {
|
|
||||||
val pIntentDetail = PendingIntent.getActivity(
|
|
||||||
context,
|
|
||||||
widgetID,
|
|
||||||
IntentHelper.getEventIntent(
|
|
||||||
context,
|
|
||||||
nextEvent,
|
|
||||||
forceEventDetails = true
|
|
||||||
),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT
|
|
||||||
)
|
|
||||||
views.setOnClickPendingIntent(
|
|
||||||
R.id.sub_line_rect,
|
|
||||||
pIntentDetail
|
|
||||||
)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (showSomething) {
|
|
||||||
views.setViewVisibility(R.id.first_line_rect, View.VISIBLE)
|
|
||||||
views.setViewVisibility(R.id.weather_rect, View.VISIBLE)
|
|
||||||
views.setViewVisibility(R.id.sub_line_rect, View.VISIBLE)
|
|
||||||
|
|
||||||
views.setViewVisibility(R.id.calendar_layout_rect, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.weather_sub_line_rect, View.GONE)
|
|
||||||
} else {
|
|
||||||
// Spacing
|
|
||||||
views.setViewVisibility(R.id.sub_line_top_margin_small_sans, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.sub_line_top_margin_medium_sans, View.GONE)
|
|
||||||
views.setViewVisibility(R.id.sub_line_top_margin_large_sans, View.GONE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Second row
|
|
||||||
views.setImageViewBitmap(
|
|
||||||
R.id.sub_line_rect,
|
|
||||||
BitmapHelper.getBitmapFromView(bindingView.subLine, draw = false)
|
|
||||||
)
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
ex.printStackTrace()
|
|
||||||
CrashlyticsReceiver.sendCrash(context, ex)
|
|
||||||
} finally {
|
|
||||||
eventRepository.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
return views
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Generates the widget bitmap from the view
|
|
||||||
fun generateWidgetView(typeface: Typeface? = null): LeftAlignedWidgetBinding {
|
|
||||||
val eventRepository = EventRepository(context)
|
|
||||||
val bindingView = LeftAlignedWidgetBinding.inflate(LayoutInflater.from(context))
|
|
||||||
|
|
||||||
bindingView.loader.isVisible = false
|
|
||||||
|
|
||||||
// Weather
|
|
||||||
if (Preferences.showWeather && Preferences.weatherIcon != "") {
|
|
||||||
bindingView.weatherDateLine.isVisible = true
|
|
||||||
val currentTemp = String.format(
|
|
||||||
Locale.getDefault(),
|
|
||||||
"%d°%s",
|
|
||||||
Preferences.weatherTemp.roundToInt(),
|
|
||||||
Preferences.weatherRealTempUnit
|
|
||||||
)
|
|
||||||
|
|
||||||
val icon: String = Preferences.weatherIcon
|
|
||||||
if (icon == "") {
|
|
||||||
bindingView.weatherSubLineWeatherIcon.isVisible = false
|
|
||||||
bindingView.weatherDateLineWeatherIcon.isVisible = false
|
|
||||||
} else {
|
|
||||||
bindingView.weatherSubLineWeatherIcon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon))
|
|
||||||
bindingView.weatherDateLineWeatherIcon.setImageResource(WeatherHelper.getWeatherIconResource(context, icon))
|
|
||||||
bindingView.weatherSubLineWeatherIcon.isVisible = true
|
|
||||||
bindingView.weatherDateLineWeatherIcon.isVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
bindingView.weatherDateLineTemperature.text = currentTemp
|
|
||||||
bindingView.weatherSubLineTemperature.text = currentTemp
|
|
||||||
|
|
||||||
if (GlanceProviderHelper.showGlanceProviders(context)) {
|
|
||||||
bindingView.weatherSubLine.isVisible = false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bindingView.weatherDateLine.isVisible = false
|
|
||||||
bindingView.weatherSubLine.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
val now = Calendar.getInstance().apply {
|
|
||||||
set(Calendar.SECOND, 0)
|
|
||||||
set(Calendar.MILLISECOND, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
bindingView.dateLayout.isVisible = true
|
|
||||||
bindingView.calendarLayout.isVisible = false
|
|
||||||
bindingView.nextEventDifferenceTime.isVisible = false
|
|
||||||
bindingView.actionNext.isVisible = false
|
|
||||||
|
|
||||||
bindingView.date.text = DateHelper.getDateText(context, now)
|
|
||||||
|
|
||||||
val nextEvent = eventRepository.getNextEvent()
|
|
||||||
val nextAlarm = AlarmHelper.getNextAlarm(context)
|
|
||||||
|
|
||||||
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null && !Preferences.showEventsAsGlanceProvider) {
|
|
||||||
// Multiple counter
|
|
||||||
bindingView.actionNext.isVisible =
|
|
||||||
Preferences.showNextEvent && eventRepository.getEventsCount() > 1
|
|
||||||
|
|
||||||
bindingView.nextEvent.text = nextEvent.title
|
|
||||||
|
|
||||||
if (Preferences.showDiffTime && now.timeInMillis < nextEvent.startDate) {
|
|
||||||
bindingView.nextEventDifferenceTime.text = if (!nextEvent.allDay) {
|
|
||||||
SettingsStringHelper.getDifferenceText(
|
|
||||||
context,
|
|
||||||
now.timeInMillis,
|
|
||||||
nextEvent.startDate
|
|
||||||
)
|
|
||||||
.toLowerCase(Locale.getDefault())
|
|
||||||
} else {
|
|
||||||
SettingsStringHelper.getAllDayEventDifferenceText(
|
|
||||||
context,
|
|
||||||
now.timeInMillis,
|
|
||||||
nextEvent.startDate
|
|
||||||
).toLowerCase(Locale.getDefault())
|
|
||||||
}
|
|
||||||
bindingView.nextEventDifferenceTime.isVisible = true
|
|
||||||
} else {
|
|
||||||
bindingView.nextEventDifferenceTime.isVisible = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextEvent.address != "" && Preferences.secondRowInformation == 1) {
|
|
||||||
bindingView.subLineIcon.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(
|
|
||||||
context,
|
|
||||||
R.drawable.round_place_24
|
|
||||||
)
|
|
||||||
)
|
|
||||||
bindingView.subLineText.text = nextEvent.address
|
|
||||||
} else {
|
|
||||||
bindingView.subLineIcon.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(
|
|
||||||
context,
|
|
||||||
R.drawable.round_today_24
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if (!nextEvent.allDay) {
|
|
||||||
val startHour =
|
|
||||||
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault())
|
|
||||||
.format(nextEvent.startDate)
|
|
||||||
val endHour =
|
|
||||||
DateFormat.getTimeInstance(DateFormat.SHORT, Locale.getDefault())
|
|
||||||
.format(nextEvent.endDate)
|
|
||||||
|
|
||||||
var dayDiff =
|
|
||||||
TimeUnit.MILLISECONDS.toDays(nextEvent.endDate - nextEvent.startDate)
|
|
||||||
|
|
||||||
val startCal = Calendar.getInstance()
|
|
||||||
startCal.timeInMillis = nextEvent.startDate
|
|
||||||
|
|
||||||
val endCal = Calendar.getInstance()
|
|
||||||
endCal.timeInMillis = nextEvent.endDate
|
|
||||||
|
|
||||||
if (startCal.get(Calendar.HOUR_OF_DAY) > endCal.get(Calendar.HOUR_OF_DAY)) {
|
|
||||||
dayDiff++
|
|
||||||
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(
|
|
||||||
Calendar.MINUTE
|
|
||||||
) > endCal.get(Calendar.MINUTE)
|
|
||||||
) {
|
|
||||||
dayDiff++
|
|
||||||
}
|
|
||||||
var multipleDay = ""
|
|
||||||
if (dayDiff > 0) {
|
|
||||||
multipleDay = String.format(
|
|
||||||
" (+%s%s)",
|
|
||||||
dayDiff,
|
|
||||||
context.getString(R.string.day_char)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nextEvent.startDate != nextEvent.endDate) {
|
|
||||||
bindingView.subLineText.text =
|
|
||||||
String.format("%s - %s%s", startHour, endHour, multipleDay)
|
|
||||||
} else {
|
|
||||||
bindingView.subLineText.text =
|
|
||||||
String.format("%s", startHour)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
val flags: Int =
|
|
||||||
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
|
||||||
val start = Calendar.getInstance().apply { timeInMillis = nextEvent.startDate }
|
|
||||||
|
|
||||||
bindingView.subLineText.text = if (now.get(Calendar.DAY_OF_YEAR) == start.get(
|
|
||||||
Calendar.DAY_OF_YEAR)) {
|
|
||||||
DateUtils.formatDateTime(context, nextEvent.startDate, flags)
|
|
||||||
} else if (now.get(Calendar.DAY_OF_YEAR) > start.get(Calendar.DAY_OF_YEAR) || now.get(
|
|
||||||
Calendar.YEAR) > start.get(Calendar.YEAR)) {
|
|
||||||
DateUtils.formatDateTime(context, now.timeInMillis, flags)
|
|
||||||
} else {
|
|
||||||
DateUtils.formatDateTime(context, nextEvent.startDate, flags)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bindingView.dateLayout.isVisible = false
|
|
||||||
bindingView.calendarLayout.isVisible = true
|
|
||||||
bindingView.subLine.isVisible = true
|
|
||||||
bindingView.weatherSubLine.isVisible = true
|
|
||||||
|
|
||||||
bindingView.subLineTopMarginSmall.visibility = View.GONE
|
|
||||||
bindingView.subLineTopMarginMedium.visibility = View.GONE
|
|
||||||
bindingView.subLineTopMarginLarge.visibility = View.GONE
|
|
||||||
} else if (GlanceProviderHelper.showGlanceProviders(context)) {
|
|
||||||
bindingView.subLineIcon.isVisible = true
|
|
||||||
var showSomething = false
|
|
||||||
loop@ for (provider: Constants.GlanceProviderId in GlanceProviderHelper.getGlanceProviders(
|
|
||||||
context
|
|
||||||
)) {
|
|
||||||
when (provider) {
|
|
||||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
|
||||||
if (MediaPlayerHelper.isSomeonePlaying(context)) {
|
|
||||||
bindingView.subLineIcon.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(
|
|
||||||
context,
|
|
||||||
R.drawable.round_music_note_24
|
|
||||||
)
|
|
||||||
)
|
|
||||||
bindingView.subLineText.text = MediaPlayerHelper.getMediaInfo()
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
|
|
||||||
if (Preferences.showNextAlarm && nextAlarm != "") {
|
|
||||||
bindingView.subLineIcon.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(
|
|
||||||
context,
|
|
||||||
R.drawable.round_alarm_24
|
|
||||||
)
|
|
||||||
)
|
|
||||||
bindingView.subLineText.text = AlarmHelper.getNextAlarm(context)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
|
|
||||||
if (Preferences.showBatteryCharging) {
|
|
||||||
BatteryHelper.updateBatteryInfo(context)
|
|
||||||
if (Preferences.isCharging) {
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
val batteryLevel = BatteryHelper.getBatteryLevel(context)
|
|
||||||
if (batteryLevel != 100) {
|
|
||||||
bindingView.subLineText.text = context.getString(R.string.charging)
|
|
||||||
} else {
|
|
||||||
bindingView.subLineText.text =
|
|
||||||
context.getString(R.string.charged)
|
|
||||||
}
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
} else if (Preferences.isBatteryLevelLow) {
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
bindingView.subLineText.text =
|
|
||||||
context.getString(R.string.battery_low_warning)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
|
||||||
if (Preferences.customNotes.isNotEmpty()) {
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
bindingView.subLineText.text = Preferences.customNotes
|
|
||||||
bindingView.subLineText.maxLines = 2
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
|
||||||
if (Preferences.showDailySteps && Preferences.googleFitSteps > 0) {
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
bindingView.subLineText.text =
|
|
||||||
context.getString(R.string.daily_steps_counter)
|
|
||||||
.format(Preferences.googleFitSteps)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.NOTIFICATIONS -> {
|
|
||||||
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
|
|
||||||
try {
|
|
||||||
if (Preferences.lastNotificationIcon != 0) {
|
|
||||||
val remotePackageContext = context.createPackageContext(
|
|
||||||
Preferences.lastNotificationPackage, 0)
|
|
||||||
val icon = ContextCompat.getDrawable(remotePackageContext,
|
|
||||||
Preferences.lastNotificationIcon)
|
|
||||||
bindingView.subLineIcon.isVisible = true
|
|
||||||
bindingView.subLineIcon.setImageDrawable(icon)
|
|
||||||
} else {
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
}
|
|
||||||
bindingView.subLineText.text = Preferences.lastNotificationTitle
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
} catch (ex: Exception) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.GREETINGS -> {
|
|
||||||
val greetingsText = GreetingsHelper.getRandomString(context)
|
|
||||||
if (Preferences.showGreetings && GreetingsHelper.showGreetings() && greetingsText.isNotBlank()) {
|
|
||||||
bindingView.subLineText.text = greetingsText
|
|
||||||
bindingView.subLineText.maxLines = 2
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constants.GlanceProviderId.EVENTS -> {
|
|
||||||
if (Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(
|
|
||||||
Manifest.permission.READ_CALENDAR) && nextEvent != null) {
|
|
||||||
bindingView.subLineText.text = context.getString(R.string.events_glance_provider_format).format(nextEvent.title, if (Preferences.showDiffTime && now.timeInMillis < nextEvent.startDate) {
|
|
||||||
if (!nextEvent.allDay) {
|
|
||||||
SettingsStringHelper.getDifferenceText(
|
|
||||||
context,
|
|
||||||
now.timeInMillis,
|
|
||||||
nextEvent.startDate
|
|
||||||
)
|
|
||||||
.toLowerCase(Locale.getDefault())
|
|
||||||
} else {
|
|
||||||
SettingsStringHelper.getAllDayEventDifferenceText(
|
|
||||||
context,
|
|
||||||
now.timeInMillis,
|
|
||||||
nextEvent.startDate
|
|
||||||
).toLowerCase(Locale.getDefault())
|
|
||||||
}
|
|
||||||
} else "").trimEnd()
|
|
||||||
bindingView.subLineIcon.isVisible = true
|
|
||||||
bindingView.subLineIcon.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(
|
|
||||||
context,
|
|
||||||
R.drawable.round_today_24
|
|
||||||
)
|
|
||||||
)
|
|
||||||
showSomething = true
|
|
||||||
break@loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (showSomething) {
|
|
||||||
bindingView.dateLayout.isVisible = true
|
|
||||||
bindingView.calendarLayout.isVisible = false
|
|
||||||
bindingView.subLine.isVisible = true
|
|
||||||
bindingView.weatherSubLine.isVisible = false
|
|
||||||
|
|
||||||
bindingView.subLineTopMarginSmall.visibility =
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.SMALL.rawValue) View.VISIBLE else View.GONE
|
|
||||||
bindingView.subLineTopMarginMedium.visibility =
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.MEDIUM.rawValue) View.VISIBLE else View.GONE
|
|
||||||
bindingView.subLineTopMarginLarge.visibility =
|
|
||||||
if (Preferences.secondRowTopMargin == Constants.SecondRowTopMargin.LARGE.rawValue) View.VISIBLE else View.GONE
|
|
||||||
} else {
|
|
||||||
bindingView.subLineIcon.isVisible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Color
|
|
||||||
listOf<TextView>(
|
|
||||||
bindingView.date,
|
|
||||||
bindingView.weatherDateLineTemperature,
|
|
||||||
bindingView.nextEvent,
|
|
||||||
bindingView.nextEventDifferenceTime,
|
|
||||||
).forEach {
|
|
||||||
it.setTextColor(ColorHelper.getFontColor(context.applicationContext.isDarkTheme()))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.rawValue) {
|
|
||||||
listOf<ImageView>(bindingView.actionNext)
|
|
||||||
} else {
|
|
||||||
listOf<ImageView>(
|
|
||||||
bindingView.actionNext,
|
|
||||||
bindingView.weatherDateLineWeatherIcon,
|
|
||||||
bindingView.weatherSubLineWeatherIcon
|
|
||||||
)
|
|
||||||
}.forEach {
|
|
||||||
it.setColorFilter(ColorHelper.getFontColorRgb(context.applicationContext.isDarkTheme()))
|
|
||||||
it.alpha =
|
|
||||||
(if (context.isDarkTheme()) Preferences.textGlobalAlphaDark.toIntValue()
|
|
||||||
.toFloat() else Preferences.textGlobalAlpha.toIntValue()
|
|
||||||
.toFloat()) / 100
|
|
||||||
}
|
|
||||||
|
|
||||||
listOf<TextView>(bindingView.subLineText, bindingView.weatherSubLineDivider, bindingView.weatherSubLineTemperature).forEach {
|
|
||||||
it.setTextColor(ColorHelper.getSecondaryFontColor(context.applicationContext.isDarkTheme()))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.rawValue) {
|
|
||||||
listOf<ImageView>(bindingView.subLineIcon, bindingView.subLineIconShadow)
|
|
||||||
} else {
|
|
||||||
listOf<ImageView>(bindingView.subLineIcon, bindingView.weatherSubLineWeatherIcon, bindingView.subLineIconShadow)
|
|
||||||
}.forEach {
|
|
||||||
it.setColorFilter(ColorHelper.getSecondaryFontColorRgb(context.applicationContext.isDarkTheme()))
|
|
||||||
it.alpha =
|
|
||||||
(if (context.isDarkTheme()) Preferences.textSecondaryAlphaDark.toIntValue()
|
|
||||||
.toFloat() else Preferences.textSecondaryAlpha.toIntValue()
|
|
||||||
.toFloat()) / 100
|
|
||||||
}
|
|
||||||
|
|
||||||
// Text Size
|
|
||||||
listOf<Pair<TextView, Float>>(
|
|
||||||
bindingView.date to Preferences.textMainSize,
|
|
||||||
bindingView.weatherDateLineTemperature to ((Preferences.textMainSize + Preferences.textSecondSize) / 2),
|
|
||||||
bindingView.nextEvent to Preferences.textMainSize,
|
|
||||||
bindingView.nextEventDifferenceTime to Preferences.textMainSize,
|
|
||||||
bindingView.subLineText to Preferences.textSecondSize,
|
|
||||||
bindingView.weatherSubLineDivider to (Preferences.textSecondSize - 2),
|
|
||||||
bindingView.weatherSubLineTemperature to Preferences.textSecondSize,
|
|
||||||
).forEach {
|
|
||||||
it.first.setTextSize(TypedValue.COMPLEX_UNIT_SP, it.second)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Icons scale
|
|
||||||
bindingView.subLineIcon.scaleX = Preferences.textSecondSize / 18f
|
|
||||||
bindingView.subLineIcon.scaleY = Preferences.textSecondSize / 18f
|
|
||||||
|
|
||||||
bindingView.weatherSubLineWeatherIcon.scaleX = Preferences.textSecondSize / 18f
|
|
||||||
bindingView.weatherSubLineWeatherIcon.scaleY = Preferences.textSecondSize / 18f
|
|
||||||
|
|
||||||
bindingView.weatherDateLineWeatherIcon.scaleX = ((Preferences.textMainSize + Preferences.textSecondSize) / 2) / 20f
|
|
||||||
bindingView.weatherDateLineWeatherIcon.scaleY = ((Preferences.textMainSize + Preferences.textSecondSize) / 2) / 20f
|
|
||||||
|
|
||||||
bindingView.actionNext.scaleX = Preferences.textMainSize / 28f
|
|
||||||
bindingView.actionNext.scaleY = Preferences.textMainSize / 28f
|
|
||||||
|
|
||||||
|
|
||||||
// Shadows
|
|
||||||
val shadowRadius =
|
|
||||||
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
|
||||||
0 -> 0f
|
|
||||||
1 -> 5f
|
|
||||||
2 -> 5f
|
|
||||||
else -> 5f
|
|
||||||
}
|
|
||||||
val shadowColor =
|
|
||||||
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
|
||||||
0 -> Color.TRANSPARENT
|
|
||||||
1 -> R.color.black_50
|
|
||||||
2 -> Color.BLACK
|
|
||||||
else -> R.color.black_50
|
|
||||||
}
|
|
||||||
val shadowDy =
|
|
||||||
when (if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) {
|
|
||||||
0 -> 0f
|
|
||||||
1 -> 0f
|
|
||||||
2 -> 1f
|
|
||||||
else -> 0f
|
|
||||||
}
|
|
||||||
|
|
||||||
listOf<TextView>(
|
|
||||||
bindingView.date,
|
|
||||||
bindingView.weatherDateLineTemperature,
|
|
||||||
bindingView.nextEvent,
|
|
||||||
bindingView.nextEventDifferenceTime,
|
|
||||||
bindingView.subLineText,
|
|
||||||
bindingView.weatherSubLineDivider,
|
|
||||||
bindingView.weatherSubLineTemperature,
|
|
||||||
).forEach {
|
|
||||||
it.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Icons shadow
|
|
||||||
|
|
||||||
listOf(
|
|
||||||
Pair(bindingView.subLineIcon, bindingView.subLineIconShadow),
|
|
||||||
).forEach {
|
|
||||||
if ((if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) == 0) {
|
|
||||||
it.second.isVisible = false
|
|
||||||
} else {
|
|
||||||
it.second.isVisible = it.first.isVisible
|
|
||||||
it.second.scaleX = it.first.scaleX
|
|
||||||
it.second.scaleY = it.first.scaleY
|
|
||||||
it.second.applyShadow(it.first)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
listOf(
|
|
||||||
Pair(bindingView.actionNext, bindingView.actionNextShadow),
|
|
||||||
).forEach {
|
|
||||||
if ((if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) == 0) {
|
|
||||||
it.second.isVisible = false
|
|
||||||
} else {
|
|
||||||
it.second.isVisible = it.first.isVisible
|
|
||||||
it.second.scaleX = it.first.scaleX
|
|
||||||
it.second.scaleY = it.first.scaleY
|
|
||||||
it.second.applyShadow(it.first, 0.6f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom Font
|
|
||||||
if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) {
|
|
||||||
val googleSans: Typeface = when (Preferences.customFontVariant) {
|
|
||||||
"100" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_thin.ttf")
|
|
||||||
"200" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_light.ttf")
|
|
||||||
"500" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_medium.ttf")
|
|
||||||
"700" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_bold.ttf")
|
|
||||||
"800" -> Typeface.createFromAsset(context.assets, "fonts/google_sans_black.ttf")
|
|
||||||
else -> Typeface.createFromAsset(context.assets, "fonts/google_sans_regular.ttf")
|
|
||||||
}
|
|
||||||
|
|
||||||
listOf<TextView>(
|
|
||||||
bindingView.date,
|
|
||||||
bindingView.weatherDateLineTemperature,
|
|
||||||
bindingView.nextEvent,
|
|
||||||
bindingView.nextEventDifferenceTime,
|
|
||||||
bindingView.subLineText,
|
|
||||||
bindingView.weatherSubLineDivider,
|
|
||||||
bindingView.weatherSubLineTemperature,
|
|
||||||
).forEach {
|
|
||||||
it.typeface = googleSans
|
|
||||||
}
|
|
||||||
} else if (Preferences.customFont == Constants.CUSTOM_FONT_DOWNLOADED && typeface != null) {
|
|
||||||
listOf<TextView>(
|
|
||||||
bindingView.date,
|
|
||||||
bindingView.weatherDateLineTemperature,
|
|
||||||
bindingView.nextEvent,
|
|
||||||
bindingView.nextEventDifferenceTime,
|
|
||||||
bindingView.subLineText,
|
|
||||||
bindingView.weatherSubLineDivider,
|
|
||||||
bindingView.weatherSubLineTemperature,
|
|
||||||
).forEach {
|
|
||||||
it.typeface = typeface
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dividers
|
|
||||||
arrayOf(bindingView.weatherSubLineDivider).forEach {
|
|
||||||
it.visibility = if (Preferences.showDividers) View.VISIBLE else View.INVISIBLE
|
|
||||||
it.layoutParams = (it.layoutParams as ViewGroup.MarginLayoutParams).apply {
|
|
||||||
this.marginEnd = if (Preferences.showDividers) 8f.convertDpToPixel(context).toInt() else 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eventRepository.close()
|
|
||||||
|
|
||||||
return bindingView
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,47 +1,20 @@
|
|||||||
package com.tommasoberlose.anotherwidget.ui.widgets
|
package com.tommasoberlose.anotherwidget.ui.widgets
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.app.PendingIntent
|
|
||||||
import android.appwidget.AppWidgetManager
|
import android.appwidget.AppWidgetManager
|
||||||
import android.appwidget.AppWidgetProvider
|
import android.appwidget.AppWidgetProvider
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.format.DateUtils
|
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.RemoteViews
|
import android.widget.RemoteViews
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.viewbinding.ViewBinding
|
|
||||||
import com.tommasoberlose.anotherwidget.R
|
|
||||||
import com.tommasoberlose.anotherwidget.databinding.LeftAlignedWidgetBinding
|
|
||||||
import com.tommasoberlose.anotherwidget.databinding.TheWidgetBinding
|
|
||||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Actions
|
|
||||||
import com.tommasoberlose.anotherwidget.global.Constants
|
import com.tommasoberlose.anotherwidget.global.Constants
|
||||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import com.tommasoberlose.anotherwidget.helpers.*
|
import com.tommasoberlose.anotherwidget.helpers.*
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
|
|
||||||
import com.tommasoberlose.anotherwidget.helpers.ImageHelper.applyShadow
|
|
||||||
import com.tommasoberlose.anotherwidget.receivers.*
|
import com.tommasoberlose.anotherwidget.receivers.*
|
||||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.convertDpToPixel
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
|
||||||
import com.tommasoberlose.anotherwidget.utils.toPixel
|
import com.tommasoberlose.anotherwidget.utils.toPixel
|
||||||
import java.text.DateFormat
|
import java.lang.Exception
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
|
|
||||||
class MainWidget : AppWidgetProvider() {
|
class MainWidget : AppWidgetProvider() {
|
||||||
@ -90,25 +63,34 @@ class MainWidget : AppWidgetProvider() {
|
|||||||
|
|
||||||
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager,
|
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager,
|
||||||
appWidgetId: Int) {
|
appWidgetId: Int) {
|
||||||
val displayMetrics = Resources.getSystem().displayMetrics
|
|
||||||
val width = displayMetrics.widthPixels
|
|
||||||
val height = displayMetrics.heightPixels
|
|
||||||
|
|
||||||
val dimensions = WidgetHelper.WidgetSizeProvider(context, appWidgetManager).getWidgetsSize(appWidgetId)
|
val dimensions = WidgetHelper.WidgetSizeProvider(context, appWidgetManager).getWidgetsSize(appWidgetId)
|
||||||
|
|
||||||
WidgetHelper.runWithCustomTypeface(context) {
|
WidgetHelper.runWithCustomTypeface(context) {
|
||||||
val views = when (Preferences.widgetAlign) {
|
val views = when (Preferences.widgetAlign) {
|
||||||
Constants.WidgetAlign.LEFT.rawValue -> LeftAlignedWidget(context).generateWidget(appWidgetId, min(dimensions.first - 8.toPixel(context), min(width, height) - 16.toPixel(context)), it)
|
Constants.WidgetAlign.LEFT.rawValue -> AlignedWidget(context).generateWidget(appWidgetId, dimensions.first, it)
|
||||||
else -> StandardWidget(context).generateWidget(appWidgetId, min(dimensions.first - 8.toPixel(context), min(width, height) - 16.toPixel(context)), it)
|
Constants.WidgetAlign.RIGHT.rawValue -> AlignedWidget(context, rightAligned = true).generateWidget(appWidgetId, dimensions.first, it)
|
||||||
|
else -> StandardWidget(context).generateWidget(appWidgetId, dimensions.first, it)
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (views != null) appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
}
|
}
|
||||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getWidgetView(context: Context, typeface: Typeface?): ViewBinding {
|
fun getWidgetView(context: Context, width: Int, typeface: Typeface?): RemoteViews? {
|
||||||
return when (Preferences.widgetAlign) {
|
return when (Preferences.widgetAlign) {
|
||||||
Constants.WidgetAlign.LEFT.rawValue -> LeftAlignedWidget(context).generateWidgetView(typeface)
|
Constants.WidgetAlign.LEFT.rawValue -> AlignedWidget(context).generateWidget(
|
||||||
else -> StandardWidget(context).generateWidgetView(typeface)
|
0,
|
||||||
|
width,
|
||||||
|
typeface
|
||||||
|
)
|
||||||
|
Constants.WidgetAlign.RIGHT.rawValue -> AlignedWidget(
|
||||||
|
context,
|
||||||
|
rightAligned = true
|
||||||
|
).generateWidget(0, width, typeface)
|
||||||
|
else -> StandardWidget(context).generateWidget(0, width, typeface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,18 +24,20 @@ import android.util.TypedValue
|
|||||||
import android.view.animation.AlphaAnimation
|
import android.view.animation.AlphaAnimation
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import androidx.annotation.UiThread
|
import androidx.annotation.UiThread
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.browser.customtabs.CustomTabColorSchemeParams
|
import androidx.browser.customtabs.CustomTabColorSchemeParams
|
||||||
import androidx.core.animation.addListener
|
import androidx.core.animation.addListener
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.tommasoberlose.anotherwidget.R
|
import com.tommasoberlose.anotherwidget.R
|
||||||
import com.tommasoberlose.anotherwidget.components.OnSingleClickListener
|
import com.tommasoberlose.anotherwidget.components.OnSingleClickListener
|
||||||
|
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
fun PackageManager.missingSystemFeature(name: String): Boolean = !hasSystemFeature(name)
|
fun PackageManager.missingSystemFeature(name: String): Boolean = !hasSystemFeature(name)
|
||||||
|
|
||||||
fun Context.toast(message: String, long: Boolean = false) {
|
fun Context.toast(message: String, long: Boolean = false) {
|
||||||
val toast = Toast.makeText(this, message, if (long) Toast.LENGTH_LONG else Toast.LENGTH_SHORT)
|
val toast = Toast.makeText(applicationContext, 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()
|
||||||
}
|
}
|
||||||
@ -192,7 +194,7 @@ fun String.isValidEmail(): Boolean
|
|||||||
Patterns.EMAIL_ADDRESS.matcher(this).matches()
|
Patterns.EMAIL_ADDRESS.matcher(this).matches()
|
||||||
|
|
||||||
fun Context.isDarkTheme(): Boolean {
|
fun Context.isDarkTheme(): Boolean {
|
||||||
return resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
|
return Preferences.darkThemePreference == AppCompatDelegate.MODE_NIGHT_YES || Preferences.darkThemePreference == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM && resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Activity.isNotificationAccessGranted(): Boolean = Settings.Secure.getString(this.contentResolver,"enabled_notification_listeners").contains(this.packageName)
|
fun Activity.isNotificationAccessGranted(): Boolean = Settings.Secure.getString(this.contentResolver,"enabled_notification_listeners").contains(this.packageName)
|
||||||
@ -265,3 +267,11 @@ fun View.setOnSingleClickListener(l: View.OnClickListener) {
|
|||||||
fun View.setOnSingleClickListener(l: (View) -> Unit) {
|
fun View.setOnSingleClickListener(l: (View) -> Unit) {
|
||||||
setOnClickListener(OnSingleClickListener(l))
|
setOnClickListener(OnSingleClickListener(l))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ignoreExceptions(function: () -> Unit) = run {
|
||||||
|
try {
|
||||||
|
function.invoke()
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 674 B After Width: | Height: | Size: 750 B |
BIN
app/src/main/res/drawable-hdpi/round_border_outer_black_18.png
Normal file
After Width: | Height: | Size: 180 B |
BIN
app/src/main/res/drawable-hdpi/round_border_outer_black_20.png
Normal file
After Width: | Height: | Size: 186 B |
BIN
app/src/main/res/drawable-hdpi/round_border_outer_black_24.png
Normal file
After Width: | Height: | Size: 188 B |
BIN
app/src/main/res/drawable-hdpi/round_border_outer_black_36.png
Normal file
After Width: | Height: | Size: 246 B |
BIN
app/src/main/res/drawable-hdpi/round_border_outer_black_48.png
Normal file
After Width: | Height: | Size: 252 B |
BIN
app/src/main/res/drawable-hdpi/round_dark_mode_white_18.png
Normal file
After Width: | Height: | Size: 246 B |
BIN
app/src/main/res/drawable-hdpi/round_dark_mode_white_20.png
Normal file
After Width: | Height: | Size: 281 B |
BIN
app/src/main/res/drawable-hdpi/round_dark_mode_white_24.png
Normal file
After Width: | Height: | Size: 325 B |
BIN
app/src/main/res/drawable-hdpi/round_dark_mode_white_36.png
Normal file
After Width: | Height: | Size: 451 B |
BIN
app/src/main/res/drawable-hdpi/round_dark_mode_white_48.png
Normal file
After Width: | Height: | Size: 571 B |
BIN
app/src/main/res/drawable-hdpi/round_more_time_white_18.png
Normal file
After Width: | Height: | Size: 428 B |
BIN
app/src/main/res/drawable-hdpi/round_more_time_white_20.png
Normal file
After Width: | Height: | Size: 448 B |
BIN
app/src/main/res/drawable-hdpi/round_more_time_white_24.png
Normal file
After Width: | Height: | Size: 436 B |
BIN
app/src/main/res/drawable-hdpi/round_more_time_white_36.png
Normal file
After Width: | Height: | Size: 779 B |
BIN
app/src/main/res/drawable-hdpi/round_more_time_white_48.png
Normal file
After Width: | Height: | Size: 867 B |
BIN
app/src/main/res/drawable-hdpi/round_select_all_black_18.png
Normal file
After Width: | Height: | Size: 217 B |
BIN
app/src/main/res/drawable-hdpi/round_select_all_black_20.png
Normal file
After Width: | Height: | Size: 212 B |
BIN
app/src/main/res/drawable-hdpi/round_select_all_black_24.png
Normal file
After Width: | Height: | Size: 221 B |
BIN
app/src/main/res/drawable-hdpi/round_select_all_black_36.png
Normal file
After Width: | Height: | Size: 282 B |
BIN
app/src/main/res/drawable-hdpi/round_select_all_black_48.png
Normal file
After Width: | Height: | Size: 268 B |
BIN
app/src/main/res/drawable-hdpi/round_subtitles_white_18.png
Normal file
After Width: | Height: | Size: 224 B |
BIN
app/src/main/res/drawable-hdpi/round_subtitles_white_20.png
Normal file
After Width: | Height: | Size: 195 B |
BIN
app/src/main/res/drawable-hdpi/round_subtitles_white_24.png
Normal file
After Width: | Height: | Size: 170 B |
BIN
app/src/main/res/drawable-hdpi/round_subtitles_white_36.png
Normal file
After Width: | Height: | Size: 290 B |
BIN
app/src/main/res/drawable-hdpi/round_subtitles_white_48.png
Normal file
After Width: | Height: | Size: 267 B |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 381 B After Width: | Height: | Size: 563 B |