Compare commits

...

44 Commits

Author SHA1 Message Date
c595168320 Merge develop 2021-01-06 17:33:24 +01:00
61e3e43fd7 Publish v2.1.1 2021-01-06 17:30:42 +01:00
1513b96313 Bugfixes, fix #257 2021-01-06 17:26:32 +01:00
536ed64d41 Default temp unit and weather provider based on locale 2021-01-05 11:08:13 +01:00
5b2d245e80 Merge develop 2021-01-04 12:07:59 +01:00
0aec34dcd2 Bugfixes 2021-01-04 12:04:25 +01:00
b2a9b9fbb3 Fix #255 2021-01-03 17:51:31 +01:00
768f04825e Building 2021-01-03 17:25:00 +01:00
80ee877bf2 Merge pull request #252 from devindang/master
Update new strings for Chinese Simplified
2021-01-03 17:24:18 +01:00
ac7839ecdc Merge pull request #244 from Moutony/patch-25
Update French Greetings
2021-01-03 17:24:11 +01:00
66d0214cd9 Move the location updates to a foreground service and fix multiple bugs 2021-01-03 17:23:22 +01:00
e069b8f6ab greetings 2020-11-27 23:47:13 +08:00
8a681f0cd7 Update New Strings 2020-11-25 20:46:02 +08:00
92158ec5f2 Update strings.xml 2020-11-22 12:21:56 +01:00
ebb37f21ed Remove useless icons 2020-10-30 19:26:01 +01:00
2a389cb422 Update strings.xml 2020-10-29 12:12:27 +01:00
4504a0617e Update Fitness in Glance 2020-10-28 14:58:22 +01:00
9ed34ee17e Update French Greetings
Thanks for adding antislash before apostrophes. I always forget it haha
But, in French typography, there is a (narrow) no-break space U+202F before these punctuations ! ? ; :
2020-10-28 14:47:11 +01:00
a7294edfd4 Fix notification listener 2020-10-27 18:28:21 +01:00
49ca17803e Update translations 2020-10-27 18:21:55 +01:00
97ab72081d Update the UI 2020-10-27 18:13:27 +01:00
e6fee0dfe1 Merge branch 'master' of github.com:tommasoberlose/another-widget into develop 2020-10-27 18:13:15 +01:00
e0c4f24c43 Merge pull request #239 from Vgbhieel/master
Added Portuguese translation (values-pt)
2020-10-27 18:13:02 +01:00
2a7d0f171b Create strings,xml for portuguese values
translated all strings to portuguese
2020-10-23 00:55:39 -03:00
00dcfc3149 Merge branch 'master' of github.com:tommasoberlose/another-widget into develop 2020-10-20 10:39:19 +02:00
eb11b603aa Merge pull request #235 from Moutony/patch-24
Update French 2
2020-10-20 10:39:01 +02:00
4d2f624448 Merge branch 'master' of github.com:tommasoberlose/another-widget into develop 2020-10-20 10:38:47 +02:00
7581af4dd2 Merge branch 'english-strings' 2020-10-20 10:38:19 +02:00
0325af6582 Fix uppercase labels 2020-10-20 10:35:54 +02:00
4de0413a35 Fix multiple bugs 2020-10-20 10:27:05 +02:00
c54a24c889 Update strings.xml 2020-10-19 21:54:51 +02:00
98eccd2833 Update strings.xml 2020-10-19 21:54:17 +02:00
0119a20765 Update strings.xml 2020-10-19 21:51:12 +02:00
a1e54892fd Update strings.xml 2020-10-19 16:28:38 +02:00
17801fd164 Update strings.xml 2020-10-19 16:26:57 +02:00
e6087b2969 Merge pull request #234 from Moutony/patch-23
Update French
2020-10-19 15:35:06 +02:00
59b8ba26a2 Merge pull request #232 from d-l-n/master
Added and translated new strings
2020-10-19 15:35:01 +02:00
f190ee5d15 Merge pull request #231 from Drumber/translation
Update German translation
2020-10-19 15:34:48 +02:00
2f266ffcf8 Update strings.xml 2020-10-19 11:07:05 +02:00
0e376aba80 Update strings.xml 2020-10-19 11:06:29 +02:00
313e4fa92d Update French 2020-10-19 11:01:21 +02:00
a8ec754bc4 Added and translated new strings 2020-10-19 01:04:33 -03:00
f8d1188634 Update strings.xml
Added greetings and notification timeout strings
2020-10-18 18:47:52 +02:00
8216fc96b9 Update English strings.xml
Removed OpenWeatherMap former instructions.
Capitalized all action buttons.
name="action_save" translatable="false">OK
2020-10-18 16:15:22 +02:00
2481 changed files with 1303 additions and 496 deletions

5
.gitignore vendored
View File

