Compare commits
29 Commits
v2.0.15-be
...
v2.0.15-be
Author | SHA1 | Date | |
---|---|---|---|
56d95c5559 | |||
c0e747a714 | |||
16076dc145 | |||
c95f9fb943 | |||
331d5772af | |||
e2719b6445 | |||
bd35022f7d | |||
6d9cb750a7 | |||
f85b4c9a6a | |||
df54a4a79e | |||
6ea97e7724 | |||
d27071739d | |||
738781225f | |||
12d32f852b | |||
f0baa60363 | |||
785eb39334 | |||
d289699d08 | |||
c68d0a8327 | |||
de2e223713 | |||
6150dd7e22 | |||
d9ecebe770 | |||
52327715b1 | |||
e301e6e6ec | |||
c884fae362 | |||
eb78257e52 | |||
109aa24af1 | |||
2403f066a3 | |||
9bc7d7b62e | |||
a1a6f9f607 |
BIN
.idea/caches/build_file_checksums.ser
generated
@ -23,11 +23,13 @@ android {
|
||||
applicationId "com.tommasoberlose.anotherwidget"
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 29
|
||||
versionCode 107
|
||||
versionCode 109
|
||||
versionName "2.0.15"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY'])
|
||||
|
||||
renderscriptSupportModeEnabled true
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
@ -25,6 +25,7 @@ import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.GreetingsHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
|
||||
import com.tommasoberlose.anotherwidget.ui.activities.AppNotificationsFilterActivity
|
||||
@ -64,7 +65,8 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
||||
view.action_filter_music_players.isVisible = provider == Constants.GlanceProviderId.PLAYING_SONG
|
||||
if (provider == Constants.GlanceProviderId.PLAYING_SONG) {
|
||||
view.action_filter_music_players.setOnClickListener {
|
||||
context.startActivity(Intent(context, MusicPlayersFilterActivity::class.java))
|
||||
dismiss()
|
||||
context.startActivityForResult(Intent(context, MusicPlayersFilterActivity::class.java), 0)
|
||||
}
|
||||
checkNotificationPermission(view)
|
||||
}
|
||||
@ -94,10 +96,24 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
||||
|
||||
/* NOTIFICATIONS */
|
||||
view.action_filter_notifications_app.isVisible = provider == Constants.GlanceProviderId.NOTIFICATIONS
|
||||
view.action_change_notification_timer.isVisible = provider == Constants.GlanceProviderId.NOTIFICATIONS
|
||||
if (provider == Constants.GlanceProviderId.NOTIFICATIONS) {
|
||||
checkLastNotificationsPermission(view)
|
||||
val stringArray = context.resources.getStringArray(R.array.glance_notifications_timeout)
|
||||
view.action_filter_notifications_app.setOnClickListener {
|
||||
context.startActivity(Intent(context, AppNotificationsFilterActivity::class.java))
|
||||
dismiss()
|
||||
context.startActivityForResult(Intent(context, AppNotificationsFilterActivity::class.java), 0)
|
||||
}
|
||||
view.notification_timer_label.text = stringArray[Preferences.hideNotificationAfter]
|
||||
view.action_change_notification_timer.setOnClickListener {
|
||||
val dialog = BottomSheetMenu<Int>(context, header = context.getString(R.string.glance_notification_hide_timeout_title)).setSelectedValue(Preferences.hideNotificationAfter)
|
||||
Constants.GlanceNotificationTimer.values().forEachIndexed { index, timeout ->
|
||||
dialog.addItem(stringArray[index], timeout.value)
|
||||
}
|
||||
dialog.addOnSelectItemListener { value ->
|
||||
Preferences.hideNotificationAfter = value
|
||||
this.show()
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,6 +160,7 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
|
||||
}
|
||||
Constants.GlanceProviderId.GREETINGS -> {
|
||||
Preferences.showGreetings = isChecked
|
||||
GreetingsHelper.toggleGreetings(context)
|
||||
}
|
||||
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||
if (isChecked) {
|
||||
|
@ -18,7 +18,7 @@ import kotlin.collections.ArrayList
|
||||
class EventRepository(val context: Context) {
|
||||
private val realm by lazy { Realm.getDefaultInstance() }
|
||||
|
||||
fun saveEvents(eventList: ArrayList<Event>) {
|
||||
fun saveEvents(eventList: List<Event>) {
|
||||
realm.executeTransaction { realm ->
|
||||
realm.where(Event::class.java).findAll().deleteAllFromRealm()
|
||||
realm.copyToRealm(eventList)
|
||||
|
@ -13,4 +13,5 @@ object Actions {
|
||||
const val ACTION_GO_TO_PREVIOUS_EVENT = "com.tommasoberlose.anotherwidget.action.GO_TO_PREVIOUS_EVENT"
|
||||
const val ACTION_REPORT_CRASH = "com.tommasoberlose.anotherwidget.action.REPORT_CRASH"
|
||||
const val ACTION_CLEAR_NOTIFICATION = "com.tommasoberlose.anotherwidget.action.CLEAR_NOTIFICATION"
|
||||
const val ACTION_UPDATE_GREETINGS = "com.tommasoberlose.anotherwidget.action.UPDATE_GREETINGS"
|
||||
}
|
@ -61,6 +61,20 @@ object Constants {
|
||||
}
|
||||
}
|
||||
|
||||
enum class GlanceNotificationTimer(val value: Int) {
|
||||
HALF_MINUTE(0),
|
||||
ONE_MINUTE(1),
|
||||
FIVE_MINUTES(2),
|
||||
TEN_MINUTES(3),
|
||||
FIFTEEN_MINUTES(4),
|
||||
WHEN_DISMISSED(5);
|
||||
|
||||
companion object {
|
||||
private val map = values().associateBy(GlanceNotificationTimer::value)
|
||||
fun fromInt(type: Int) = map[type]
|
||||
}
|
||||
}
|
||||
|
||||
enum class WeatherIconPack(val value: Int) {
|
||||
DEFAULT(0),
|
||||
MINIMAL(1),
|
||||
|
@ -125,6 +125,7 @@ object Preferences : KotprefModel() {
|
||||
var showDailySteps by booleanPref(default = false)
|
||||
var showGreetings by booleanPref(default = false)
|
||||
var showNotifications by booleanPref(default = false)
|
||||
var hideNotificationAfter by intPref(default = Constants.GlanceNotificationTimer.ONE_MINUTE.value)
|
||||
|
||||
var lastNotificationId by intPref(default = -1)
|
||||
var lastNotificationTitle by stringPref(default = "")
|
||||
|
@ -80,4 +80,27 @@ object CalendarHelper {
|
||||
.filter { (!Preferences.showOnlyBusyEvents || it.availability != CalendarContract.EventsEntity.AVAILABILITY_FREE) }
|
||||
.toList()
|
||||
}
|
||||
|
||||
fun List<Event>.sortEvents(): List<Event> {
|
||||
return sortedWith { event: Event, event1: Event ->
|
||||
val date = Calendar.getInstance().apply { timeInMillis = event.startDate }
|
||||
val date1 = Calendar.getInstance().apply { timeInMillis = event1.startDate }
|
||||
|
||||
if (date.get(Calendar.DAY_OF_YEAR) == date1.get(Calendar.DAY_OF_YEAR) && date.get(
|
||||
Calendar.YEAR) == date1.get(Calendar.YEAR)
|
||||
) {
|
||||
if (event.allDay && event1.allDay) {
|
||||
event.startDate.compareTo(event1.startDate)
|
||||
} else if (event.allDay) {
|
||||
1
|
||||
} else if (event1.allDay) {
|
||||
-1
|
||||
} else {
|
||||
event.startDate.compareTo(event1.startDate)
|
||||
}
|
||||
} else {
|
||||
event.startDate.compareTo(event1.startDate)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
@ -16,7 +17,8 @@ object GlanceProviderHelper {
|
||||
val providers = Constants.GlanceProviderId.values()
|
||||
.filter {
|
||||
context.checkIfFitInstalled() || it != Constants.GlanceProviderId.GOOGLE_FIT_STEPS
|
||||
}.toTypedArray()
|
||||
}
|
||||
.toTypedArray()
|
||||
|
||||
providers.sortWith(Comparator { p1, p2 ->
|
||||
when {
|
||||
@ -34,7 +36,6 @@ object GlanceProviderHelper {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return ArrayList(providers.toList())
|
||||
}
|
||||
|
||||
@ -49,7 +50,7 @@ object GlanceProviderHelper {
|
||||
Constants.GlanceProviderId.PLAYING_SONG -> {
|
||||
GlanceProvider(providerId.id,
|
||||
context.getString(R.string.settings_show_music_title),
|
||||
R.drawable.round_radio
|
||||
R.drawable.round_music_note
|
||||
)
|
||||
}
|
||||
Constants.GlanceProviderId.CUSTOM_INFO -> {
|
||||
@ -67,7 +68,7 @@ object GlanceProviderHelper {
|
||||
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
|
||||
GlanceProvider(providerId.id,
|
||||
context.getString(R.string.settings_daily_steps_title),
|
||||
R.drawable.round_run_circle
|
||||
R.drawable.round_near_me
|
||||
)
|
||||
}
|
||||
Constants.GlanceProviderId.NOTIFICATIONS -> {
|
||||
@ -100,7 +101,8 @@ object GlanceProviderHelper {
|
||||
(MediaPlayerHelper.isSomeonePlaying(context)) ||
|
||||
(Preferences.showBatteryCharging && Preferences.isCharging || Preferences.isBatteryLevelLow) ||
|
||||
(Preferences.customNotes.isNotEmpty()) ||
|
||||
(Preferences.showDailySteps && Preferences.googleFitSteps > 0)
|
||||
(Preferences.showDailySteps && Preferences.googleFitSteps > 0) ||
|
||||
(Preferences.showGreetings && GreetingsHelper.showGreetings())
|
||||
)
|
||||
eventRepository.close()
|
||||
return showGlance
|
||||
|
@ -0,0 +1,110 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.app.AlarmManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||
import java.util.*
|
||||
|
||||
|
||||
object GreetingsHelper {
|
||||
private const val MORNING_TIME = 36
|
||||
private const val MORNING_TIME_END = 37
|
||||
private const val EVENING_TIME = 38
|
||||
private const val NIGHT_TIME = 39
|
||||
|
||||
fun toggleGreetings(context: Context) {
|
||||
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
|
||||
val now = Calendar.getInstance().apply {
|
||||
set(Calendar.SECOND, 0)
|
||||
set(Calendar.MILLISECOND, 0)
|
||||
set(Calendar.MINUTE, 0)
|
||||
set(Calendar.HOUR_OF_DAY, 0)
|
||||
}
|
||||
if (Preferences.showGreetings) {
|
||||
setRepeating(
|
||||
AlarmManager.RTC,
|
||||
now.apply {
|
||||
set(Calendar.HOUR_OF_DAY, 5)
|
||||
}.timeInMillis,
|
||||
1000 * 60 * 60 * 24,
|
||||
PendingIntent.getBroadcast(context,
|
||||
MORNING_TIME,
|
||||
Intent(context, UpdatesReceiver::class.java).apply {
|
||||
action = Actions.ACTION_UPDATE_GREETINGS
|
||||
},
|
||||
0)
|
||||
)
|
||||
|
||||
setRepeating(
|
||||
AlarmManager.RTC,
|
||||
now.apply {
|
||||
set(Calendar.HOUR_OF_DAY, 9)
|
||||
}.timeInMillis,
|
||||
1000 * 60 * 60 * 24,
|
||||
PendingIntent.getBroadcast(context,
|
||||
MORNING_TIME_END,
|
||||
Intent(context, UpdatesReceiver::class.java).apply {
|
||||
action = Actions.ACTION_UPDATE_GREETINGS
|
||||
},
|
||||
0)
|
||||
)
|
||||
|
||||
setRepeating(
|
||||
AlarmManager.RTC,
|
||||
now.apply {
|
||||
set(Calendar.HOUR_OF_DAY, 19)
|
||||
}.timeInMillis,
|
||||
1000 * 60 * 60 * 24,
|
||||
PendingIntent.getBroadcast(context,
|
||||
EVENING_TIME,
|
||||
Intent(context, UpdatesReceiver::class.java).apply {
|
||||
action = Actions.ACTION_UPDATE_GREETINGS
|
||||
},
|
||||
0)
|
||||
)
|
||||
|
||||
setRepeating(
|
||||
AlarmManager.RTC,
|
||||
now.apply {
|
||||
set(Calendar.HOUR_OF_DAY, 22)
|
||||
}.timeInMillis,
|
||||
1000 * 60 * 60 * 24,
|
||||
PendingIntent.getBroadcast(context,
|
||||
NIGHT_TIME,
|
||||
Intent(context, UpdatesReceiver::class.java).apply {
|
||||
action = Actions.ACTION_UPDATE_GREETINGS
|
||||
},
|
||||
0)
|
||||
)
|
||||
} else {
|
||||
listOf(MORNING_TIME, MORNING_TIME_END, EVENING_TIME, NIGHT_TIME).forEach {
|
||||
cancel(PendingIntent.getBroadcast(context, it, Intent(context,
|
||||
UpdatesReceiver::class.java).apply {
|
||||
action = Actions.ACTION_UPDATE_GREETINGS
|
||||
}, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun showGreetings(): Boolean {
|
||||
val hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY)
|
||||
return hour < 9 || hour >= 19
|
||||
}
|
||||
|
||||
fun getRandomString(context: Context): String {
|
||||
val hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY)
|
||||
val array = when {
|
||||
hour in 5..8 -> context.resources.getStringArray(R.array.morning_greetings)
|
||||
hour in 19..21 -> context.resources.getStringArray(R.array.evening_greetings)
|
||||
hour >= 22 && hour < 5 -> context.resources.getStringArray(R.array.night_greetings)
|
||||
else -> emptyArray()
|
||||
}
|
||||
return if (array.isNotEmpty()) array[Random().nextInt(array.size)] else ""
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package com.tommasoberlose.anotherwidget.helpers
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.*
|
||||
import android.renderscript.*
|
||||
import android.util.TypedValue
|
||||
import android.widget.ImageView
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||
import java.util.prefs.Preferences
|
||||
import kotlin.math.min
|
||||
|
||||
object ImageHelper {
|
||||
fun ImageView.applyShadow(originalView: ImageView, factor: Float = 1f) {
|
||||
clearColorFilter()
|
||||
val cElevation = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, when (if (context.isDarkTheme()) com.tommasoberlose.anotherwidget.global.Preferences.textShadowDark else com.tommasoberlose.anotherwidget.global.Preferences.textShadow) {
|
||||
0 -> 0f * factor
|
||||
1 -> 8f * factor
|
||||
2 -> 16f * factor
|
||||
else -> 0f * factor
|
||||
}, resources.displayMetrics)
|
||||
|
||||
if (originalView.drawable != null) {
|
||||
val btm = originalView.drawable.toBitmap().copy(Bitmap.Config.ARGB_8888, true)
|
||||
val comb = Bitmap.createBitmap(btm)
|
||||
val shadowBitmap = generateShadowBitmap(context, cElevation, btm, factor)
|
||||
|
||||
shadowBitmap?.let {
|
||||
val canvas = Canvas(comb)
|
||||
canvas.drawColor(Color.TRANSPARENT)
|
||||
canvas.save()
|
||||
val rect = Rect()
|
||||
val bounds = originalView.drawable.copyBounds()
|
||||
canvas.getClipBounds(rect)
|
||||
rect.inset(-2 * getBlurRadius(context, cElevation).toInt(), -2 * getBlurRadius(context, cElevation).toInt())
|
||||
canvas.save()
|
||||
canvas.clipRect(rect)
|
||||
canvas.drawBitmap(shadowBitmap, 0f, 2f, null)
|
||||
canvas.restore()
|
||||
setImageBitmap(comb)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateShadowBitmap(context: Context, cElevation: Float, bitmap: Bitmap?, factor: Float): Bitmap? {
|
||||
val rs: RenderScript = RenderScript.create(context)
|
||||
val element = Element.U8_4(rs)
|
||||
val blurScript: ScriptIntrinsicBlur = ScriptIntrinsicBlur.create(rs, element)
|
||||
val colorMatrixScript: ScriptIntrinsicColorMatrix = ScriptIntrinsicColorMatrix.create(rs)
|
||||
val allocationIn = Allocation.createFromBitmap(rs, bitmap)
|
||||
val allocationOut = Allocation.createTyped(rs, allocationIn.type)
|
||||
|
||||
val matrix = Matrix4f(floatArrayOf(
|
||||
0f, 0f, 0f, 0f,
|
||||
0f, 0f, 0f, 0f,
|
||||
0f, 0f, 0f, 0f,
|
||||
0f, 0f, 0f, when (if (context.isDarkTheme()) com.tommasoberlose.anotherwidget.global.Preferences.textShadowDark else com.tommasoberlose.anotherwidget.global.Preferences.textShadow) {
|
||||
0 -> 0f * factor
|
||||
1 -> 0.8f * factor
|
||||
2 -> 1f * factor
|
||||
else -> 0f
|
||||
}))
|
||||
|
||||
colorMatrixScript.setColorMatrix(matrix)
|
||||
colorMatrixScript.forEach(allocationIn, allocationOut)
|
||||
|
||||
blurScript.setRadius(getBlurRadius(context, cElevation))
|
||||
|
||||
blurScript.setInput(allocationOut)
|
||||
blurScript.forEach(allocationIn)
|
||||
|
||||
allocationIn.copyTo(bitmap)
|
||||
|
||||
allocationIn.destroy()
|
||||
allocationOut.destroy()
|
||||
|
||||
return bitmap
|
||||
}
|
||||
|
||||
private fun getBlurRadius(context: Context, customElevation: Float): Float {
|
||||
val maxElevation = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24f, context.resources.displayMetrics)
|
||||
return min(25f * (customElevation / maxElevation), 25f)
|
||||
}
|
||||
}
|
@ -66,7 +66,6 @@ object IntentHelper {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
context.toast(context.getString(R.string.error_opening_app))
|
||||
Intent()
|
||||
}
|
||||
}
|
||||
@ -96,7 +95,6 @@ object IntentHelper {
|
||||
data = calendarUri
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
context.toast(context.getString(R.string.error_opening_app))
|
||||
Intent()
|
||||
}
|
||||
}
|
||||
@ -181,7 +179,6 @@ object IntentHelper {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
context.toast(context.getString(R.string.error_opening_app))
|
||||
Intent()
|
||||
}
|
||||
}
|
||||
@ -204,7 +201,6 @@ object IntentHelper {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
context.toast(context.getString(R.string.error_opening_app))
|
||||
Intent()
|
||||
}
|
||||
}
|
||||
@ -218,7 +214,6 @@ object IntentHelper {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
context.toast(context.getString(R.string.error_opening_app))
|
||||
Intent()
|
||||
}
|
||||
}
|
||||
@ -230,7 +225,6 @@ object IntentHelper {
|
||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
context.toast(context.getString(R.string.error_opening_app))
|
||||
Intent()
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,12 @@ import android.service.notification.NotificationListenerService
|
||||
import android.service.notification.StatusBarNotification
|
||||
import android.util.Log
|
||||
import com.tommasoberlose.anotherwidget.global.Actions
|
||||
import com.tommasoberlose.anotherwidget.global.Constants
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import java.lang.Exception
|
||||
import java.util.*
|
||||
|
||||
|
||||
@ -35,10 +37,18 @@ class NotificationListener : NotificationListenerService() {
|
||||
Preferences.lastNotificationId = sbn.id
|
||||
Preferences.lastNotificationTitle = bundle.getString(Notification.EXTRA_TITLE) ?: ""
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||
Preferences.lastNotificationIcon = sbn.notification.smallIcon.resId
|
||||
try {
|
||||
Preferences.lastNotificationIcon = sbn.notification.smallIcon.resId
|
||||
} catch (ex: Exception) {
|
||||
Preferences.lastNotificationIcon = 0
|
||||
}
|
||||
Preferences.lastNotificationPackage = sbn.notification.smallIcon.resPackage
|
||||
} else {
|
||||
Preferences.lastNotificationIcon = sbn.notification.icon
|
||||
try {
|
||||
Preferences.lastNotificationIcon = sbn.notification.icon
|
||||
} catch (ex: Exception) {
|
||||
Preferences.lastNotificationIcon = 0
|
||||
}
|
||||
Preferences.lastNotificationPackage = sbn.packageName
|
||||
}
|
||||
MainWidget.updateWidget(this)
|
||||
@ -69,16 +79,26 @@ class NotificationListener : NotificationListenerService() {
|
||||
action = Actions.ACTION_CLEAR_NOTIFICATION
|
||||
}
|
||||
cancel(PendingIntent.getBroadcast(context, 28943, intent, 0))
|
||||
setExact(
|
||||
AlarmManager.RTC,
|
||||
Calendar.getInstance().timeInMillis + 30 * 1000,
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
5,
|
||||
intent,
|
||||
0
|
||||
val timeoutPref = Constants.GlanceNotificationTimer.fromInt(Preferences.hideNotificationAfter)
|
||||
if (timeoutPref != Constants.GlanceNotificationTimer.WHEN_DISMISSED) {
|
||||
setExact(
|
||||
AlarmManager.RTC,
|
||||
Calendar.getInstance().timeInMillis + when (timeoutPref) {
|
||||
Constants.GlanceNotificationTimer.HALF_MINUTE -> 30 * 1000
|
||||
Constants.GlanceNotificationTimer.ONE_MINUTE -> 60 * 1000
|
||||
Constants.GlanceNotificationTimer.FIVE_MINUTES -> 5 * 60 * 1000
|
||||
Constants.GlanceNotificationTimer.TEN_MINUTES -> 10 * 60 * 1000
|
||||
Constants.GlanceNotificationTimer.FIFTEEN_MINUTES -> 15 * 60 * 1000
|
||||
else -> 0
|
||||
},
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
5,
|
||||
intent,
|
||||
0
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -52,6 +52,9 @@ class UpdatesReceiver : BroadcastReceiver() {
|
||||
ActiveNotificationsHelper.clearLastNotification(context)
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
Actions.ACTION_UPDATE_GREETINGS -> {
|
||||
MainWidget.updateWidget(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import com.tommasoberlose.anotherwidget.db.EventRepository
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.applyFilters
|
||||
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.sortEvents
|
||||
import com.tommasoberlose.anotherwidget.models.Event
|
||||
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
|
||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||
@ -44,8 +45,17 @@ class UpdateCalendarJob : JobIntentService() {
|
||||
set(Calendar.HOUR_OF_DAY, 0)
|
||||
}
|
||||
val limit = Calendar.getInstance().apply {
|
||||
timeInMillis = begin.timeInMillis
|
||||
add(Calendar.DAY_OF_YEAR, 2)
|
||||
when (Preferences.showUntil) {
|
||||
0 -> add(Calendar.HOUR, 3)
|
||||
1 -> add(Calendar.HOUR, 6)
|
||||
2 -> add(Calendar.HOUR, 12)
|
||||
3 -> add(Calendar.DAY_OF_MONTH, 1)
|
||||
4 -> add(Calendar.DAY_OF_MONTH, 3)
|
||||
5 -> add(Calendar.DAY_OF_MONTH, 7)
|
||||
6 -> add(Calendar.MINUTE, 30)
|
||||
7 -> add(Calendar.HOUR, 1)
|
||||
else -> add(Calendar.HOUR, 6)
|
||||
}
|
||||
}
|
||||
|
||||
if (!checkGrantedPermission(
|
||||
@ -95,34 +105,16 @@ class UpdateCalendarJob : JobIntentService() {
|
||||
}
|
||||
}
|
||||
|
||||
val filteredEventList = eventList
|
||||
val sortedEvents = eventList.sortEvents()
|
||||
val filteredEventList = sortedEvents
|
||||
.applyFilters()
|
||||
|
||||
if (filteredEventList.isEmpty()) {
|
||||
eventRepository.resetNextEventData()
|
||||
eventRepository.clearEvents()
|
||||
} else {
|
||||
eventList.sortWith(Comparator { event: Event, event1: Event ->
|
||||
val date = Calendar.getInstance().apply { timeInMillis = event.startDate }
|
||||
val date1 = Calendar.getInstance().apply { timeInMillis = event1.startDate }
|
||||
|
||||
if (date.get(Calendar.DAY_OF_YEAR) == date1.get(Calendar.DAY_OF_YEAR) && date.get(Calendar.YEAR) == date1.get(Calendar.YEAR)) {
|
||||
if (event.allDay && event1.allDay) {
|
||||
event.startDate.compareTo(event1.startDate)
|
||||
} else if (event.allDay) {
|
||||
1
|
||||
} else if (event1.allDay) {
|
||||
-1
|
||||
} else {
|
||||
event.startDate.compareTo(event1.startDate)
|
||||
}
|
||||
} else {
|
||||
event.startDate.compareTo(event1.startDate)
|
||||
}
|
||||
})
|
||||
|
||||
eventRepository.saveEvents(
|
||||
eventList
|
||||
sortedEvents
|
||||
)
|
||||
eventRepository.saveNextEventData(filteredEventList.first())
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import kotlinx.android.synthetic.main.activity_choose_application.search
|
||||
import kotlinx.android.synthetic.main.activity_music_players_filter.*
|
||||
import kotlinx.coroutines.*
|
||||
import net.idik.lib.slimadapter.SlimAdapter
|
||||
import net.idik.lib.slimadapter.SlimAdapterEx
|
||||
|
||||
|
||||
class ChooseApplicationActivity : AppCompatActivity() {
|
||||
@ -47,7 +48,7 @@ class ChooseApplicationActivity : AppCompatActivity() {
|
||||
val mLayoutManager = LinearLayoutManager(this)
|
||||
list_view.layoutManager = mLayoutManager
|
||||
|
||||
adapter = SlimAdapter.create()
|
||||
adapter = SlimAdapterEx.create()
|
||||
adapter
|
||||
.register<String>(R.layout.application_info_layout) { _, injector ->
|
||||
injector
|
||||
|
@ -90,7 +90,7 @@ class CustomDateActivity : AppCompatActivity() {
|
||||
ERROR_STRING
|
||||
}
|
||||
} else {
|
||||
"__"
|
||||
ERROR_STRING
|
||||
}
|
||||
|
||||
if (viewModel.isDateCapitalize.value == true) {
|
||||
@ -102,7 +102,6 @@ class CustomDateActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
action_save.isVisible = text != ERROR_STRING
|
||||
loader.visibility = View.INVISIBLE
|
||||
date_format_value.text = text
|
||||
}
|
||||
@ -143,15 +142,6 @@ class CustomDateActivity : AppCompatActivity() {
|
||||
onBackPressed()
|
||||
}
|
||||
|
||||
action_save.setOnClickListener {
|
||||
Preferences.blockingBulk {
|
||||
dateFormat = viewModel.dateInput.value ?: ""
|
||||
isDateCapitalize = viewModel.isDateCapitalize.value ?: true
|
||||
isDateUppercase = viewModel.isDateUppercase.value ?: false
|
||||
}
|
||||
finish()
|
||||
}
|
||||
|
||||
action_capitalize.setOnClickListener {
|
||||
when {
|
||||
viewModel.isDateUppercase.value == true -> {
|
||||
@ -179,6 +169,15 @@ class CustomDateActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
Preferences.blockingBulk {
|
||||
dateFormat = viewModel.dateInput.value ?: ""
|
||||
isDateCapitalize = viewModel.isDateCapitalize.value ?: true
|
||||
isDateUppercase = viewModel.isDateUppercase.value ?: false
|
||||
}
|
||||
super.onBackPressed()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ERROR_STRING = "--"
|
||||
val DATE: Calendar = Calendar.getInstance().apply {
|
||||
|
@ -66,6 +66,10 @@ class WeatherProviderActivity : AppCompatActivity() {
|
||||
injector
|
||||
.text(R.id.text, WeatherHelper.getProviderName(this, provider))
|
||||
.clicked(R.id.item) {
|
||||
if (Preferences.weatherProvider != provider.value) {
|
||||
Preferences.weatherProviderError = "-"
|
||||
Preferences.weatherProviderLocationError = ""
|
||||
}
|
||||
val oldValue = Preferences.weatherProvider
|
||||
Preferences.weatherProvider = provider.value
|
||||
updateListItem(oldValue)
|
||||
@ -77,6 +81,10 @@ class WeatherProviderActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
.clicked(R.id.radioButton) {
|
||||
if (Preferences.weatherProvider != provider.value) {
|
||||
Preferences.weatherProviderError = "-"
|
||||
Preferences.weatherProviderLocationError = ""
|
||||
}
|
||||
val oldValue = Preferences.weatherProvider
|
||||
Preferences.weatherProvider = provider.value
|
||||
updateListItem(oldValue)
|
||||
|
@ -241,8 +241,6 @@ class GlanceTabFragment : Fragment() {
|
||||
val toPos = target.adapterPosition
|
||||
// move item in `fromPos` to `toPos` in adapter.
|
||||
adapter.notifyItemMoved(fromPos, toPos)
|
||||
|
||||
Collections.swap(list, fromPos, toPos)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -250,12 +248,21 @@ class GlanceTabFragment : Fragment() {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun clearView(
|
||||
override fun onMoved(
|
||||
recyclerView: RecyclerView,
|
||||
viewHolder: RecyclerView.ViewHolder
|
||||
viewHolder: RecyclerView.ViewHolder,
|
||||
fromPos: Int,
|
||||
target: RecyclerView.ViewHolder,
|
||||
toPos: Int,
|
||||
x: Int,
|
||||
y: Int
|
||||
) {
|
||||
super.clearView(recyclerView, viewHolder)
|
||||
with(list[fromPos]) {
|
||||
list[fromPos] = list[toPos]
|
||||
list[toPos] = this
|
||||
}
|
||||
GlanceProviderHelper.saveGlanceProviderOrder(list)
|
||||
super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y)
|
||||
}
|
||||
|
||||
override fun onChildDraw(
|
||||
@ -279,7 +286,6 @@ class GlanceTabFragment : Fragment() {
|
||||
}
|
||||
|
||||
val topEdge = if ((view.top == 0 && dY < 0) || ((view.top + view.height >= recyclerView.height - 32f.convertDpToPixel(requireContext())) && dY > 0)) 0f else dY
|
||||
Log.d("ciao", "${view.top} + ${view.height} = ${view.top + view.height} to compare to ${recyclerView.height} - ${32f.convertDpToPixel(requireContext())}")
|
||||
|
||||
super.onChildDraw(c,
|
||||
recyclerView,
|
||||
@ -302,7 +308,6 @@ class GlanceTabFragment : Fragment() {
|
||||
adapter.updateData(
|
||||
GlanceProviderHelper.getGlanceProviders(requireContext())
|
||||
.mapNotNull { GlanceProviderHelper.getGlanceProviderById(requireContext(), it) }
|
||||
.filterNot { it.id == Constants.GlanceProviderId.GREETINGS.id }
|
||||
)
|
||||
providers_list.isNestedScrollingEnabled = false
|
||||
|
||||
|
@ -354,6 +354,7 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
|
||||
) != true)
|
||||
|| (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-")
|
||||
|| (Preferences.weatherProviderLocationError != "")
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -42,6 +42,8 @@ import com.tommasoberlose.anotherwidget.ui.activities.WeatherProviderActivity
|
||||
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
|
||||
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import com.tommasoberlose.anotherwidget.utils.collapse
|
||||
import com.tommasoberlose.anotherwidget.utils.expand
|
||||
import kotlinx.android.synthetic.main.fragment_weather_settings.*
|
||||
import kotlinx.android.synthetic.main.fragment_weather_settings.scrollView
|
||||
import kotlinx.coroutines.delay
|
||||
@ -87,11 +89,6 @@ class WeatherTabFragment : Fragment() {
|
||||
) {
|
||||
binding.isWeatherVisible = Preferences.showWeather
|
||||
|
||||
viewModel.showWeatherWarning.observe(viewLifecycleOwner, Observer {
|
||||
weather_warning?.isVisible = it
|
||||
checkLocationPermission()
|
||||
})
|
||||
|
||||
viewModel.showWeather.observe(viewLifecycleOwner, Observer {
|
||||
maintainScrollPosition {
|
||||
show_weather_label?.text =
|
||||
@ -100,6 +97,7 @@ class WeatherTabFragment : Fragment() {
|
||||
binding.isWeatherVisible = it
|
||||
}
|
||||
checkLocationPermission()
|
||||
checkWeatherProviderConfig()
|
||||
})
|
||||
|
||||
viewModel.weatherProvider.observe(viewLifecycleOwner, Observer {
|
||||
@ -174,7 +172,7 @@ class WeatherTabFragment : Fragment() {
|
||||
WeatherReceiver.setUpdates(requireContext())
|
||||
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
|
||||
location_permission_alert?.isVisible = true
|
||||
background_location_warning.isVisible = false
|
||||
background_location_warning.isVisible = true
|
||||
location_permission_alert?.setOnClickListener {
|
||||
MaterialBottomSheetDialog(requireContext(), message = getString(R.string.background_location_warning))
|
||||
.setPositiveButton(getString(android.R.string.ok)) {
|
||||
@ -188,18 +186,22 @@ class WeatherTabFragment : Fragment() {
|
||||
}
|
||||
|
||||
private fun checkWeatherProviderConfig() {
|
||||
weather_provider_error.isVisible = Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-"
|
||||
if (Preferences.showWeather && Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-" && !location_permission_alert.isVisible) {
|
||||
weather_provider_error.expand()
|
||||
} else {
|
||||
weather_provider_error.collapse()
|
||||
}
|
||||
weather_provider_error?.text = Preferences.weatherProviderError
|
||||
|
||||
weather_provider_location_error.isVisible = Preferences.weatherProviderLocationError != ""
|
||||
if (Preferences.showWeather && Preferences.weatherProviderLocationError != "" && !location_permission_alert.isVisible) {
|
||||
weather_provider_location_error.expand()
|
||||
} else {
|
||||
weather_provider_location_error.collapse()
|
||||
}
|
||||
weather_provider_location_error?.text = Preferences.weatherProviderLocationError
|
||||
}
|
||||
|
||||
private fun setupListener() {
|
||||
action_hide_weather_warning.setOnClickListener {
|
||||
Preferences.showWeatherWarning = false
|
||||
}
|
||||
|
||||
action_show_weather.setOnClickListener {
|
||||
Preferences.showWeather = !Preferences.showWeather
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ 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.*
|
||||
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
|
||||
import com.tommasoberlose.anotherwidget.utils.isDarkTheme
|
||||
@ -350,8 +351,12 @@ class MainWidget : AppWidgetProvider() {
|
||||
Constants.GlanceProviderId.NOTIFICATIONS -> {
|
||||
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
|
||||
try {
|
||||
val remotePackageContext = context.createPackageContext(Preferences.lastNotificationPackage, 0)
|
||||
val icon = ContextCompat.getDrawable(remotePackageContext, Preferences.lastNotificationIcon)
|
||||
if (Preferences.lastNotificationIcon != 0) {
|
||||
val remotePackageContext = context.createPackageContext(Preferences.lastNotificationPackage, 0)
|
||||
ContextCompat.getDrawable(
|
||||
remotePackageContext,
|
||||
Preferences.lastNotificationIcon)
|
||||
}
|
||||
val notificationIntent = PendingIntent.getActivity(
|
||||
context,
|
||||
widgetID,
|
||||
@ -367,6 +372,12 @@ class MainWidget : AppWidgetProvider() {
|
||||
} catch (ex: Exception) {}
|
||||
}
|
||||
}
|
||||
Constants.GlanceProviderId.GREETINGS -> {
|
||||
if (Preferences.showGreetings && GreetingsHelper.showGreetings() && GreetingsHelper.getRandomString(context).isNotBlank()) {
|
||||
showSomething = true
|
||||
break@loop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -606,7 +617,7 @@ class MainWidget : AppWidgetProvider() {
|
||||
dayDiff++
|
||||
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(
|
||||
Calendar.MINUTE
|
||||
) >= endCal.get(Calendar.MINUTE)
|
||||
) > endCal.get(Calendar.MINUTE)
|
||||
) {
|
||||
dayDiff++
|
||||
}
|
||||
@ -618,14 +629,27 @@ class MainWidget : AppWidgetProvider() {
|
||||
context.getString(R.string.day_char)
|
||||
)
|
||||
}
|
||||
v.next_event_date.text =
|
||||
String.format("%s - %s%s", startHour, endHour, multipleDay)
|
||||
|
||||
if (nextEvent.startDate != nextEvent.endDate) {
|
||||
v.next_event_date.text =
|
||||
String.format("%s - %s%s", startHour, endHour, multipleDay)
|
||||
} else {
|
||||
v.next_event_date.text =
|
||||
String.format("%s", startHour)
|
||||
}
|
||||
|
||||
} else {
|
||||
val flags: Int =
|
||||
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
|
||||
v.next_event_date.text =
|
||||
val start = Calendar.getInstance().apply { timeInMillis = nextEvent.startDate }
|
||||
|
||||
v.next_event_date.text = if (now.get(Calendar.DAY_OF_YEAR) == start.get(Calendar.DAY_OF_YEAR)) {
|
||||
DateUtils.formatDateTime(context, nextEvent.startDate, flags)
|
||||
} else if (now.get(Calendar.DAY_OF_YEAR) > start.get(Calendar.DAY_OF_YEAR) || now.get(Calendar.YEAR) > start.get(Calendar.YEAR)) {
|
||||
DateUtils.formatDateTime(context, now.timeInMillis, flags)
|
||||
} else {
|
||||
DateUtils.formatDateTime(context, nextEvent.startDate, flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -698,7 +722,6 @@ class MainWidget : AppWidgetProvider() {
|
||||
if (Preferences.customNotes.isNotEmpty()) {
|
||||
v.second_row_icon.isVisible = false
|
||||
v.next_event_date.text = Preferences.customNotes
|
||||
v.next_event_date.gravity
|
||||
v.next_event_date.maxLines = 2
|
||||
showSomething = true
|
||||
break@loop
|
||||
@ -717,16 +740,31 @@ class MainWidget : AppWidgetProvider() {
|
||||
Constants.GlanceProviderId.NOTIFICATIONS -> {
|
||||
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
|
||||
try {
|
||||
val remotePackageContext = context.createPackageContext(Preferences.lastNotificationPackage, 0)
|
||||
val icon = ContextCompat.getDrawable(remotePackageContext, Preferences.lastNotificationIcon)
|
||||
v.second_row_icon.isVisible = true
|
||||
v.second_row_icon.setImageDrawable(icon)
|
||||
if (Preferences.lastNotificationIcon != 0) {
|
||||
val remotePackageContext = context.createPackageContext(Preferences.lastNotificationPackage, 0)
|
||||
val icon = ContextCompat.getDrawable(remotePackageContext,
|
||||
Preferences.lastNotificationIcon)
|
||||
v.second_row_icon.isVisible = true
|
||||
v.second_row_icon.setImageDrawable(icon)
|
||||
} else {
|
||||
v.second_row_icon.isVisible = false
|
||||
}
|
||||
v.next_event_date.text = Preferences.lastNotificationTitle
|
||||
showSomething = true
|
||||
break@loop
|
||||
} catch (ex: Exception) {}
|
||||
}
|
||||
}
|
||||
Constants.GlanceProviderId.GREETINGS -> {
|
||||
val greetingsText = GreetingsHelper.getRandomString(context)
|
||||
if (Preferences.showGreetings && GreetingsHelper.showGreetings() && greetingsText.isNotBlank()) {
|
||||
v.next_event_date.text = greetingsText
|
||||
v.next_event_date.maxLines = 2
|
||||
v.second_row_icon.isVisible = false
|
||||
showSomething = true
|
||||
break@loop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -782,9 +820,9 @@ class MainWidget : AppWidgetProvider() {
|
||||
}
|
||||
|
||||
if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.value) {
|
||||
listOf<ImageView>(v.second_row_icon)
|
||||
listOf<ImageView>(v.second_row_icon, v.second_row_icon_shadow)
|
||||
} else {
|
||||
listOf<ImageView>(v.second_row_icon, v.weather_icon)
|
||||
listOf<ImageView>(v.second_row_icon, v.weather_icon, v.second_row_icon_shadow)
|
||||
}.forEach {
|
||||
it.setColorFilter(ColorHelper.getSecondaryFontColorRgb(context.applicationContext.isDarkTheme()))
|
||||
it.alpha =
|
||||
@ -825,8 +863,8 @@ class MainWidget : AppWidgetProvider() {
|
||||
v.action_previous.scaleX = Preferences.textMainSize / 28f
|
||||
v.action_previous.scaleY = Preferences.textMainSize / 28f
|
||||
|
||||
v.special_weather_icon.scaleX = Preferences.textMainSize / 20f
|
||||
v.special_weather_icon.scaleY = Preferences.textMainSize / 20f
|
||||
v.special_weather_icon.scaleX = Preferences.textMainSize / 18f
|
||||
v.special_weather_icon.scaleY = Preferences.textMainSize / 18f
|
||||
|
||||
|
||||
// Shadows
|
||||
@ -867,6 +905,38 @@ class MainWidget : AppWidgetProvider() {
|
||||
it.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
|
||||
}
|
||||
|
||||
// Icons shadow
|
||||
|
||||
listOf(
|
||||
Pair(v.second_row_icon, v.second_row_icon_shadow),
|
||||
).forEach {
|
||||
if ((if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) == 0) {
|
||||
it.second.isVisible = false
|
||||
} else {
|
||||
it.second.isVisible = it.first.isVisible
|
||||
it.second.scaleX = it.first.scaleX
|
||||
it.second.scaleY = it.first.scaleY
|
||||
it.second.applyShadow(it.first)
|
||||
}
|
||||
}
|
||||
|
||||
listOf(
|
||||
Pair(v.action_next, v.action_next_shadow),
|
||||
Pair(v.action_previous, v.action_previous_shadow),
|
||||
).forEach {
|
||||
if ((if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) == 0) {
|
||||
it.second.isVisible = false
|
||||
} else {
|
||||
it.second.isVisible = it.first.isVisible
|
||||
it.second.scaleX = it.first.scaleX
|
||||
it.second.scaleY = it.first.scaleY
|
||||
it.second.applyShadow(it.first, 0.6f)
|
||||
}
|
||||
}
|
||||
|
||||
v.action_previous.scaleX = v.action_previous.scaleX * -1
|
||||
v.action_previous_shadow.scaleX = v.action_previous_shadow.scaleX * -1
|
||||
|
||||
// Custom Font
|
||||
if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) {
|
||||
val googleSans: Typeface = when (Preferences.customFontVariant) {
|
||||
|
@ -1,12 +1,11 @@
|
||||
package com.tommasoberlose.anotherwidget.utils
|
||||
|
||||
import android.animation.*
|
||||
import android.content.pm.PackageManager
|
||||
import android.view.Gravity
|
||||
import android.view.View
|
||||
import android.view.ViewAnimationUtils
|
||||
import android.widget.Toast
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.app.Activity
|
||||
import android.app.WallpaperManager
|
||||
import android.content.*
|
||||
@ -23,10 +22,20 @@ import android.content.res.Resources
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.TypedValue
|
||||
import android.view.ViewPropertyAnimator
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.Transformation
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.core.animation.addListener
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.core.animation.doOnStart
|
||||
import androidx.core.view.isVisible
|
||||
import com.tommasoberlose.anotherwidget.R
|
||||
import com.tommasoberlose.anotherwidget.global.Preferences
|
||||
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
|
||||
import kotlinx.android.synthetic.main.fragment_app_main.*
|
||||
import kotlinx.android.synthetic.main.the_widget_sans.*
|
||||
import java.util.*
|
||||
|
||||
|
||||
@ -68,55 +77,72 @@ fun View.reveal(initialX: Int? = null, initialY: Int? = null) {
|
||||
}
|
||||
|
||||
|
||||
fun View.expand() {
|
||||
if (visibility != View.VISIBLE) {
|
||||
measure(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||
val targetHeight = measuredHeight
|
||||
fun View.expand(duration: Long = 500L) {
|
||||
clearAnimation()
|
||||
try {
|
||||
val animator = (tag as ValueAnimator)
|
||||
animator.removeAllListeners()
|
||||
animator.cancel()
|
||||
} catch (ex: java.lang.Exception) {}
|
||||
|
||||
layoutParams.height = 0
|
||||
visibility = View.VISIBLE
|
||||
val a = object : Animation() {
|
||||
protected override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
|
||||
layoutParams.height = if (interpolatedTime == 1f)
|
||||
LinearLayout.LayoutParams.WRAP_CONTENT
|
||||
else
|
||||
(targetHeight * interpolatedTime).toInt()
|
||||
translationY = 0f
|
||||
requestLayout()
|
||||
}
|
||||
|
||||
override fun willChangeBounds(): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
a.duration = 500L
|
||||
startAnimation(a)
|
||||
layoutParams = layoutParams.apply {
|
||||
height = RelativeLayout.LayoutParams.WRAP_CONTENT
|
||||
}
|
||||
measure(0, 0)
|
||||
|
||||
val initialHeight = measuredHeight
|
||||
val anim = ValueAnimator.ofFloat(
|
||||
alpha,
|
||||
1f
|
||||
).apply {
|
||||
this.duration = duration
|
||||
addUpdateListener {
|
||||
val animatedValue = animatedValue as Float
|
||||
layoutParams = layoutParams.apply {
|
||||
height = (initialHeight * animatedValue).toInt()
|
||||
}
|
||||
translationY = (initialHeight * animatedValue - initialHeight)
|
||||
alpha = animatedValue
|
||||
}
|
||||
addListener(
|
||||
onStart = {
|
||||
isVisible = true
|
||||
}
|
||||
)
|
||||
}
|
||||
tag = anim
|
||||
anim.start()
|
||||
}
|
||||
|
||||
fun View.collapse(duration: Long = 500L) {
|
||||
if (visibility != View.GONE) {
|
||||
val initialHeight = measuredHeight
|
||||
|
||||
val a = object : Animation() {
|
||||
protected override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
|
||||
if (interpolatedTime == 1f) {
|
||||
visibility = View.GONE
|
||||
} else {
|
||||
layoutParams.height = initialHeight - (initialHeight * interpolatedTime).toInt()
|
||||
requestLayout()
|
||||
}
|
||||
}
|
||||
|
||||
override fun willChangeBounds(): Boolean {
|
||||
return true
|
||||
clearAnimation()
|
||||
try {
|
||||
val animator = (tag as ValueAnimator)
|
||||
animator.removeAllListeners()
|
||||
animator.cancel()
|
||||
} catch (ex: java.lang.Exception) {}
|
||||
val initialHeight = measuredHeight
|
||||
val anim = ValueAnimator.ofFloat(
|
||||
alpha,
|
||||
0f
|
||||
).apply {
|
||||
this.duration = duration
|
||||
addUpdateListener {
|
||||
val animatedValue = animatedValue as Float
|
||||
layoutParams = layoutParams.apply {
|
||||
height = (initialHeight * animatedValue).toInt()
|
||||
}
|
||||
translationY = (initialHeight * animatedValue - initialHeight)
|
||||
alpha = animatedValue
|
||||
}
|
||||
|
||||
a.duration = duration //(initialHeight / v.context.resources.displayMetrics.density).toLong()
|
||||
startAnimation(a)
|
||||
addListener(
|
||||
onEnd = {
|
||||
isVisible = false
|
||||
}
|
||||
)
|
||||
}
|
||||
tag = anim
|
||||
anim.start()
|
||||
}
|
||||
|
||||
fun Context.openURI(url: String) {
|
||||
|
BIN
app/src/main/res/drawable-hdpi/round_design_services.png
Normal file
After Width: | Height: | Size: 583 B |
After Width: | Height: | Size: 348 B |
After Width: | Height: | Size: 446 B |
After Width: | Height: | Size: 694 B |
BIN
app/src/main/res/drawable-hdpi/round_grass_white.png
Normal file
After Width: | Height: | Size: 435 B |
BIN
app/src/main/res/drawable-hdpi/round_grass_white_18.png
Normal file
After Width: | Height: | Size: 364 B |
BIN
app/src/main/res/drawable-hdpi/round_grass_white_36.png
Normal file
After Width: | Height: | Size: 611 B |
BIN
app/src/main/res/drawable-hdpi/round_grass_white_48.png
Normal file
After Width: | Height: | Size: 781 B |
BIN
app/src/main/res/drawable-hdpi/round_near_me.png
Normal file
After Width: | Height: | Size: 253 B |
BIN
app/src/main/res/drawable-hdpi/round_near_me_white_24.png
Normal file
After Width: | Height: | Size: 307 B |
BIN
app/src/main/res/drawable-hdpi/round_near_me_white_36.png
Normal file
After Width: | Height: | Size: 429 B |
BIN
app/src/main/res/drawable-hdpi/round_near_me_white_48.png
Normal file
After Width: | Height: | Size: 532 B |
BIN
app/src/main/res/drawable-hdpi/round_topic_white_18.png
Normal file
After Width: | Height: | Size: 228 B |
BIN
app/src/main/res/drawable-hdpi/round_topic_white_24.png
Normal file
After Width: | Height: | Size: 217 B |
BIN
app/src/main/res/drawable-hdpi/round_topic_white_36.png
Normal file
After Width: | Height: | Size: 314 B |
BIN
app/src/main/res/drawable-hdpi/round_topic_white_48.png
Normal file
After Width: | Height: | Size: 365 B |
BIN
app/src/main/res/drawable-mdpi/round_design_services.png
Normal file
After Width: | Height: | Size: 446 B |
After Width: | Height: | Size: 232 B |
After Width: | Height: | Size: 306 B |
After Width: | Height: | Size: 516 B |
BIN
app/src/main/res/drawable-mdpi/round_grass_white.png
Normal file
After Width: | Height: | Size: 304 B |
BIN
app/src/main/res/drawable-mdpi/round_grass_white_18.png
Normal file
After Width: | Height: | Size: 258 B |
BIN
app/src/main/res/drawable-mdpi/round_grass_white_36.png
Normal file
After Width: | Height: | Size: 435 B |
BIN
app/src/main/res/drawable-mdpi/round_grass_white_48.png
Normal file
After Width: | Height: | Size: 535 B |
BIN
app/src/main/res/drawable-mdpi/round_near_me.png
Normal file
After Width: | Height: | Size: 188 B |
BIN
app/src/main/res/drawable-mdpi/round_near_me_white_24.png
Normal file
After Width: | Height: | Size: 222 B |
BIN
app/src/main/res/drawable-mdpi/round_near_me_white_36.png
Normal file
After Width: | Height: | Size: 307 B |
BIN
app/src/main/res/drawable-mdpi/round_near_me_white_48.png
Normal file
After Width: | Height: | Size: 390 B |
BIN
app/src/main/res/drawable-mdpi/round_topic_white_18.png
Normal file
After Width: | Height: | Size: 167 B |
BIN
app/src/main/res/drawable-mdpi/round_topic_white_24.png
Normal file
After Width: | Height: | Size: 158 B |
BIN
app/src/main/res/drawable-mdpi/round_topic_white_36.png
Normal file
After Width: | Height: | Size: 217 B |
BIN
app/src/main/res/drawable-mdpi/round_topic_white_48.png
Normal file
After Width: | Height: | Size: 264 B |
BIN
app/src/main/res/drawable-xhdpi/round_design_services.png
Normal file
After Width: | Height: | Size: 694 B |
After Width: | Height: | Size: 446 B |
After Width: | Height: | Size: 516 B |
After Width: | Height: | Size: 873 B |
BIN
app/src/main/res/drawable-xhdpi/round_grass_white.png
Normal file
After Width: | Height: | Size: 535 B |
BIN
app/src/main/res/drawable-xhdpi/round_grass_white_18.png
Normal file
After Width: | Height: | Size: 435 B |
BIN
app/src/main/res/drawable-xhdpi/round_grass_white_36.png
Normal file
After Width: | Height: | Size: 781 B |
BIN
app/src/main/res/drawable-xhdpi/round_grass_white_48.png
Normal file
After Width: | Height: | Size: 1012 B |
BIN
app/src/main/res/drawable-xhdpi/round_near_me.png
Normal file
After Width: | Height: | Size: 307 B |
BIN
app/src/main/res/drawable-xhdpi/round_near_me_white_24.png
Normal file
After Width: | Height: | Size: 390 B |
BIN
app/src/main/res/drawable-xhdpi/round_near_me_white_36.png
Normal file
After Width: | Height: | Size: 532 B |
BIN
app/src/main/res/drawable-xhdpi/round_near_me_white_48.png
Normal file
After Width: | Height: | Size: 676 B |
BIN
app/src/main/res/drawable-xhdpi/round_topic_white_18.png
Normal file
After Width: | Height: | Size: 217 B |
BIN
app/src/main/res/drawable-xhdpi/round_topic_white_24.png
Normal file
After Width: | Height: | Size: 264 B |
BIN
app/src/main/res/drawable-xhdpi/round_topic_white_36.png
Normal file
After Width: | Height: | Size: 365 B |
BIN
app/src/main/res/drawable-xhdpi/round_topic_white_48.png
Normal file
After Width: | Height: | Size: 454 B |
BIN
app/src/main/res/drawable-xxhdpi/round_design_services.png
Normal file
After Width: | Height: | Size: 962 B |
After Width: | Height: | Size: 583 B |
After Width: | Height: | Size: 694 B |
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable-xxhdpi/round_grass_white.png
Normal file
After Width: | Height: | Size: 781 B |
BIN
app/src/main/res/drawable-xxhdpi/round_grass_white_18.png
Normal file
After Width: | Height: | Size: 611 B |
BIN
app/src/main/res/drawable-xxhdpi/round_grass_white_36.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable-xxhdpi/round_grass_white_48.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/drawable-xxhdpi/round_near_me.png
Normal file
After Width: | Height: | Size: 429 B |
BIN
app/src/main/res/drawable-xxhdpi/round_near_me_white_24.png
Normal file
After Width: | Height: | Size: 532 B |
BIN
app/src/main/res/drawable-xxhdpi/round_near_me_white_36.png
Normal file
After Width: | Height: | Size: 731 B |
BIN
app/src/main/res/drawable-xxhdpi/round_near_me_white_48.png
Normal file
After Width: | Height: | Size: 962 B |
BIN
app/src/main/res/drawable-xxhdpi/round_topic_white_18.png
Normal file
After Width: | Height: | Size: 314 B |
BIN
app/src/main/res/drawable-xxhdpi/round_topic_white_24.png
Normal file
After Width: | Height: | Size: 365 B |
BIN
app/src/main/res/drawable-xxhdpi/round_topic_white_36.png
Normal file
After Width: | Height: | Size: 508 B |
BIN
app/src/main/res/drawable-xxhdpi/round_topic_white_48.png
Normal file
After Width: | Height: | Size: 698 B |
BIN
app/src/main/res/drawable-xxxhdpi/round_design_services.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 694 B |
After Width: | Height: | Size: 873 B |
After Width: | Height: | Size: 1.5 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/round_grass_white.png
Normal file
After Width: | Height: | Size: 1012 B |
BIN
app/src/main/res/drawable-xxxhdpi/round_grass_white_18.png
Normal file
After Width: | Height: | Size: 781 B |
BIN
app/src/main/res/drawable-xxxhdpi/round_grass_white_36.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/round_grass_white_48.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/round_near_me.png
Normal file
After Width: | Height: | Size: 532 B |
BIN
app/src/main/res/drawable-xxxhdpi/round_near_me_white_24.png
Normal file
After Width: | Height: | Size: 676 B |
BIN
app/src/main/res/drawable-xxxhdpi/round_near_me_white_36.png
Normal file
After Width: | Height: | Size: 962 B |
BIN
app/src/main/res/drawable-xxxhdpi/round_near_me_white_48.png
Normal file
After Width: | Height: | Size: 1.2 KiB |