Compare commits

..

28 Commits

Author SHA1 Message Date
56d95c5559 Update the bundle version 2020-10-18 12:58:13 +02:00
c0e747a714 Add greetings as glance provider 2020-10-18 12:51:02 +02:00
16076dc145 Fix #225 2020-10-18 11:21:52 +02:00
c95f9fb943 Fix #222 2020-10-18 11:20:40 +02:00
331d5772af Added the shadow to the icons 2020-10-16 18:04:30 +02:00
e2719b6445 Fix #181 2020-10-16 12:31:32 +02:00
bd35022f7d Merge branch 'master' of github.com:tommasoberlose/another-widget into develop 2020-10-16 11:58:38 +02:00
6d9cb750a7 Merge pull request #220 from Moutony/patch-20
Update strings.xml (English) for syntax
2020-10-16 11:58:27 +02:00
f85b4c9a6a Merge pull request #223 from Drumber/translation
Update German translation
2020-10-16 11:58:22 +02:00
df54a4a79e Merge pull request #221 from Moutony/patch-21
Update French
2020-10-16 11:58:10 +02:00
6ea97e7724 Fix the events order 2020-10-16 11:58:02 +02:00
d27071739d Update strings.xml 2020-10-15 22:59:12 +02:00
738781225f Update strings.xml
Added missing strings and updated some translations
2020-10-15 20:03:53 +02:00
12d32f852b Update French
Shortened some sentences
2020-10-15 19:10:17 +02:00
f0baa60363 Update strings.xml 2020-10-15 18:43:35 +02:00
785eb39334 Update strings.xml (English) for syntax
<string name="weather_warning">
2020-10-15 18:15:48 +02:00
d289699d08 Merge pull request #213 from Moutony/patch-17
Update strings.xml (English) for UI optimization
2020-10-15 10:12:58 +02:00
c68d0a8327 Merge pull request #215 from Moutony/patch-19
Update strings.xml (French)
2020-10-15 10:12:49 +02:00
de2e223713 Merge pull request #214 from chreddy/patch-3
Updating Danish translation
2020-10-15 10:12:15 +02:00
6150dd7e22 Fix #217 2020-10-15 10:10:38 +02:00
d9ecebe770 Update strings.xml 2020-10-14 22:30:44 +02:00
52327715b1 Update strings.xml
Change the data provider priority by sorting the list below with the drag-and-drop icons.
2020-10-14 22:23:28 +02:00
e301e6e6ec Update strings.xml
Grammar
2020-10-14 22:11:56 +02:00
c884fae362 Update strings.xml
Added (EN) to Legal & Privacy
2020-10-14 20:42:29 +02:00
eb78257e52 Update strings.xml
Fixed some old things too.
Update 2 of today.
2020-10-14 20:37:30 +02:00
109aa24af1 Update strings.xml (English) for UI optimization
I added periods for some sentences (error notice, full sentence with subject-verb-object)
I shortened some sentences that where on multiple rows with a single word in the last row.
Line 131: I changed grammar to be more correct.
Project header: I added Open-source to header, in order to shorten the Feedback subtitle.
2020-10-14 19:57:27 +02:00
2403f066a3 Updating Danish translation 2020-10-14 19:50:11 +02:00
9bc7d7b62e Update strings.xml (English) for UI optimization
I added periods for some sentences (error notice, full sentence with subject-verb-object)
I shortened some sentences that where on multiple rows with a single word in the last row.
Project header: I added Open-source to header, in order to shorten the Feedback subtitle.
2020-10-14 19:31:15 +02:00
118 changed files with 912 additions and 347 deletions

Binary file not shown.

View File

