Compare commits

..

54 Commits

Author SHA1 Message Date
49ca17803e Update translations 2020-10-27 18:21:55 +01:00
97ab72081d Update the UI 2020-10-27 18:13:27 +01:00
e6fee0dfe1 Merge branch 'master' of github.com:tommasoberlose/another-widget into develop 2020-10-27 18:13:15 +01:00
e0c4f24c43 Merge pull request #239 from Vgbhieel/master
Added Portuguese translation (values-pt)
2020-10-27 18:13:02 +01:00
2a7d0f171b Create strings,xml for portuguese values
translated all strings to portuguese
2020-10-23 00:55:39 -03:00
00dcfc3149 Merge branch 'master' of github.com:tommasoberlose/another-widget into develop 2020-10-20 10:39:19 +02:00
eb11b603aa Merge pull request #235 from Moutony/patch-24
Update French 2
2020-10-20 10:39:01 +02:00
4d2f624448 Merge branch 'master' of github.com:tommasoberlose/another-widget into develop 2020-10-20 10:38:47 +02:00
7581af4dd2 Merge branch 'english-strings' 2020-10-20 10:38:19 +02:00
0325af6582 Fix uppercase labels 2020-10-20 10:35:54 +02:00
4de0413a35 Fix multiple bugs 2020-10-20 10:27:05 +02:00
c54a24c889 Update strings.xml 2020-10-19 21:54:51 +02:00
98eccd2833 Update strings.xml 2020-10-19 21:54:17 +02:00
0119a20765 Update strings.xml 2020-10-19 21:51:12 +02:00
a1e54892fd Update strings.xml 2020-10-19 16:28:38 +02:00
17801fd164 Update strings.xml 2020-10-19 16:26:57 +02:00
e6087b2969 Merge pull request #234 from Moutony/patch-23
Update French
2020-10-19 15:35:06 +02:00
59b8ba26a2 Merge pull request #232 from d-l-n/master
Added and translated new strings
2020-10-19 15:35:01 +02:00
f190ee5d15 Merge pull request #231 from Drumber/translation
Update German translation
2020-10-19 15:34:48 +02:00
2f266ffcf8 Update strings.xml 2020-10-19 11:07:05 +02:00
0e376aba80 Update strings.xml 2020-10-19 11:06:29 +02:00
313e4fa92d Update French 2020-10-19 11:01:21 +02:00
a8ec754bc4 Added and translated new strings 2020-10-19 01:04:33 -03:00
f8d1188634 Update strings.xml
Added greetings and notification timeout strings
2020-10-18 18:47:52 +02:00
8216fc96b9 Update English strings.xml
Removed OpenWeatherMap former instructions.
Capitalized all action buttons.
name="action_save" translatable="false">OK
2020-10-18 16:15:22 +02:00
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
a1a6f9f607 Fix the privacy policy error 2020-10-14 14:56:37 +02:00
128 changed files with 1714 additions and 542 deletions

Binary file not shown.

View File