@ -8,4 +8,7 @@
.externalNativeBuild
/tasksintegration/build
/app/google-services.json
apikey.properties
apikey.properties
./.idea/*
app/release/*
/app/release/*

View File

@ -123,6 +123,29 @@
</PersistentState>
</value>
</entry>
<entry key="vectorWizard">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="vectorAssetStep">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="assetSourceType" value="FILE" />
<entry key="outputName" value="round_aspect_ratio_24" />
<entry key="sourceFile" value="$USER_HOME$/Desktop/round_aspect_ratio_24.svg" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</component>

Binary file not shown.

View File

@ -16,15 +16,15 @@ apikeyProperties.load(new FileInputStream(apikeyPropertiesFile))
android {
compileSdkVersion 29
compileSdkVersion 30
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.tommasoberlose.anotherwidget"
minSdkVersion 23
targetSdkVersion 29
versionCode 109
versionName "2.0.15"
targetSdkVersion 30
versionCode 115
versionName "2.1.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY'])
@ -72,9 +72,9 @@ dependencies {
// UI
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
implementation 'com.google.android.material:material:1.3.0-alpha03'
implementation 'androidx.browser:browser:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'com.google.android.material:material:1.3.0-beta01'
implementation 'androidx.browser:browser:1.3.0'
implementation 'net.idik:slimadapter:2.1.2'
implementation 'com.google.android:flexbox:2.0.1'
@ -89,8 +89,8 @@ dependencies {
implementation 'org.greenrobot:eventbus:3.2.0'
// Navigation
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.2'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.2'
// Other
implementation 'androidx.multidex:multidex:2.0.1'
@ -103,7 +103,7 @@ dependencies {
kapt 'com.github.bumptech.glide:compiler:4.11.0'
// Fitness
implementation 'com.google.android.gms:play-services-fitness:18.0.0'
implementation 'com.google.android.gms:play-services-fitness:20.0.0'
implementation 'com.google.android.gms:play-services-auth:18.1.0'
//Weather
@ -111,8 +111,8 @@ dependencies {
implementation 'com.google.android.gms:play-services-location:17.1.0'
// Billing
implementation 'com.android.billingclient:billing:3.0.1'
implementation 'com.android.billingclient:billing-ktx:3.0.1'
implementation 'com.android.billingclient:billing:3.0.2'
implementation 'com.android.billingclient:billing-ktx:3.0.2'
// KTX
implementation "androidx.core:core-ktx:1.3.2"
@ -128,10 +128,10 @@ dependencies {
implementation "com.github.haroldadmin:NetworkResponseAdapter:4.0.1"
//Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
// Add the Firebase SDK for Crashlytics.
implementation 'com.google.firebase:firebase-crashlytics:17.2.2'
implementation 'com.google.firebase:firebase-crashlytics:17.3.0'
// Preferences
implementation 'com.chibatching.kotpref:kotpref:2.11.0'

Binary file not shown.

View File

@ -5,7 +5,6 @@
<uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="com.android.vending.BILLING" />
@ -13,7 +12,7 @@
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.gms.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:allowBackup="true"
@ -154,6 +153,17 @@
android:name=".services.UpdateCalendarJob"
android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true"/>
<service
android:name=".services.LocationService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="location" />
</application>
<queries>
<package android:name="com.google.android.apps.fitness"/>
<intent>
<action android:name="android.intent.action.MAIN" />
</intent>
</queries>
</manifest>

View File

@ -24,6 +24,7 @@ import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.helpers.ColorHelper
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.isColorDark
import com.tommasoberlose.anotherwidget.utils.expand
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
import com.tommasoberlose.anotherwidget.utils.reveal
import com.tommasoberlose.anotherwidget.utils.toPixel
import com.warkiz.widget.IndicatorSeekBar
@ -93,6 +94,7 @@ class BottomSheetColorPicker(
injector
.with<MaterialCardView>(R.id.color) {
it.setCardBackgroundColor(ColorStateList.valueOf(item))
it.strokeWidth = if ((colors.indexOf(item) == 0 && !context.isDarkTheme()) || (colors.indexOf(item) == 10 && context.isDarkTheme())) 2 else 0
}
.with<AppCompatImageView>(R.id.check) {
if (getSelected?.invoke() == item) {

View File

@ -9,7 +9,7 @@ import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.global.Preferences
import kotlinx.android.synthetic.main.custom_notes_dialog_layout.view.*
class CustomNotesDialog(context: Context) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
class CustomNotesDialog(context: Context, callback: (() -> Unit)?) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
init {
val view = View.inflate(context, R.layout.custom_notes_dialog_layout, null)
@ -18,6 +18,7 @@ class CustomNotesDialog(context: Context) : BottomSheetDialog(context, R.style.B
view.action_positive.setOnClickListener {
Preferences.customNotes = view.notes.text.toString()
this.dismiss()
callback?.invoke()
}
view.notes.requestFocus()

View File

@ -7,6 +7,7 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.util.EventLog
import android.util.Log
import android.view.View
import androidx.core.app.NotificationManagerCompat
@ -30,9 +31,11 @@ import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
import com.tommasoberlose.anotherwidget.ui.activities.AppNotificationsFilterActivity
import com.tommasoberlose.anotherwidget.ui.activities.MusicPlayersFilterActivity
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import kotlinx.android.synthetic.main.glance_provider_settings_layout.view.*
import kotlinx.coroutines.*
import org.greenrobot.eventbus.EventBus
class GlanceSettingsDialog(val context: Activity, val provider: Constants.GlanceProviderId, private val statusCallback: (() -> Unit)?) : BottomSheetDialog(context, R.style.BottomSheetDialogTheme) {
@ -48,6 +51,7 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> context.getString(R.string.settings_daily_steps_title)
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_title)
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_title)
Constants.GlanceProviderId.EVENTS -> context.getString(R.string.settings_show_events_as_glance_provider_title)
}
/* SUBTITLE*/
@ -59,6 +63,7 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> context.getString(R.string.settings_daily_steps_subtitle)
Constants.GlanceProviderId.NOTIFICATIONS -> context.getString(R.string.settings_show_notifications_subtitle)
Constants.GlanceProviderId.GREETINGS -> context.getString(R.string.settings_show_greetings_subtitle)
Constants.GlanceProviderId.EVENTS -> context.getString(R.string.settings_show_events_as_glance_provider_subtitle)
}
/* SONG */
@ -124,6 +129,13 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
view.divider.isVisible = false
}
/* EVENTS */
if (provider == Constants.GlanceProviderId.EVENTS) {
view.header.isVisible = false
view.divider.isVisible = false
checkCalendarConfig(view)
}
/* TOGGLE */
view.provider_switch.isChecked = when (provider) {
Constants.GlanceProviderId.PLAYING_SONG -> Preferences.showMusic
@ -133,6 +145,7 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> Preferences.showDailySteps
Constants.GlanceProviderId.NOTIFICATIONS -> Preferences.showNotifications
Constants.GlanceProviderId.GREETINGS -> Preferences.showGreetings
Constants.GlanceProviderId.EVENTS -> Preferences.showEventsAsGlanceProvider
}
var job: Job? = null
@ -188,6 +201,9 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
checkFitnessPermission(view)
checkGoogleFitConnection(view)
}
Constants.GlanceProviderId.EVENTS -> {
Preferences.showEventsAsGlanceProvider = isChecked
}
else -> {
}
}
@ -220,6 +236,19 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
statusCallback?.invoke()
}
private fun checkCalendarConfig(view: View) {
if (!Preferences.showEvents || !context.checkGrantedPermission(Manifest.permission.READ_CALENDAR)) {
view.warning_container.isVisible = true
view.warning_title.text = context.getString(R.string.settings_show_events_as_glance_provider_error)
view.warning_container.setOnClickListener {
dismiss()
EventBus.getDefault().post(MainFragment.ChangeTabEvent(1))
}
} else {
view.warning_container.isVisible = false
}
}
private fun checkNotificationPermission(view: View) {
when {
ActiveNotificationsHelper.checkNotificationAccess(context) -> {

View File

@ -32,7 +32,8 @@ object Constants {
CUSTOM_INFO("CUSTOM_INFO"),
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS"),
NOTIFICATIONS("NOTIFICATIONS"),
GREETINGS("GREETINGS");
GREETINGS("GREETINGS"),
EVENTS("EVENTS");
companion object {
private val map = GlanceProviderId.values().associateBy(GlanceProviderId::id)

View File

@ -2,7 +2,10 @@ package com.tommasoberlose.anotherwidget.global
import android.os.Build
import androidx.appcompat.app.AppCompatDelegate.*
import androidx.core.os.ConfigurationCompat
import com.chibatching.kotpref.KotprefModel
import com.tommasoberlose.anotherwidget.utils.isMetric
import java.util.*
object Preferences : KotprefModel() {
override val commitAllPropertiesByDefault: Boolean = true
@ -14,8 +17,8 @@ object Preferences : KotprefModel() {
var showWeather by booleanPref(key = "PREF_SHOW_WEATHER", default = false)
var weatherIcon by stringPref(key = "PREF_WEATHER_ICON", default = "")
var weatherTemp by floatPref(key = "PREF_WEATHER_TEMP", default = 0f)
var weatherTempUnit by stringPref(key = "PREF_WEATHER_TEMP_UNIT", default = "F")
var weatherRealTempUnit by stringPref(key = "PREF_WEATHER_REAL_TEMP_UNIT", default = "F")
var weatherTempUnit by stringPref(key = "PREF_WEATHER_TEMP_UNIT", default = if (ConfigurationCompat.getLocales(context.resources.configuration)[0].isMetric()) "C" else "F")
var weatherRealTempUnit by stringPref(key = "PREF_WEATHER_REAL_TEMP_UNIT", default = if (ConfigurationCompat.getLocales(context.resources.configuration)[0].isMetric()) "C" else "F")
var calendarAllDay by booleanPref(key = "PREF_CALENDAR_ALL_DAY", default = true)
var calendarFilter by stringPref(key = "PREF_CALENDAR_FILTER", default = "")
@ -43,7 +46,7 @@ object Preferences : KotprefModel() {
var weatherProviderApiWeatherApi by stringPref(default = "")
var weatherProviderApiWeatherBit by stringPref(default = "")
var weatherProviderApiAccuweather by stringPref(default = "")
var weatherProvider by intPref(default = Constants.WeatherProvider.OPEN_WEATHER.value)
var weatherProvider by intPref(default = if (ConfigurationCompat.getLocales(context.resources.configuration)[0].isMetric()) Constants.WeatherProvider.YR.value else Constants.WeatherProvider.WEATHER_GOV.value)
var weatherProviderError by stringPref(default = "")
var weatherProviderLocationError by stringPref(default = "")
var eventAppName by stringPref(key = "PREF_EVENT_APP_NAME", default = "")
@ -141,6 +144,8 @@ object Preferences : KotprefModel() {
var musicPlayersFilter by stringPref(default = "")
var appNotificationsFilter by stringPref(default = "")
var showEventsAsGlanceProvider by booleanPref(default = false)
// Integrations
var installedIntegrations by intPref(default = 0)
}

View File

@ -9,6 +9,7 @@ import com.chibatching.kotpref.Kotpref
import com.chibatching.kotpref.blockingBulk
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.receivers.NotificationListener
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
object ActiveNotificationsHelper {
fun showLastNotification(): Boolean {
@ -23,6 +24,7 @@ object ActiveNotificationsHelper {
remove(Preferences::lastNotificationPackage)
remove(Preferences::lastNotificationIcon)
}
MainWidget.updateWidget(context)
}
fun checkNotificationAccess(context: Context): Boolean {

View File

@ -1,5 +1,6 @@
package com.tommasoberlose.anotherwidget.helpers
import android.Manifest
import android.content.Context
import android.util.Log
import com.tommasoberlose.anotherwidget.R
@ -7,6 +8,7 @@ import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.models.GlanceProvider
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.checkIfFitInstalled
import java.util.ArrayList
@ -20,7 +22,7 @@ object GlanceProviderHelper {
}
.toTypedArray()
providers.sortWith(Comparator { p1, p2 ->
return ArrayList(providers.filter { enabledProviders.contains(it.id) }.sortedWith(Comparator { p1, p2 ->
when {
enabledProviders.contains(p1.id) && enabledProviders.contains(p2.id) -> {
enabledProviders.indexOf(p1.id).compareTo(enabledProviders.indexOf(p2.id))
@ -35,8 +37,7 @@ object GlanceProviderHelper {
p1.id.compareTo(p2.id)
}
}
})
return ArrayList(providers.toList())
}) + providers.filter { !enabledProviders.contains(it.id) })
}
fun getGlanceProviderById(context: Context, providerId: Constants.GlanceProviderId): GlanceProvider? {
@ -44,49 +45,55 @@ object GlanceProviderHelper {
Constants.GlanceProviderId.NEXT_CLOCK_ALARM -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_show_next_alarm_title),
R.drawable.round_access_alarm
R.drawable.round_access_alarm_24
)
}
Constants.GlanceProviderId.PLAYING_SONG -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_show_music_title),
R.drawable.round_music_note
R.drawable.round_music_note_24
)
}
Constants.GlanceProviderId.CUSTOM_INFO -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_custom_notes_title),
R.drawable.round_sticky_note_2
R.drawable.round_sticky_note_2_24
)
}
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_low_battery_level_title),
R.drawable.round_battery_charging_full
R.drawable.round_battery_charging_full_24
)
}
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_daily_steps_title),
R.drawable.round_near_me
R.drawable.round_favorite_border_24
)
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_show_notifications_title),
R.drawable.round_notifications
R.drawable.round_notifications_24
)
}
Constants.GlanceProviderId.GREETINGS -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_show_greetings_title),
R.drawable.round_history_edu
R.drawable.round_history_edu_24
)
}
Constants.GlanceProviderId.EVENTS -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_show_events_as_glance_provider_title),
R.drawable.round_event_note_24
)
}
}
}
fun saveGlanceProviderOrder(list: ArrayList<Constants.GlanceProviderId>) {
fun saveGlanceProviderOrder(list: List<Constants.GlanceProviderId>) {
Preferences.enabledGlanceProviderOrder = list.joinToString(separator = ",")
}
@ -94,7 +101,7 @@ object GlanceProviderHelper {
val eventRepository = EventRepository(context)
BatteryHelper.updateBatteryInfo(context)
val showGlance = Preferences.showGlance && (eventRepository.getEventsCount() == 0 || !Preferences.showEvents)
val showGlance = Preferences.showGlance && (eventRepository.getEventsCount() == 0 || !Preferences.showEvents || Preferences.showEventsAsGlanceProvider)
&& (
(Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) ||
(Preferences.showNextAlarm && AlarmHelper.getNextAlarm(context) != "") ||
@ -102,7 +109,9 @@ object GlanceProviderHelper {
(Preferences.showBatteryCharging && Preferences.isCharging || Preferences.isBatteryLevelLow) ||
(Preferences.customNotes.isNotEmpty()) ||
(Preferences.showDailySteps && Preferences.googleFitSteps > 0) ||
(Preferences.showGreetings && GreetingsHelper.showGreetings())
(Preferences.showGreetings && GreetingsHelper.showGreetings()) ||
(Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(
Manifest.permission.READ_CALENDAR) && eventRepository.getNextEvent() != null)
)
eventRepository.close()
return showGlance

View File

@ -10,6 +10,7 @@ import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
import com.tommasoberlose.anotherwidget.services.LocationService
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
@ -31,26 +32,8 @@ object WeatherHelper {
val networkApi = WeatherNetworkApi(context)
if (Preferences.customLocationAdd != "") {
networkApi.updateWeather()
} else if (context.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION)) {
LocationServices.getFusedLocationProviderClient(context).lastLocation.addOnCompleteListener { task ->
if (task.isSuccessful) {
val location = task.result
if (location != null) {
Preferences.customLocationLat = location.latitude.toString()
Preferences.customLocationLon = location.longitude.toString()
}
CoroutineScope(Dispatchers.IO).launch {
networkApi.updateWeather()
}
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} else {
CoroutineScope(Dispatchers.IO).launch {
networkApi.updateWeather()
}
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
}
}
} else if (context.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
LocationService.requestNewLocation(context)
}
}

View File

@ -8,6 +8,7 @@ import android.os.Build
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import android.util.Log
import android.widget.Toast
import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
@ -33,24 +34,19 @@ class NotificationListener : NotificationListenerService() {
val isGroupHeader = sbn.notification.flags and Notification.FLAG_GROUP_SUMMARY != 0
val isOngoing = sbn.notification.flags and Notification.FLAG_ONGOING_EVENT != 0
if (bundle.containsKey(Notification.EXTRA_TITLE) && !isGroupHeader && !isOngoing && ActiveNotificationsHelper.isAppAccepted(sbn.packageName)) {
if (bundle.containsKey(Notification.EXTRA_TITLE) && !isGroupHeader && !isOngoing && ActiveNotificationsHelper.isAppAccepted(sbn.packageName) && !sbn.packageName.contains("com.android.systemui")) {
Preferences.lastNotificationId = sbn.id
Preferences.lastNotificationTitle = bundle.getString(Notification.EXTRA_TITLE) ?: ""
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
try {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
Preferences.lastNotificationIcon = sbn.notification.smallIcon.resId
} catch (ex: Exception) {
Preferences.lastNotificationIcon = 0
}
Preferences.lastNotificationPackage = sbn.notification.smallIcon.resPackage
} else {
try {
} else {
Preferences.lastNotificationIcon = sbn.notification.icon
} catch (ex: Exception) {
Preferences.lastNotificationIcon = 0
}
Preferences.lastNotificationPackage = sbn.packageName
} catch (ex: Exception) {
Preferences.lastNotificationIcon = 0
}
Preferences.lastNotificationPackage = sbn.packageName
MainWidget.updateWidget(this)
setTimeout(this)
}

View File

@ -33,9 +33,9 @@ class UpdatesReceiver : BroadcastReceiver() {
Intent.ACTION_LOCALE_CHANGED,
Intent.ACTION_DATE_CHANGED,
Actions.ACTION_CALENDAR_UPDATE -> {
CalendarHelper.updateEventList(context)
ActiveNotificationsHelper.clearLastNotification(context)
MediaPlayerHelper.updatePlayingMediaInfo(context)
CalendarHelper.updateEventList(context)
}
"com.sec.android.widgetapp.APPWIDGET_RESIZE",

View File

@ -0,0 +1,129 @@
package com.tommasoberlose.anotherwidget.services
import android.Manifest
import android.app.*
import android.app.job.JobScheduler
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.location.Address
import android.location.Geocoder
import android.os.IBinder
import android.util.Log
import androidx.core.app.*
import androidx.core.content.ContextCompat
import com.google.android.gms.location.LocationServices
import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.network.WeatherNetworkApi
import com.tommasoberlose.anotherwidget.ui.activities.MainActivity
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
import kotlinx.coroutines.*
import org.greenrobot.eventbus.EventBus
import java.lang.Exception
import java.util.*
import kotlin.collections.ArrayList
class LocationService : Service() {
private val jobs: ArrayList<Job> = ArrayList()
override fun onCreate() {
super.onCreate()
startForeground(LOCATION_ACCESS_NOTIFICATION_ID, getLocationAccessNotification())
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
) {
jobs += GlobalScope.launch(Dispatchers.IO) {
LocationServices.getFusedLocationProviderClient(this@LocationService).lastLocation.addOnCompleteListener { task ->
val networkApi = WeatherNetworkApi(this@LocationService)
if (task.isSuccessful) {
val location = task.result
if (location != null) {
Preferences.customLocationLat = location.latitude.toString()
Preferences.customLocationLon = location.longitude.toString()
}
CoroutineScope(Dispatchers.IO).launch {
networkApi.updateWeather()
withContext(Dispatchers.Main) {
stopSelf()
}
}
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
} else {
CoroutineScope(Dispatchers.IO).launch {
networkApi.updateWeather()
withContext(Dispatchers.Main) {
stopSelf()
}
}
EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent())
}
}
}
} else {
stopSelf()
}
return START_STICKY
}
override fun onDestroy() {
super.onDestroy()
jobs.forEach {
it.cancel()
}
}
companion object {
const val LOCATION_ACCESS_NOTIFICATION_ID = 28465
@JvmStatic
fun requestNewLocation(context: Context) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
context.startForegroundService(Intent(context, LocationService::class.java))
} else {
context.startService(Intent(context, LocationService::class.java))
}
}
}
override fun onBind(intent: Intent?): IBinder? {
return null
}
private fun getLocationAccessNotification(): Notification {
with(NotificationManagerCompat.from(this)) {
// Create channel
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
createNotificationChannel(
NotificationChannel(
getString(R.string.location_access_notification_channel_id),
getString(R.string.location_access_notification_channel_name),
NotificationManager.IMPORTANCE_LOW
).apply {
description = getString(R.string.location_access_notification_channel_description)
}
)
}
val builder = NotificationCompat.Builder(this@LocationService, getString(R.string.location_access_notification_channel_id))
.setSmallIcon(R.drawable.ic_stat_notification)
.setContentTitle(getString(R.string.location_access_notification_title))
.setStyle(NotificationCompat.BigTextStyle().bigText(getString(R.string.location_access_notification_subtitle)))
.setOngoing(true)
.setColor(ContextCompat.getColor(this@LocationService, R.color.colorAccent))
// Main intent that open the activity
builder.setContentIntent(PendingIntent.getActivity(this@LocationService, 0, Intent(this@LocationService, MainActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT))
return builder.build()
}
}
}