@ -23,11 +23,13 @@ android {
applicationId "com.tommasoberlose.anotherwidget" applicationId "com.tommasoberlose.anotherwidget"
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 29 targetSdkVersion 29
versionCode 108 versionCode 109
versionName "2.0.15" versionName "2.0.15"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY']) buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY'])
renderscriptSupportModeEnabled true
} }
buildTypes { buildTypes {

Binary file not shown.

View File

@ -25,6 +25,7 @@ import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
import com.tommasoberlose.anotherwidget.helpers.AlarmHelper import com.tommasoberlose.anotherwidget.helpers.AlarmHelper
import com.tommasoberlose.anotherwidget.helpers.GreetingsHelper
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver import com.tommasoberlose.anotherwidget.receivers.ActivityDetectionReceiver
import com.tommasoberlose.anotherwidget.ui.activities.AppNotificationsFilterActivity 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 view.action_filter_music_players.isVisible = provider == Constants.GlanceProviderId.PLAYING_SONG
if (provider == Constants.GlanceProviderId.PLAYING_SONG) { if (provider == Constants.GlanceProviderId.PLAYING_SONG) {
view.action_filter_music_players.setOnClickListener { view.action_filter_music_players.setOnClickListener {
context.startActivity(Intent(context, MusicPlayersFilterActivity::class.java)) dismiss()
context.startActivityForResult(Intent(context, MusicPlayersFilterActivity::class.java), 0)
} }
checkNotificationPermission(view) checkNotificationPermission(view)
} }
@ -94,10 +96,24 @@ class GlanceSettingsDialog(val context: Activity, val provider: Constants.Glance
/* NOTIFICATIONS */ /* NOTIFICATIONS */
view.action_filter_notifications_app.isVisible = provider == Constants.GlanceProviderId.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) { if (provider == Constants.GlanceProviderId.NOTIFICATIONS) {
checkLastNotificationsPermission(view) checkLastNotificationsPermission(view)
val stringArray = context.resources.getStringArray(R.array.glance_notifications_timeout)
view.action_filter_notifications_app.setOnClickListener { 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 -> { Constants.GlanceProviderId.GREETINGS -> {
Preferences.showGreetings = isChecked Preferences.showGreetings = isChecked
GreetingsHelper.toggleGreetings(context)
} }
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> { Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
if (isChecked) { if (isChecked) {

View File

@ -18,7 +18,7 @@ import kotlin.collections.ArrayList
class EventRepository(val context: Context) { class EventRepository(val context: Context) {
private val realm by lazy { Realm.getDefaultInstance() } private val realm by lazy { Realm.getDefaultInstance() }
fun saveEvents(eventList: ArrayList<Event>) { fun saveEvents(eventList: List<Event>) {
realm.executeTransaction { realm -> realm.executeTransaction { realm ->
realm.where(Event::class.java).findAll().deleteAllFromRealm() realm.where(Event::class.java).findAll().deleteAllFromRealm()
realm.copyToRealm(eventList) realm.copyToRealm(eventList)

View File

@ -13,4 +13,5 @@ object Actions {
const val ACTION_GO_TO_PREVIOUS_EVENT = "com.tommasoberlose.anotherwidget.action.GO_TO_PREVIOUS_EVENT" const val ACTION_GO_TO_PREVIOUS_EVENT = "com.tommasoberlose.anotherwidget.action.GO_TO_PREVIOUS_EVENT"
const val ACTION_REPORT_CRASH = "com.tommasoberlose.anotherwidget.action.REPORT_CRASH" const val ACTION_REPORT_CRASH = "com.tommasoberlose.anotherwidget.action.REPORT_CRASH"
const val ACTION_CLEAR_NOTIFICATION = "com.tommasoberlose.anotherwidget.action.CLEAR_NOTIFICATION" const val ACTION_CLEAR_NOTIFICATION = "com.tommasoberlose.anotherwidget.action.CLEAR_NOTIFICATION"
const val ACTION_UPDATE_GREETINGS = "com.tommasoberlose.anotherwidget.action.UPDATE_GREETINGS"
} }

View File

@ -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) { enum class WeatherIconPack(val value: Int) {
DEFAULT(0), DEFAULT(0),
MINIMAL(1), MINIMAL(1),

View File

@ -125,6 +125,7 @@ object Preferences : KotprefModel() {
var showDailySteps by booleanPref(default = false) var showDailySteps by booleanPref(default = false)
var showGreetings by booleanPref(default = false) var showGreetings by booleanPref(default = false)
var showNotifications 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 lastNotificationId by intPref(default = -1)
var lastNotificationTitle by stringPref(default = "") var lastNotificationTitle by stringPref(default = "")

View File

@ -80,4 +80,27 @@ object CalendarHelper {
.filter { (!Preferences.showOnlyBusyEvents || it.availability != CalendarContract.EventsEntity.AVAILABILITY_FREE) } .filter { (!Preferences.showOnlyBusyEvents || it.availability != CalendarContract.EventsEntity.AVAILABILITY_FREE) }
.toList() .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)
}
}
}
} }

View File

@ -1,6 +1,7 @@
package com.tommasoberlose.anotherwidget.helpers package com.tommasoberlose.anotherwidget.helpers
import android.content.Context import android.content.Context
import android.util.Log
import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.db.EventRepository import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Constants import com.tommasoberlose.anotherwidget.global.Constants
@ -16,7 +17,8 @@ object GlanceProviderHelper {
val providers = Constants.GlanceProviderId.values() val providers = Constants.GlanceProviderId.values()
.filter { .filter {
context.checkIfFitInstalled() || it != Constants.GlanceProviderId.GOOGLE_FIT_STEPS context.checkIfFitInstalled() || it != Constants.GlanceProviderId.GOOGLE_FIT_STEPS
}.toTypedArray() }
.toTypedArray()
providers.sortWith(Comparator { p1, p2 -> providers.sortWith(Comparator { p1, p2 ->
when { when {
@ -34,7 +36,6 @@ object GlanceProviderHelper {
} }
} }
}) })
return ArrayList(providers.toList()) return ArrayList(providers.toList())
} }
@ -49,7 +50,7 @@ object GlanceProviderHelper {
Constants.GlanceProviderId.PLAYING_SONG -> { Constants.GlanceProviderId.PLAYING_SONG -> {
GlanceProvider(providerId.id, GlanceProvider(providerId.id,
context.getString(R.string.settings_show_music_title), context.getString(R.string.settings_show_music_title),
R.drawable.round_radio R.drawable.round_music_note
) )
} }
Constants.GlanceProviderId.CUSTOM_INFO -> { Constants.GlanceProviderId.CUSTOM_INFO -> {
@ -67,7 +68,7 @@ object GlanceProviderHelper {
Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> { Constants.GlanceProviderId.GOOGLE_FIT_STEPS -> {
GlanceProvider(providerId.id, GlanceProvider(providerId.id,
context.getString(R.string.settings_daily_steps_title), context.getString(R.string.settings_daily_steps_title),
R.drawable.round_run_circle R.drawable.round_near_me
) )
} }
Constants.GlanceProviderId.NOTIFICATIONS -> { Constants.GlanceProviderId.NOTIFICATIONS -> {
@ -100,7 +101,8 @@ object GlanceProviderHelper {
(MediaPlayerHelper.isSomeonePlaying(context)) || (MediaPlayerHelper.isSomeonePlaying(context)) ||
(Preferences.showBatteryCharging && Preferences.isCharging || Preferences.isBatteryLevelLow) || (Preferences.showBatteryCharging && Preferences.isCharging || Preferences.isBatteryLevelLow) ||
(Preferences.customNotes.isNotEmpty()) || (Preferences.customNotes.isNotEmpty()) ||
(Preferences.showDailySteps && Preferences.googleFitSteps > 0) (Preferences.showDailySteps && Preferences.googleFitSteps > 0) ||
(Preferences.showGreetings && GreetingsHelper.showGreetings())
) )
eventRepository.close() eventRepository.close()
return showGlance return showGlance

View File

@ -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 ""
}
}

View File

@ -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)
}
}

View File

@ -66,7 +66,6 @@ object IntentHelper {
flags = Intent.FLAG_ACTIVITY_NEW_TASK flags = Intent.FLAG_ACTIVITY_NEW_TASK
} }
} catch (e: Exception) { } catch (e: Exception) {
context.toast(context.getString(R.string.error_opening_app))
Intent() Intent()
} }
} }
@ -96,7 +95,6 @@ object IntentHelper {
data = calendarUri data = calendarUri
} }
} catch (e: Exception) { } catch (e: Exception) {
context.toast(context.getString(R.string.error_opening_app))
Intent() Intent()
} }
} }
@ -181,7 +179,6 @@ object IntentHelper {
addCategory(Intent.CATEGORY_LAUNCHER) addCategory(Intent.CATEGORY_LAUNCHER)
} }
} catch (e: Exception) { } catch (e: Exception) {
context.toast(context.getString(R.string.error_opening_app))
Intent() Intent()
} }
} }
@ -204,7 +201,6 @@ object IntentHelper {
addCategory(Intent.CATEGORY_LAUNCHER) addCategory(Intent.CATEGORY_LAUNCHER)
} }
} catch (e: Exception) { } catch (e: Exception) {
context.toast(context.getString(R.string.error_opening_app))
Intent() Intent()
} }
} }
@ -218,7 +214,6 @@ object IntentHelper {
addCategory(Intent.CATEGORY_LAUNCHER) addCategory(Intent.CATEGORY_LAUNCHER)
} }
} catch (e: Exception) { } catch (e: Exception) {
context.toast(context.getString(R.string.error_opening_app))
Intent() Intent()
} }
} }
@ -230,7 +225,6 @@ object IntentHelper {
addCategory(Intent.CATEGORY_LAUNCHER) addCategory(Intent.CATEGORY_LAUNCHER)
} }
} catch (e: Exception) { } catch (e: Exception) {
context.toast(context.getString(R.string.error_opening_app))
Intent() Intent()
} }
} }