@ -23,11 +23,13 @@ android {
applicationId "com.tommasoberlose.anotherwidget"
minSdkVersion 23
targetSdkVersion 29
versionCode 107
versionCode 110
versionName "2.0.15"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildConfigField("String", "GOOGLE_API_KEY", apikeyProperties['GOOGLE_API_KEY'])
renderscriptSupportModeEnabled true
}
buildTypes {
@ -87,8 +89,8 @@ dependencies {
implementation 'org.greenrobot:eventbus:3.2.0'
// Navigation
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
// Other
implementation 'androidx.multidex:multidex:2.0.1'

Binary file not shown.

View File

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

View File

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

View File

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

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

View File

@ -32,7 +32,8 @@ object Constants {
CUSTOM_INFO("CUSTOM_INFO"),
GOOGLE_FIT_STEPS("GOOGLE_FIT_STEPS"),
NOTIFICATIONS("NOTIFICATIONS"),
GREETINGS("GREETINGS");
GREETINGS("GREETINGS"),
EVENTS("EVENTS");
companion object {
private val map = GlanceProviderId.values().associateBy(GlanceProviderId::id)
@ -61,6 +62,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),

View File

@ -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 = "")
@ -140,6 +141,8 @@ object Preferences : KotprefModel() {
var musicPlayersFilter by stringPref(default = "")
var appNotificationsFilter by stringPref(default = "")
var showEventsAsGlanceProvider by booleanPref(default = false)
// Integrations
var installedIntegrations by intPref(default = 0)
}

View File

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

View File

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

View File

@ -1,11 +1,14 @@
package com.tommasoberlose.anotherwidget.helpers
import android.Manifest
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
import com.tommasoberlose.anotherwidget.global.Preferences
import com.tommasoberlose.anotherwidget.models.GlanceProvider
import com.tommasoberlose.anotherwidget.utils.checkGrantedPermission
import com.tommasoberlose.anotherwidget.utils.checkIfFitInstalled
import java.util.ArrayList
@ -16,9 +19,10 @@ object GlanceProviderHelper {
val providers = Constants.GlanceProviderId.values()
.filter {
context.checkIfFitInstalled() || it != Constants.GlanceProviderId.GOOGLE_FIT_STEPS
}.toTypedArray()
}
.toTypedArray()
providers.sortWith(Comparator { p1, p2 ->
return ArrayList(providers.filter { enabledProviders.contains(it.id) }.sortedWith(Comparator { p1, p2 ->
when {
enabledProviders.contains(p1.id) && enabledProviders.contains(p2.id) -> {
enabledProviders.indexOf(p1.id).compareTo(enabledProviders.indexOf(p2.id))
@ -33,9 +37,7 @@ object GlanceProviderHelper {
p1.id.compareTo(p2.id)
}
}
})
return ArrayList(providers.toList())
}) + providers.filter { !enabledProviders.contains(it.id) })
}
fun getGlanceProviderById(context: Context, providerId: Constants.GlanceProviderId): GlanceProvider? {
@ -49,7 +51,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 +69,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_favorite_border
)
}
Constants.GlanceProviderId.NOTIFICATIONS -> {
@ -82,10 +84,16 @@ object GlanceProviderHelper {
R.drawable.round_history_edu
)
}
Constants.GlanceProviderId.EVENTS -> {
GlanceProvider(providerId.id,
context.getString(R.string.settings_show_events_as_glance_provider_title),
R.drawable.round_event_note
)
}
}
}
fun saveGlanceProviderOrder(list: ArrayList<Constants.GlanceProviderId>) {
fun saveGlanceProviderOrder(list: List<Constants.GlanceProviderId>) {
Preferences.enabledGlanceProviderOrder = list.joinToString(separator = ",")
}
@ -93,14 +101,17 @@ object GlanceProviderHelper {
val eventRepository = EventRepository(context)
BatteryHelper.updateBatteryInfo(context)
val showGlance = Preferences.showGlance && (eventRepository.getEventsCount() == 0 || !Preferences.showEvents)
val showGlance = Preferences.showGlance && (eventRepository.getEventsCount() == 0 || !Preferences.showEvents || Preferences.showEventsAsGlanceProvider)
&& (
(Preferences.showNotifications && ActiveNotificationsHelper.showLastNotification()) ||
(Preferences.showNextAlarm && AlarmHelper.getNextAlarm(context) != "") ||
(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()) ||
(Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(
Manifest.permission.READ_CALENDAR) && eventRepository.getNextEvent() != null)
)
eventRepository.close()
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
}
} 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()
}
}

View File

@ -8,11 +8,14 @@ import android.os.Build
import android.service.notification.NotificationListenerService
import android.service.notification.StatusBarNotification
import android.util.Log
import android.widget.Toast
import com.tommasoberlose.anotherwidget.global.Actions
import com.tommasoberlose.anotherwidget.global.Constants
import com.tommasoberlose.anotherwidget.global.Preferences
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.*
@ -31,14 +34,22 @@ class NotificationListener : NotificationListenerService() {
val isGroupHeader = sbn.notification.flags and Notification.FLAG_GROUP_SUMMARY != 0
val isOngoing = sbn.notification.flags and Notification.FLAG_ONGOING_EVENT != 0
if (bundle.containsKey(Notification.EXTRA_TITLE) && !isGroupHeader && !isOngoing && ActiveNotificationsHelper.isAppAccepted(sbn.packageName)) {
if (bundle.containsKey(Notification.EXTRA_TITLE) && !isGroupHeader && !isOngoing && ActiveNotificationsHelper.isAppAccepted(sbn.packageName) && !sbn.packageName.contains("com.android.systemui")) {
Preferences.lastNotificationId = sbn.id
Preferences.lastNotificationTitle = bundle.getString(Notification.EXTRA_TITLE) ?: ""
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
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 +80,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
)
)
)
}
}
}
}