View File

@ -85,6 +85,24 @@ class UpdateCalendarJob : JobIntentService() {
instance.end =
end.timeInMillis - end.timeZone.getOffset(end.timeInMillis)
}
// Check all day events
val startDate = Calendar.getInstance()
startDate.timeInMillis = instance.begin
val endDate = Calendar.getInstance()
endDate.timeInMillis = instance.end
val isAllDay = e.allDay || (
startDate.get(Calendar.MILLISECOND) == 0
&& startDate.get(Calendar.SECOND) == 0
&& startDate.get(Calendar.MINUTE) == 0
&& startDate.get(Calendar.HOUR_OF_DAY) == 0
&& endDate.get(Calendar.MILLISECOND) == 0
&& endDate.get(Calendar.SECOND) == 0
&& endDate.get(Calendar.MINUTE) == 0
&& endDate.get(Calendar.HOUR_OF_DAY) == 0
)
eventList.add(
Event(
id = instance.id,
@ -93,7 +111,7 @@ class UpdateCalendarJob : JobIntentService() {
startDate = instance.begin,
endDate = instance.end,
calendarID = e.calendarId.toInt(),
allDay = e.allDay,
allDay = isAllDay,
address = e.eventLocation ?: "",
selfAttendeeStatus = e.selfAttendeeStatus.toInt(),
availability = e.availability

View File

@ -53,7 +53,7 @@ class ChooseApplicationActivity : AppCompatActivity() {
.register<String>(R.layout.application_info_layout) { _, injector ->
injector
.text(R.id.text, getString(R.string.default_name))
.image(R.id.icon, R.drawable.round_add_to_home_screen)
.image(R.id.icon, R.drawable.round_add_to_home_screen_24)
.with<ImageView>(R.id.icon) {
it.scaleX = 0.8f
it.scaleY = 0.8f

View File

@ -69,11 +69,7 @@ class CustomLocationActivity : AppCompatActivity() {
injector
.text(R.id.text, getString(R.string.custom_location_gps))
.clicked(R.id.text) {
MaterialBottomSheetDialog(this, message = getString(R.string.background_location_warning))
.setPositiveButton(getString(android.R.string.ok)) {
requirePermission()
}
.show()
requirePermission()
}
}
.register<Address>(R.layout.custom_location_item) { item, injector ->
@ -140,7 +136,7 @@ class CustomLocationActivity : AppCompatActivity() {
private fun requirePermission() {
Dexter.withContext(this)
.withPermissions(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
Manifest.permission.ACCESS_FINE_LOCATION
).withListener(object: MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
report?.let {

View File

@ -129,7 +129,7 @@ class WeatherProviderActivity : AppCompatActivity() {
it.isVisible = false
}
}
.image(R.id.action_configure, ContextCompat.getDrawable(this, if (WeatherHelper.isKeyRequired(provider)) R.drawable.round_settings else R.drawable.outline_info_white))
.image(R.id.action_configure, ContextCompat.getDrawable(this, if (WeatherHelper.isKeyRequired(provider)) R.drawable.round_settings_24 else R.drawable.outline_info_24))
}.attachTo(list_view)
adapter.updateData(

View File

@ -15,7 +15,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.databinding.DataBindingUtil
@ -51,7 +50,6 @@ import kotlinx.android.synthetic.main.fragment_glance_settings.*
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.idik.lib.slimadapter.SlimAdapter
import java.util.*
class GlanceTabFragment : Fragment() {
@ -63,6 +61,7 @@ class GlanceTabFragment : Fragment() {
private var dialog: GlanceSettingsDialog? = null
private lateinit var adapter: SlimAdapter
private lateinit var viewModel: MainViewModel
private lateinit var list: ArrayList<Constants.GlanceProviderId>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -84,6 +83,8 @@ class GlanceTabFragment : Fragment() {
binding.lifecycleOwner = this
binding.viewModel = viewModel
list = GlanceProviderHelper.getGlanceProviders(requireContext())
return binding.root
}
@ -107,7 +108,9 @@ class GlanceTabFragment : Fragment() {
.clicked(R.id.item) {
if (Preferences.showGlance) {
if (provider == Constants.GlanceProviderId.CUSTOM_INFO) {
CustomNotesDialog(requireContext()).show()
CustomNotesDialog(requireContext()){
adapter.notifyItemRangeChanged(0, adapter.data.size)
}.show()
} else {
dialog = GlanceSettingsDialog(requireActivity(), provider) {
adapter.notifyItemRangeChanged(0, adapter.data.size)
@ -119,6 +122,7 @@ class GlanceTabFragment : Fragment() {
}
}
}
var isVisible = false
when (provider) {
Constants.GlanceProviderId.PLAYING_SONG -> {
when {
@ -129,16 +133,19 @@ class GlanceTabFragment : Fragment() {
injector.text(R.id.label,
if (Preferences.showMusic) getString(R.string.settings_visible) else getString(
R.string.settings_not_visible))
isVisible = Preferences.showMusic
}
Preferences.showMusic -> {
injector.visibility(R.id.error_icon, View.VISIBLE)
injector.visibility(R.id.info_icon, View.GONE)
injector.text(R.id.label, getString(R.string.settings_not_visible))
isVisible = false
}
else -> {
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
injector.text(R.id.label, getString(R.string.settings_not_visible))
isVisible = false
}
}
}
@ -156,6 +163,8 @@ class GlanceTabFragment : Fragment() {
if (!(Preferences.showNextAlarm && AlarmHelper.isAlarmProbablyWrong(
requireContext()))
) View.VISIBLE else View.GONE)
isVisible = !(Preferences.showNextAlarm && AlarmHelper.isAlarmProbablyWrong(
requireContext()))
}
Constants.GlanceProviderId.BATTERY_LEVEL_LOW -> {
injector.text(R.id.label,
@ -163,6 +172,7 @@ class GlanceTabFragment : Fragment() {
R.string.settings_not_visible))
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
isVisible = Preferences.showBatteryCharging
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
when {
@ -172,16 +182,19 @@ class GlanceTabFragment : Fragment() {
injector.text(R.id.label,
if (Preferences.showNotifications) getString(
R.string.settings_visible) else getString(R.string.settings_not_visible))
isVisible = Preferences.showNotifications
}
Preferences.showNotifications -> {
injector.visibility(R.id.error_icon, View.VISIBLE)
injector.visibility(R.id.info_icon, View.GONE)
injector.text(R.id.label, getString(R.string.settings_not_visible))
isVisible = false
}
else -> {
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
injector.text(R.id.label, getString(R.string.settings_not_visible))
isVisible = false
}
}
}
@ -191,6 +204,7 @@ class GlanceTabFragment : Fragment() {
R.string.settings_not_visible))
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
isVisible = Preferences.showGreetings
}
Constants.GlanceProviderId.CUSTOM_INFO -> {
injector.text(R.id.label,
@ -198,6 +212,7 @@ class GlanceTabFragment : Fragment() {
R.string.settings_not_visible))
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
isVisible = Preferences.customNotes != ""
}
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
val account: GoogleSignInAccount? = GoogleSignIn.getLastSignedInAccount(context)
@ -209,19 +224,34 @@ class GlanceTabFragment : Fragment() {
R.string.settings_not_visible))
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
isVisible = Preferences.showDailySteps
} else if (Preferences.showDailySteps) {
ActivityDetectionReceiver.unregisterFence(requireContext())
injector.visibility(R.id.error_icon, View.VISIBLE)
injector.visibility(R.id.info_icon, View.GONE)
injector.text(R.id.label, getString(R.string.settings_not_visible))
isVisible = false
} else {
ActivityDetectionReceiver.unregisterFence(requireContext())
injector.text(R.id.label, getString(R.string.settings_not_visible))
injector.visibility(R.id.error_icon, View.GONE)
injector.visibility(R.id.info_icon, View.VISIBLE)
isVisible = false
}
}
Constants.GlanceProviderId.EVENTS -> {
isVisible = Preferences.showEventsAsGlanceProvider && Preferences.showEvents && requireContext().checkGrantedPermission(Manifest.permission.READ_CALENDAR)
injector.text(R.id.label,
if (isVisible) getString(R.string.settings_visible) else getString(
R.string.settings_not_visible))
injector.visibility(R.id.error_icon, if (isVisible) View.GONE else View.VISIBLE)
injector.visibility(R.id.info_icon, if (isVisible) View.VISIBLE else View.GONE)
}
}
injector.alpha(R.id.title, if (isVisible) 1f else .25f)
injector.alpha(R.id.label, if (isVisible) 1f else .25f)
injector.alpha(R.id.icon, if (isVisible) 1f else .25f)
}
.attachTo(providers_list)
@ -231,8 +261,6 @@ class GlanceTabFragment : Fragment() {
0
) {
val list = GlanceProviderHelper.getGlanceProviders(requireContext())
override fun onMove(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder,
@ -244,10 +272,6 @@ class GlanceTabFragment : Fragment() {
return true
}
override fun isItemViewSwipeEnabled(): Boolean {
return false
}
override fun onMoved(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
@ -257,14 +281,28 @@ class GlanceTabFragment : Fragment() {
x: Int,
y: Int
) {
with(list[fromPos]) {
list[fromPos] = list[toPos]
list[toPos] = this
with(list[toPos]) {
list[toPos] = list[fromPos]
list[fromPos] = this
}
GlanceProviderHelper.saveGlanceProviderOrder(list)
super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y)
}
override fun isItemViewSwipeEnabled(): Boolean {
return false
}
override fun clearView(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder
) {
super.clearView(recyclerView, viewHolder)
GlanceProviderHelper.saveGlanceProviderOrder(
list
)
adapter.updateData(list.mapNotNull { GlanceProviderHelper.getGlanceProviderById(requireContext(), it) })
}
override fun onChildDraw(
c: Canvas,
recyclerView: RecyclerView,
@ -305,10 +343,7 @@ class GlanceTabFragment : Fragment() {
})
mIth.attachToRecyclerView(providers_list)
adapter.updateData(
GlanceProviderHelper.getGlanceProviders(requireContext())
.mapNotNull { GlanceProviderHelper.getGlanceProviderById(requireContext(), it) }
)
adapter.updateData(list.mapNotNull { GlanceProviderHelper.getGlanceProviderById(requireContext(), it) })
providers_list.isNestedScrollingEnabled = false
setupListener()
@ -338,6 +373,11 @@ class GlanceTabFragment : Fragment() {
show_glance_switch.setOnCheckedChangeListener { _, enabled: Boolean ->
Preferences.showGlance = enabled
}
action_show_glance.setOnLongClickListener {
Preferences.enabledGlanceProviderOrder = ""
true
}
}
private val nextAlarmChangeBroadcastReceiver = object : BroadcastReceiver() {

View File

@ -351,7 +351,7 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
}?.isVisible = if (Preferences.showWeather) {
(WeatherHelper.isKeyRequired() && WeatherHelper.getApiKey() == "")
|| (Preferences.customLocationAdd == "" && activity?.checkGrantedPermission(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
Manifest.permission.ACCESS_FINE_LOCATION
) != true)
|| (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-")
|| (Preferences.weatherProviderLocationError != "")
@ -365,7 +365,8 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
badgeGravity = BadgeDrawable.TOP_END
}?.isVisible = ((Preferences.showMusic || Preferences.showNotifications) && !ActiveNotificationsHelper.checkNotificationAccess(requireContext())) ||
(Preferences.showDailySteps && !(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || requireActivity().checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION))) ||
(AlarmHelper.isAlarmProbablyWrong(requireContext()))
(AlarmHelper.isAlarmProbablyWrong(requireContext())) ||
(Preferences.showEventsAsGlanceProvider && (!Preferences.showEvents || !requireContext().checkGrantedPermission(Manifest.permission.READ_CALENDAR)))
}
override fun onResume() {
@ -396,6 +397,7 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
}
class UpdateUiMessageEvent
class ChangeTabEvent(val page: Int)
@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(ignore: UpdateUiMessageEvent?) {
@ -407,4 +409,11 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
}
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(event: ChangeTabEvent?) {
event?.let {
pager.setCurrentItem(event.page, true)
}
}
}

View File

@ -117,7 +117,6 @@ class WeatherTabFragment : Fragment() {
viewModel.customLocationAdd.observe(viewLifecycleOwner, Observer {
maintainScrollPosition {
background_location_warning.isVisible = it == ""
label_custom_location?.text =
if (it == "") getString(R.string.custom_location_gps) else it
}
@ -161,18 +160,11 @@ class WeatherTabFragment : Fragment() {
}
private fun checkLocationPermission() {
// Background permission
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && activity?.checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION) == true && activity?.checkGrantedPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION) != true) {
requirePermission()
}
if (activity?.checkGrantedPermission(if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION) == true) {
if (requireActivity().checkGrantedPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
location_permission_alert?.isVisible = false
background_location_warning.isVisible = Preferences.customLocationAdd == ""
WeatherReceiver.setUpdates(requireContext())
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
location_permission_alert?.isVisible = true
background_location_warning.isVisible = true
location_permission_alert?.setOnClickListener {
MaterialBottomSheetDialog(requireContext(), message = getString(R.string.background_location_warning))
.setPositiveButton(getString(android.R.string.ok)) {
@ -299,7 +291,7 @@ class WeatherTabFragment : Fragment() {
private fun requirePermission() {
Dexter.withContext(requireContext())
.withPermissions(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
Manifest.permission.ACCESS_FINE_LOCATION
).withListener(object: MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport?) {
report?.let {

View File

@ -172,7 +172,7 @@ class MainWidget : AppWidgetProvider() {
val nextEvent = eventRepository.getNextEvent()
val nextAlarm = AlarmHelper.getNextAlarm(context)
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null && !Preferences.showEventsAsGlanceProvider) {
if (Preferences.showNextEvent && eventRepository.getEventsCount() > 1) {
views.setImageViewBitmap(
R.id.action_next_rect,
@ -378,6 +378,26 @@ class MainWidget : AppWidgetProvider() {
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.second_row_rect,
pIntentDetail
)
showSomething = true
break@loop
}
}
}
}
@ -552,7 +572,7 @@ class MainWidget : AppWidgetProvider() {
val nextEvent = eventRepository.getNextEvent()
val nextAlarm = AlarmHelper.getNextAlarm(context)
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null && !Preferences.showEventsAsGlanceProvider) {
// Multiple counter
v.action_next.isVisible =
Preferences.showNextEvent && eventRepository.getEventsCount() > 1
@ -585,7 +605,7 @@ class MainWidget : AppWidgetProvider() {
v.second_row_icon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_place
R.drawable.round_place_24
)
)
v.next_event_date.text = nextEvent.address
@ -593,7 +613,7 @@ class MainWidget : AppWidgetProvider() {
v.second_row_icon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_today
R.drawable.round_today_24
)
)
if (!nextEvent.allDay) {
@ -674,7 +694,7 @@ class MainWidget : AppWidgetProvider() {
v.second_row_icon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_music_note
R.drawable.round_music_note_24
)
)
v.next_event_date.text = MediaPlayerHelper.getMediaInfo()
@ -687,7 +707,7 @@ class MainWidget : AppWidgetProvider() {
v.second_row_icon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_alarm
R.drawable.round_alarm_24
)
)
v.next_event_date.text = AlarmHelper.getNextAlarm(context)
@ -765,6 +785,35 @@ class MainWidget : AppWidgetProvider() {
break@loop
}
}
Constants.GlanceProviderId.EVENTS -> {
if (Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
v.next_event_date.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()
v.second_row_icon.isVisible = true
v.second_row_icon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_today_24
)
)
showSomething = true
break@loop
}
}
}
}

View File

@ -21,6 +21,7 @@ import android.content.Intent
import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.util.DisplayMetrics
import android.util.Log
import android.util.TypedValue
import android.view.ViewPropertyAnimator
import android.view.animation.Animation
@ -256,4 +257,11 @@ fun Intent.isDefaultSet(context: Context): Boolean {
} catch (ex: java.lang.Exception) {
false
}
}
fun Locale.isMetric(): Boolean {
return when (country.toUpperCase(this)) {
"US", "LR", "MM", "GB" -> false
else -> true
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 449 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 751 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 953 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 804 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1013 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 439 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 601 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 867 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 536 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 466 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1005 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 616 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 509 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 642 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 444 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 538 B

Some files were not shown because too many files have changed in this diff Show More