View File

@ -9,10 +9,12 @@ import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification import android.service.notification.StatusBarNotification
import android.util.Log import android.util.Log
import com.tommasoberlose.anotherwidget.global.Actions import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper import com.tommasoberlose.anotherwidget.helpers.ActiveNotificationsHelper
import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper import com.tommasoberlose.anotherwidget.helpers.MediaPlayerHelper
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import java.lang.Exception
import java.util.* import java.util.*
@ -35,10 +37,18 @@ class NotificationListener : NotificationListenerService() {
Preferences.lastNotificationId = sbn.id Preferences.lastNotificationId = sbn.id
Preferences.lastNotificationTitle = bundle.getString(Notification.EXTRA_TITLE) ?: "" Preferences.lastNotificationTitle = bundle.getString(Notification.EXTRA_TITLE) ?: ""
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { 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 Preferences.lastNotificationPackage = sbn.notification.smallIcon.resPackage
} else { } else {
Preferences.lastNotificationIcon = sbn.notification.icon try {
Preferences.lastNotificationIcon = sbn.notification.icon
} catch (ex: Exception) {
Preferences.lastNotificationIcon = 0
}
Preferences.lastNotificationPackage = sbn.packageName Preferences.lastNotificationPackage = sbn.packageName
} }
MainWidget.updateWidget(this) MainWidget.updateWidget(this)
@ -69,16 +79,26 @@ class NotificationListener : NotificationListenerService() {
action = Actions.ACTION_CLEAR_NOTIFICATION action = Actions.ACTION_CLEAR_NOTIFICATION
} }
cancel(PendingIntent.getBroadcast(context, 28943, intent, 0)) cancel(PendingIntent.getBroadcast(context, 28943, intent, 0))
setExact( val timeoutPref = Constants.GlanceNotificationTimer.fromInt(Preferences.hideNotificationAfter)
AlarmManager.RTC, if (timeoutPref != Constants.GlanceNotificationTimer.WHEN_DISMISSED) {
Calendar.getInstance().timeInMillis + 30 * 1000, setExact(
PendingIntent.getBroadcast( AlarmManager.RTC,
context, Calendar.getInstance().timeInMillis + when (timeoutPref) {
5, Constants.GlanceNotificationTimer.HALF_MINUTE -> 30 * 1000
intent, Constants.GlanceNotificationTimer.ONE_MINUTE -> 60 * 1000
0 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
)
) )
) }
} }
} }
} }