View File

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

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.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

View File

@ -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 {

View File

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

View File

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

View File

@ -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
}
@ -364,7 +365,8 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
badgeGravity = BadgeDrawable.TOP_END
}?.isVisible = ((Preferences.showMusic || Preferences.showNotifications) && !ActiveNotificationsHelper.checkNotificationAccess(requireContext())) ||
(Preferences.showDailySteps && !(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || requireActivity().checkGrantedPermission(Manifest.permission.ACTIVITY_RECOGNITION))) ||
(AlarmHelper.isAlarmProbablyWrong(requireContext()))
(AlarmHelper.isAlarmProbablyWrong(requireContext())) ||
(Preferences.showEventsAsGlanceProvider && (!Preferences.showEvents || !requireContext().checkGrantedPermission(Manifest.permission.READ_CALENDAR)))
}
override fun onResume() {
@ -395,6 +397,7 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
}
class UpdateUiMessageEvent
class ChangeTabEvent(val page: Int)
@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(ignore: UpdateUiMessageEvent?) {
@ -406,4 +409,11 @@ class MainFragment : Fragment(), SharedPreferences.OnSharedPreferenceChangeList
}
}
}
@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(event: ChangeTabEvent?) {
event?.let {
pager.setCurrentItem(event.page, true)
}
}
}

View File

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

View File

@ -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
@ -171,7 +172,7 @@ class MainWidget : AppWidgetProvider() {
val nextEvent = eventRepository.getNextEvent()
val nextAlarm = AlarmHelper.getNextAlarm(context)
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null && !Preferences.showEventsAsGlanceProvider) {
if (Preferences.showNextEvent && eventRepository.getEventsCount() > 1) {
views.setImageViewBitmap(
R.id.action_next_rect,
@ -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,32 @@ class MainWidget : AppWidgetProvider() {
} catch (ex: Exception) {}
}
}
Constants.GlanceProviderId.GREETINGS -> {
if (Preferences.showGreetings && GreetingsHelper.showGreetings() && GreetingsHelper.getRandomString(context).isNotBlank()) {
showSomething = true
break@loop
}
}
Constants.GlanceProviderId.EVENTS -> {
if (Preferences.showEventsAsGlanceProvider&& Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
val pIntentDetail = PendingIntent.getActivity(
context,
widgetID,
IntentHelper.getEventIntent(
context,
nextEvent,
forceEventDetails = true
),
PendingIntent.FLAG_UPDATE_CURRENT
)
views.setOnClickPendingIntent(
R.id.second_row_rect,
pIntentDetail
)
showSomething = true
break@loop
}
}
}
}
@ -541,7 +572,7 @@ class MainWidget : AppWidgetProvider() {
val nextEvent = eventRepository.getNextEvent()
val nextAlarm = AlarmHelper.getNextAlarm(context)
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
if (Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null && !Preferences.showEventsAsGlanceProvider) {
// Multiple counter
v.action_next.isVisible =
Preferences.showNextEvent && eventRepository.getEventsCount() > 1
@ -606,7 +637,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 +649,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 +742,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 +760,60 @@ 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
}
}
Constants.GlanceProviderId.EVENTS -> {
if (Preferences.showEventsAsGlanceProvider && Preferences.showEvents && context.checkGrantedPermission(Manifest.permission.READ_CALENDAR) && nextEvent != null) {
v.next_event_date.text = context.getString(R.string.events_glance_provider_format).format(nextEvent.title, if (Preferences.showDiffTime && now.timeInMillis < nextEvent.startDate) {
if (!nextEvent.allDay) {
SettingsStringHelper.getDifferenceText(
context,
now.timeInMillis,
nextEvent.startDate
)
.toLowerCase(Locale.getDefault())
} else {
SettingsStringHelper.getAllDayEventDifferenceText(
context,
now.timeInMillis,
nextEvent.startDate
).toLowerCase(Locale.getDefault())
}
} else "").trimEnd()
v.second_row_icon.isVisible = true
v.second_row_icon.setImageDrawable(
ContextCompat.getDrawable(
context,
R.drawable.round_today
)
)
showSomething = true
break@loop
}
}
}
}
@ -782,9 +869,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 +912,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 +954,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) {

View File

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

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

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