View File

@ -52,6 +52,9 @@ class UpdatesReceiver : BroadcastReceiver() {
ActiveNotificationsHelper.clearLastNotification(context) ActiveNotificationsHelper.clearLastNotification(context)
MainWidget.updateWidget(context) MainWidget.updateWidget(context)
} }
Actions.ACTION_UPDATE_GREETINGS -> {
MainWidget.updateWidget(context)
}
} }
} }

View File

@ -10,6 +10,7 @@ import com.tommasoberlose.anotherwidget.db.EventRepository
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper import com.tommasoberlose.anotherwidget.helpers.CalendarHelper
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.applyFilters import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.applyFilters
import com.tommasoberlose.anotherwidget.helpers.CalendarHelper.sortEvents
import com.tommasoberlose.anotherwidget.models.Event import com.tommasoberlose.anotherwidget.models.Event
import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
@ -44,8 +45,17 @@ class UpdateCalendarJob : JobIntentService() {
set(Calendar.HOUR_OF_DAY, 0) set(Calendar.HOUR_OF_DAY, 0)
} }
val limit = Calendar.getInstance().apply { val limit = Calendar.getInstance().apply {
timeInMillis = begin.timeInMillis when (Preferences.showUntil) {
add(Calendar.DAY_OF_YEAR, 2) 0 -> add(Calendar.HOUR, 3)
1 -> add(Calendar.HOUR, 6)
2 -> add(Calendar.HOUR, 12)
3 -> add(Calendar.DAY_OF_MONTH, 1)
4 -> add(Calendar.DAY_OF_MONTH, 3)
5 -> add(Calendar.DAY_OF_MONTH, 7)
6 -> add(Calendar.MINUTE, 30)
7 -> add(Calendar.HOUR, 1)
else -> add(Calendar.HOUR, 6)
}
} }
if (!checkGrantedPermission( if (!checkGrantedPermission(
@ -95,34 +105,16 @@ class UpdateCalendarJob : JobIntentService() {
} }
} }
val filteredEventList = eventList val sortedEvents = eventList.sortEvents()
val filteredEventList = sortedEvents
.applyFilters() .applyFilters()
if (filteredEventList.isEmpty()) { if (filteredEventList.isEmpty()) {
eventRepository.resetNextEventData() eventRepository.resetNextEventData()
eventRepository.clearEvents() eventRepository.clearEvents()
} else { } 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( eventRepository.saveEvents(
eventList sortedEvents
) )
eventRepository.saveNextEventData(filteredEventList.first()) eventRepository.saveNextEventData(filteredEventList.first())
} }

View File

@ -30,6 +30,7 @@ import kotlinx.android.synthetic.main.activity_choose_application.search
import kotlinx.android.synthetic.main.activity_music_players_filter.* import kotlinx.android.synthetic.main.activity_music_players_filter.*
import kotlinx.coroutines.* import kotlinx.coroutines.*
import net.idik.lib.slimadapter.SlimAdapter import net.idik.lib.slimadapter.SlimAdapter
import net.idik.lib.slimadapter.SlimAdapterEx
class ChooseApplicationActivity : AppCompatActivity() { class ChooseApplicationActivity : AppCompatActivity() {
@ -47,7 +48,7 @@ class ChooseApplicationActivity : AppCompatActivity() {
val mLayoutManager = LinearLayoutManager(this) val mLayoutManager = LinearLayoutManager(this)
list_view.layoutManager = mLayoutManager list_view.layoutManager = mLayoutManager
adapter = SlimAdapter.create() adapter = SlimAdapterEx.create()
adapter adapter
.register<String>(R.layout.application_info_layout) { _, injector -> .register<String>(R.layout.application_info_layout) { _, injector ->
injector injector

View File

@ -90,7 +90,7 @@ class CustomDateActivity : AppCompatActivity() {
ERROR_STRING ERROR_STRING
} }
} else { } else {
"__" ERROR_STRING
} }
if (viewModel.isDateCapitalize.value == true) { if (viewModel.isDateCapitalize.value == true) {
@ -102,7 +102,6 @@ class CustomDateActivity : AppCompatActivity() {
} }
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
action_save.isVisible = text != ERROR_STRING
loader.visibility = View.INVISIBLE loader.visibility = View.INVISIBLE
date_format_value.text = text date_format_value.text = text
} }
@ -143,15 +142,6 @@ class CustomDateActivity : AppCompatActivity() {
onBackPressed() onBackPressed()
} }
action_save.setOnClickListener {
Preferences.blockingBulk {
dateFormat = viewModel.dateInput.value ?: ""
isDateCapitalize = viewModel.isDateCapitalize.value ?: true
isDateUppercase = viewModel.isDateUppercase.value ?: false
}
finish()
}
action_capitalize.setOnClickListener { action_capitalize.setOnClickListener {
when { when {
viewModel.isDateUppercase.value == true -> { 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 { companion object {
const val ERROR_STRING = "--" const val ERROR_STRING = "--"
val DATE: Calendar = Calendar.getInstance().apply { val DATE: Calendar = Calendar.getInstance().apply {

View File

@ -66,6 +66,10 @@ class WeatherProviderActivity : AppCompatActivity() {
injector injector
.text(R.id.text, WeatherHelper.getProviderName(this, provider)) .text(R.id.text, WeatherHelper.getProviderName(this, provider))
.clicked(R.id.item) { .clicked(R.id.item) {
if (Preferences.weatherProvider != provider.value) {
Preferences.weatherProviderError = "-"
Preferences.weatherProviderLocationError = ""
}
val oldValue = Preferences.weatherProvider val oldValue = Preferences.weatherProvider
Preferences.weatherProvider = provider.value Preferences.weatherProvider = provider.value
updateListItem(oldValue) updateListItem(oldValue)
@ -77,6 +81,10 @@ class WeatherProviderActivity : AppCompatActivity() {
} }
} }
.clicked(R.id.radioButton) { .clicked(R.id.radioButton) {
if (Preferences.weatherProvider != provider.value) {
Preferences.weatherProviderError = "-"
Preferences.weatherProviderLocationError = ""
}
val oldValue = Preferences.weatherProvider val oldValue = Preferences.weatherProvider
Preferences.weatherProvider = provider.value Preferences.weatherProvider = provider.value
updateListItem(oldValue) updateListItem(oldValue)

View File

@ -241,8 +241,6 @@ class GlanceTabFragment : Fragment() {
val toPos = target.adapterPosition val toPos = target.adapterPosition
// move item in `fromPos` to `toPos` in adapter. // move item in `fromPos` to `toPos` in adapter.
adapter.notifyItemMoved(fromPos, toPos) adapter.notifyItemMoved(fromPos, toPos)
Collections.swap(list, fromPos, toPos)
return true return true
} }
@ -250,12 +248,21 @@ class GlanceTabFragment : Fragment() {
return false return false
} }
override fun clearView( override fun onMoved(
recyclerView: RecyclerView, 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) GlanceProviderHelper.saveGlanceProviderOrder(list)
super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y)
} }
override fun onChildDraw( 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 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, super.onChildDraw(c,
recyclerView, recyclerView,
@ -302,7 +308,6 @@ class GlanceTabFragment : Fragment() {
adapter.updateData( adapter.updateData(
GlanceProviderHelper.getGlanceProviders(requireContext()) GlanceProviderHelper.getGlanceProviders(requireContext())
.mapNotNull { GlanceProviderHelper.getGlanceProviderById(requireContext(), it) } .mapNotNull { GlanceProviderHelper.getGlanceProviderById(requireContext(), it) }
.filterNot { it.id == Constants.GlanceProviderId.GREETINGS.id }
) )
providers_list.isNestedScrollingEnabled = false providers_list.isNestedScrollingEnabled = false

View File

@ -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 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) Manifest.permission.ACCESS_BACKGROUND_LOCATION else Manifest.permission.ACCESS_FINE_LOCATION
) != true) ) != true)
|| (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-") || (Preferences.weatherProviderError != "" && Preferences.weatherProviderError != "-")
|| (Preferences.weatherProviderLocationError != "")
} else { } else {
false false
} }

View File

@ -42,6 +42,8 @@ import com.tommasoberlose.anotherwidget.ui.activities.WeatherProviderActivity
import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel
import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget import com.tommasoberlose.anotherwidget.ui.widgets.MainWidget
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.collapse
import com.tommasoberlose.anotherwidget.utils.expand
import kotlinx.android.synthetic.main.fragment_weather_settings.* import kotlinx.android.synthetic.main.fragment_weather_settings.*
import kotlinx.android.synthetic.main.fragment_weather_settings.scrollView import kotlinx.android.synthetic.main.fragment_weather_settings.scrollView
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -87,11 +89,6 @@ class WeatherTabFragment : Fragment() {
) { ) {
binding.isWeatherVisible = Preferences.showWeather binding.isWeatherVisible = Preferences.showWeather
viewModel.showWeatherWarning.observe(viewLifecycleOwner, Observer {
weather_warning?.isVisible = it
checkLocationPermission()
})
viewModel.showWeather.observe(viewLifecycleOwner, Observer { viewModel.showWeather.observe(viewLifecycleOwner, Observer {
maintainScrollPosition { maintainScrollPosition {
show_weather_label?.text = show_weather_label?.text =
@ -100,6 +97,7 @@ class WeatherTabFragment : Fragment() {
binding.isWeatherVisible = it binding.isWeatherVisible = it
} }
checkLocationPermission() checkLocationPermission()
checkWeatherProviderConfig()
}) })
viewModel.weatherProvider.observe(viewLifecycleOwner, Observer { viewModel.weatherProvider.observe(viewLifecycleOwner, Observer {
@ -174,7 +172,7 @@ class WeatherTabFragment : Fragment() {
WeatherReceiver.setUpdates(requireContext()) WeatherReceiver.setUpdates(requireContext())
} else if (Preferences.showWeather && Preferences.customLocationAdd == "") { } else if (Preferences.showWeather && Preferences.customLocationAdd == "") {
location_permission_alert?.isVisible = true location_permission_alert?.isVisible = true
background_location_warning.isVisible = false background_location_warning.isVisible = true
location_permission_alert?.setOnClickListener { location_permission_alert?.setOnClickListener {
MaterialBottomSheetDialog(requireContext(), message = getString(R.string.background_location_warning)) MaterialBottomSheetDialog(requireContext(), message = getString(R.string.background_location_warning))
.setPositiveButton(getString(android.R.string.ok)) { .setPositiveButton(getString(android.R.string.ok)) {
@ -188,18 +186,22 @@ class WeatherTabFragment : Fragment() {
} }
private fun checkWeatherProviderConfig() { 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_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 weather_provider_location_error?.text = Preferences.weatherProviderLocationError
} }
private fun setupListener() { private fun setupListener() {
action_hide_weather_warning.setOnClickListener {
Preferences.showWeatherWarning = false
}
action_show_weather.setOnClickListener { action_show_weather.setOnClickListener {
Preferences.showWeather = !Preferences.showWeather Preferences.showWeather = !Preferences.showWeather
} }

View File

@ -29,6 +29,7 @@ import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.helpers.* import com.tommasoberlose.anotherwidget.helpers.*
import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue import com.tommasoberlose.anotherwidget.helpers.ColorHelper.toIntValue
import com.tommasoberlose.anotherwidget.helpers.ImageHelper.applyShadow
import com.tommasoberlose.anotherwidget.receivers.* import com.tommasoberlose.anotherwidget.receivers.*
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.isDarkTheme import com.tommasoberlose.anotherwidget.utils.isDarkTheme
@ -350,8 +351,12 @@ class MainWidget : AppWidgetProvider() {
Constants.GlanceProviderId.NOTIFICATIONS -> { Constants.GlanceProviderId.NOTIFICATIONS -> {
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) { if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
try { try {
val remotePackageContext = context.createPackageContext(Preferences.lastNotificationPackage, 0) if (Preferences.lastNotificationIcon != 0) {
val icon = ContextCompat.getDrawable(remotePackageContext, Preferences.lastNotificationIcon) val remotePackageContext = context.createPackageContext(Preferences.lastNotificationPackage, 0)
ContextCompat.getDrawable(
remotePackageContext,
Preferences.lastNotificationIcon)
}
val notificationIntent = PendingIntent.getActivity( val notificationIntent = PendingIntent.getActivity(
context, context,
widgetID, widgetID,
@ -367,6 +372,12 @@ class MainWidget : AppWidgetProvider() {
} catch (ex: Exception) {} } 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++ dayDiff++
} else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get( } else if (startCal.get(Calendar.HOUR_OF_DAY) == endCal.get(Calendar.HOUR_OF_DAY) && startCal.get(
Calendar.MINUTE Calendar.MINUTE
) >= endCal.get(Calendar.MINUTE) ) > endCal.get(Calendar.MINUTE)
) { ) {
dayDiff++ dayDiff++
} }
@ -618,14 +629,27 @@ class MainWidget : AppWidgetProvider() {
context.getString(R.string.day_char) 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 { } else {
val flags: Int = val flags: Int =
DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH DateUtils.FORMAT_SHOW_DATE or DateUtils.FORMAT_NO_YEAR or DateUtils.FORMAT_ABBREV_MONTH
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) 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()) { if (Preferences.customNotes.isNotEmpty()) {
v.second_row_icon.isVisible = false v.second_row_icon.isVisible = false
v.next_event_date.text = Preferences.customNotes v.next_event_date.text = Preferences.customNotes
v.next_event_date.gravity
v.next_event_date.maxLines = 2 v.next_event_date.maxLines = 2
showSomething = true showSomething = true
break@loop break@loop
@ -717,16 +740,31 @@ class MainWidget : AppWidgetProvider() {
Constants.GlanceProviderId.NOTIFICATIONS -> { Constants.GlanceProviderId.NOTIFICATIONS -> {
if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) { if (Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) {
try { try {
val remotePackageContext = context.createPackageContext(Preferences.lastNotificationPackage, 0) if (Preferences.lastNotificationIcon != 0) {
val icon = ContextCompat.getDrawable(remotePackageContext, Preferences.lastNotificationIcon) val remotePackageContext = context.createPackageContext(Preferences.lastNotificationPackage, 0)
v.second_row_icon.isVisible = true val icon = ContextCompat.getDrawable(remotePackageContext,
v.second_row_icon.setImageDrawable(icon) 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 v.next_event_date.text = Preferences.lastNotificationTitle
showSomething = true showSomething = true
break@loop break@loop
} catch (ex: Exception) {} } 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) { if (Preferences.weatherIconPack != Constants.WeatherIconPack.MINIMAL.value) {
listOf<ImageView>(v.second_row_icon) listOf<ImageView>(v.second_row_icon, v.second_row_icon_shadow)
} else { } else {
listOf<ImageView>(v.second_row_icon, v.weather_icon) listOf<ImageView>(v.second_row_icon, v.weather_icon, v.second_row_icon_shadow)
}.forEach { }.forEach {
it.setColorFilter(ColorHelper.getSecondaryFontColorRgb(context.applicationContext.isDarkTheme())) it.setColorFilter(ColorHelper.getSecondaryFontColorRgb(context.applicationContext.isDarkTheme()))
it.alpha = it.alpha =
@ -825,8 +863,8 @@ class MainWidget : AppWidgetProvider() {
v.action_previous.scaleX = Preferences.textMainSize / 28f v.action_previous.scaleX = Preferences.textMainSize / 28f
v.action_previous.scaleY = Preferences.textMainSize / 28f v.action_previous.scaleY = Preferences.textMainSize / 28f
v.special_weather_icon.scaleX = Preferences.textMainSize / 20f v.special_weather_icon.scaleX = Preferences.textMainSize / 18f
v.special_weather_icon.scaleY = Preferences.textMainSize / 20f v.special_weather_icon.scaleY = Preferences.textMainSize / 18f
// Shadows // Shadows
@ -867,6 +905,38 @@ class MainWidget : AppWidgetProvider() {
it.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor) it.setShadowLayer(shadowRadius, 0f, shadowDy, shadowColor)
} }
// Icons shadow
listOf(
Pair(v.second_row_icon, v.second_row_icon_shadow),
).forEach {
if ((if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) == 0) {
it.second.isVisible = false
} else {
it.second.isVisible = it.first.isVisible
it.second.scaleX = it.first.scaleX
it.second.scaleY = it.first.scaleY
it.second.applyShadow(it.first)
}
}
listOf(
Pair(v.action_next, v.action_next_shadow),
Pair(v.action_previous, v.action_previous_shadow),
).forEach {
if ((if (context.isDarkTheme()) Preferences.textShadowDark else Preferences.textShadow) == 0) {
it.second.isVisible = false
} else {
it.second.isVisible = it.first.isVisible
it.second.scaleX = it.first.scaleX
it.second.scaleY = it.first.scaleY
it.second.applyShadow(it.first, 0.6f)
}
}
v.action_previous.scaleX = v.action_previous.scaleX * -1
v.action_previous_shadow.scaleX = v.action_previous_shadow.scaleX * -1
// Custom Font // Custom Font
if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) { if (Preferences.customFont == Constants.CUSTOM_FONT_GOOGLE_SANS) {
val googleSans: Typeface = when (Preferences.customFontVariant) { val googleSans: Typeface = when (Preferences.customFontVariant) {

View File

@ -1,12 +1,11 @@
package com.tommasoberlose.anotherwidget.utils package com.tommasoberlose.anotherwidget.utils
import android.animation.*
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.view.Gravity import android.view.Gravity
import android.view.View import android.view.View
import android.view.ViewAnimationUtils import android.view.ViewAnimationUtils
import android.widget.Toast import android.widget.Toast
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.app.Activity import android.app.Activity
import android.app.WallpaperManager import android.app.WallpaperManager
import android.content.* import android.content.*
@ -23,10 +22,20 @@ import android.content.res.Resources
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.util.DisplayMetrics import android.util.DisplayMetrics
import android.util.TypedValue import android.util.TypedValue
import android.view.ViewPropertyAnimator
import android.view.animation.Animation import android.view.animation.Animation
import android.view.animation.Transformation import android.view.animation.Transformation
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.RelativeLayout
import androidx.core.animation.addListener
import androidx.core.animation.doOnEnd
import androidx.core.animation.doOnStart
import androidx.core.view.isVisible
import com.tommasoberlose.anotherwidget.R import com.tommasoberlose.anotherwidget.R
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.ui.fragments.MainFragment
import kotlinx.android.synthetic.main.fragment_app_main.*
import kotlinx.android.synthetic.main.the_widget_sans.*
import java.util.* import java.util.*
@ -68,55 +77,72 @@ fun View.reveal(initialX: Int? = null, initialY: Int? = null) {
} }
fun View.expand() { fun View.expand(duration: Long = 500L) {
if (visibility != View.VISIBLE) { clearAnimation()
measure(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) try {
val targetHeight = measuredHeight val animator = (tag as ValueAnimator)
animator.removeAllListeners()
animator.cancel()
} catch (ex: java.lang.Exception) {}
layoutParams.height = 0 layoutParams = layoutParams.apply {
visibility = View.VISIBLE height = RelativeLayout.LayoutParams.WRAP_CONTENT
val a = object : Animation() {
protected override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
layoutParams.height = if (interpolatedTime == 1f)
LinearLayout.LayoutParams.WRAP_CONTENT
else
(targetHeight * interpolatedTime).toInt()
translationY = 0f
requestLayout()
}
override fun willChangeBounds(): Boolean {
return true
}
}
a.duration = 500L
startAnimation(a)
} }
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) { fun View.collapse(duration: Long = 500L) {
if (visibility != View.GONE) { clearAnimation()
val initialHeight = measuredHeight try {
val animator = (tag as ValueAnimator)
val a = object : Animation() { animator.removeAllListeners()
protected override fun applyTransformation(interpolatedTime: Float, t: Transformation) { animator.cancel()
if (interpolatedTime == 1f) { } catch (ex: java.lang.Exception) {}
visibility = View.GONE val initialHeight = measuredHeight
} else { val anim = ValueAnimator.ofFloat(
layoutParams.height = initialHeight - (initialHeight * interpolatedTime).toInt() alpha,
requestLayout() 0f
} ).apply {
} this.duration = duration
addUpdateListener {
override fun willChangeBounds(): Boolean { val animatedValue = animatedValue as Float
return true layoutParams = layoutParams.apply {
height = (initialHeight * animatedValue).toInt()
} }
translationY = (initialHeight * animatedValue - initialHeight)
alpha = animatedValue
} }
addListener(
a.duration = duration //(initialHeight / v.context.resources.displayMetrics.density).toLong() onEnd = {
startAnimation(a) isVisible = false
}
)
} }
tag = anim
anim.start()
} }
fun Context.openURI(url: String) { fun Context.openURI(url: String) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 731 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

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