Merge pull request #10 from SimpleMobileTools/master

upd
This commit is contained in:
solokot 2018-06-14 20:49:09 +03:00 committed by GitHub
commit 9215bca146
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
172 changed files with 788 additions and 410 deletions

View File

@ -1,6 +1,38 @@
Changelog
==========
Version 4.1.0 *(2018-06-13)*
----------------------------
* Make reminders on Android Oreo more reliable
* Allow deleting only future occurrences of repeating events
* Fixed some visual glitches at the weekly view
* Multiple CalDAV event related improvements
Version 4.0.4 *(2018-05-27)*
----------------------------
* Make sure the alarm rings properly at DND mode
* Improved the UK holidays and added Singapore ones
* Make Event list items more compact when possible
* Couple other UX improvements and bugfixes
Version 4.0.3 *(2018-05-15)*
----------------------------
* Fixing some widget related crashes
Version 4.0.2 *(2018-05-14)*
----------------------------
* Make sure we store the proper calendar ID at events
Version 4.0.1 *(2018-05-14)*
----------------------------
* Fix app not opening at clicking widgets
* Couple stability improvements
Version 4.0.0 *(2018-05-10)*
----------------------------

View File

@ -10,8 +10,8 @@ android {
applicationId "com.simplemobiletools.calendar"
minSdkVersion 16
targetSdkVersion 27
versionCode 119
versionName "4.0.0"
versionCode 124
versionName "4.1.0"
multiDexEnabled true
setProperty("archivesBaseName", "calendar")
}
@ -46,7 +46,7 @@ ext {
}
dependencies {
implementation 'com.simplemobiletools:commons:4.0.3'
implementation 'com.simplemobiletools:commons:4.1.7'
implementation 'joda-time:joda-time:2.9.9'
implementation 'com.facebook.stetho:stetho:1.5.0'
implementation 'com.android.support:multidex:1.0.3'

View File

@ -29,6 +29,8 @@
android:launchMode="singleTask"
android:theme="@style/SplashTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>

125
app/src/main/assets/singapore.ics Executable file
View File

@ -0,0 +1,125 @@
BEGIN:VCALENDAR
BEGIN:VEVENT
DTSTART;VALUE=DATE:20181225
DTEND;VALUE=DATE:20181226
UID:20181225-christmas-day@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Christmas Day
RRULE:FREQ=YEARLY;INTERVAL=1
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20181106
DTEND;VALUE=DATE:20181107
UID:20181106-deepavali@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Deepavali
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20191027
DTEND;VALUE=DATE:20191028
UID:20191027-deepavali@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Deepavali
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20180822
DTEND;VALUE=DATE:20180823
UID:20180822-hari-raya-haji@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Hari Raya Haji
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20190811
DTEND;VALUE=DATE:20190812
UID:20190811-hari-raya-haji@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Hari Raya Haji
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20180809
DTEND;VALUE=DATE:20180810
UID:20180809-national-day@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:National Day
RRULE:FREQ=YEARLY;INTERVAL=1
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20180615
DTEND;VALUE=DATE:20180616
UID:20180615-hari-raya-puasa@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Hari Raya Puasa
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20190605
DTEND;VALUE=DATE:20190606
UID:20190605-hari-raya-puasa@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Hari Raya Puasa
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20180529
DTEND;VALUE=DATE:20180530
UID:20180529-vesak-day@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Vesak Day
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20190519
DTEND;VALUE=DATE:20190520
UID:20190519-vesak-day@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Vesak Day
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20180501
DTEND;VALUE=DATE:20180502
UID:20180501-labour-day@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Labour Day
RRULE:FREQ=YEARLY;INTERVAL=1
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20180330
DTEND;VALUE=DATE:20180331
UID:20180330-good-friday@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Good Friday
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20190419
DTEND;VALUE=DATE:20190420
UID:20190419-good-friday@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Good Friday
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20180217
DTEND;VALUE=DATE:20180218
UID:20180217-chinese-new-year@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Chinese New Year
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20180216
DTEND;VALUE=DATE:20180217
UID:20180216-chinese-new-year@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Chinese New Year
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20180101
DTEND;VALUE=DATE:20180102
UID:20180101-new-years-day@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:New Year's Day
RRULE:FREQ=YEARLY;INTERVAL=1
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20190205
DTEND;VALUE=DATE:20190206
UID:20190205-chinese-new-year@www.mom.gov.sg
STATUS:CONFIRMED
SUMMARY:Chinese New Year
END:VEVENT
END:VCALENDAR

View File

@ -8,52 +8,20 @@ STATUS:CONFIRMED
RRULE:FREQ=YEARLY;INTERVAL=1
END:VEVENT
BEGIN:VEVENT
SUMMARY:St. David's Day
UID:a08053d8-530b-4025-8edf-81c88d05fe84
DTSTART;VALUE=DATE:20100301
DTEND;VALUE=DATE:20100302
STATUS:CONFIRMED
RRULE:FREQ=YEARLY;INTERVAL=1
END:VEVENT
BEGIN:VEVENT
SUMMARY:St. George's Day
UID:b58227e2-7f9d-4571-afa5-0ae93192d10e
DTSTART;VALUE=DATE:20100423
DTEND;VALUE=DATE:20100424
STATUS:CONFIRMED
RRULE:FREQ=YEARLY;INTERVAL=1
END:VEVENT
BEGIN:VEVENT
SUMMARY:Early May Bank Holiday
UID:21626542-636f-43d7-8fa9-bad05bb82dca
DTSTART;VALUE=DATE:20100503
DTEND;VALUE=DATE:20100504
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=5;BYDAY=1MO
STATUS:CONFIRMED
RRULE:FREQ=YEARLY;INTERVAL=1
END:VEVENT
BEGIN:VEVENT
SUMMARY:Summer Bank Holiday
UID:5dac6a63-e519-4ad1-a687-2fd5fccb4656
DTSTART;VALUE=DATE:20100802
DTEND;VALUE=DATE:20100803
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8;BYDAY=-1MO
STATUS:CONFIRMED
RRULE:FREQ=YEARLY;INTERVAL=1
END:VEVENT
BEGIN:VEVENT
SUMMARY:Summer Bank Holiday
UID:3d37b115-f0fa-4456-98c9-3b18cfffb47d
DTSTART;VALUE=DATE:20170828
DTEND;VALUE=DATE:20170829
STATUS:CONFIRMED
RRULE:FREQ=YEARLY;INTERVAL=1
END:VEVENT
BEGIN:VEVENT
SUMMARY:BST ends
UID:8eb163f3-6d42-494e-9e7c-747619cf965f
DTSTART:20101031T000000Z
DTEND:20101031T020000Z
STATUS:CONFIRMED
RRULE:FREQ=YEARLY;INTERVAL=1
END:VEVENT
BEGIN:VEVENT
SUMMARY:Christmas Day
@ -71,4 +39,26 @@ DTEND;VALUE=DATE:20101227
STATUS:CONFIRMED
RRULE:FREQ=YEARLY;INTERVAL=1
END:VEVENT
BEGIN:VEVENT
DTEND;VALUE=DATE:20190423
DTSTART;VALUE=DATE:20190422
SUMMARY:Easter Monday
UID:ca6af7456b0088abad9a69f9f620f5ac-59@gov.uk
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
DTEND;VALUE=DATE:20190420
DTSTART;VALUE=DATE:20190419
SUMMARY:Good Friday
UID:ca6af7456b0088abad9a69f9f620f5ac-58@gov.uk
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
SUMMARY:Spring Bank Holiday
UID:5dac6a63-e519-4ad1-a687-2fd5fccb4
DTSTART;VALUE=DATE:20100802
DTEND;VALUE=DATE:20100803
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=5;BYDAY=-1MO
STATUS:CONFIRMED
END:VEVENT
END:VCALENDAR

View File

@ -528,6 +528,7 @@ class EventActivity : SimpleActivity() {
event_caldav_calendar_email.beGoneIf(currentCalendar == null)
if (currentCalendar == null) {
mEventCalendarId = STORED_LOCALLY_ONLY
val mediumMargin = resources.getDimension(R.dimen.medium_margin).toInt()
event_caldav_calendar_name.apply {
text = getString(R.string.store_locally_only)
@ -561,11 +562,11 @@ class EventActivity : SimpleActivity() {
}
private fun deleteEvent() {
DeleteEventDialog(this, arrayListOf(mEvent.id)) {
if (it) {
dbHelper.deleteEvents(arrayOf(mEvent.id.toString()), true)
} else {
dbHelper.addEventRepeatException(mEvent.id, mEventOccurrenceTS, true)
DeleteEventDialog(this, arrayListOf(mEvent.id), mEvent.repeatInterval > 0) {
when (it) {
DELETE_SELECTED_OCCURRENCE -> dbHelper.addEventRepeatException(mEvent.id, mEventOccurrenceTS, true)
DELETE_FUTURE_OCCURRENCES -> dbHelper.addEventRepeatLimit(mEvent.id, mEventOccurrenceTS)
DELETE_ALL_OCCURRENCES -> dbHelper.deleteEvents(arrayOf(mEvent.id.toString()), true)
}
finish()
}

View File

@ -470,8 +470,9 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
try {
val formatter = SimpleDateFormat(format, Locale.getDefault())
val date = formatter.parse(startDate)
if (date.year < 70)
if (date.year < 70) {
date.year = 70
}
val timestamp = (date.time / 1000).toInt()
val source = if (birthdays) SOURCE_CONTACT_BIRTHDAY else SOURCE_CONTACT_ANNIVERSARY
@ -788,6 +789,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
put("Россия", "russia.ics")
put("România", "romania.ics")
put("Schweiz", "switzerland.ics")
put("Singapore", "singapore.ics")
put("Srbija", "serbia.ics")
put("Slovenija", "slovenia.ics")
put("Slovensko", "slovakia.ics")

View File

@ -8,7 +8,10 @@ import android.text.TextUtils
import com.simplemobiletools.calendar.R
import com.simplemobiletools.calendar.dialogs.SelectCalendarsDialog
import com.simplemobiletools.calendar.extensions.*
import com.simplemobiletools.calendar.helpers.*
import com.simplemobiletools.calendar.helpers.CalDAVHandler
import com.simplemobiletools.calendar.helpers.FONT_SIZE_LARGE
import com.simplemobiletools.calendar.helpers.FONT_SIZE_MEDIUM
import com.simplemobiletools.calendar.helpers.FONT_SIZE_SMALL
import com.simplemobiletools.calendar.models.EventType
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.dialogs.CustomIntervalPickerDialog
@ -16,6 +19,7 @@ import com.simplemobiletools.commons.dialogs.RadioGroupDialog
import com.simplemobiletools.commons.dialogs.SelectAlarmSoundDialog
import com.simplemobiletools.commons.extensions.*
import com.simplemobiletools.commons.helpers.ALARM_SOUND_TYPE_NOTIFICATION
import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS
import com.simplemobiletools.commons.helpers.PERMISSION_READ_CALENDAR
import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_CALENDAR
import com.simplemobiletools.commons.models.AlarmSound
@ -85,7 +89,7 @@ class SettingsActivity : SimpleActivity() {
private fun setupSectionColors() {
val adjustedPrimaryColor = getAdjustedPrimaryColor()
arrayListOf(reminders_label, caldav_label, weekly_view_label, monthly_view_label, simple_event_list_label, simple_font_size_label, events_label).forEach {
arrayListOf(reminders_label, caldav_label, weekly_view_label, monthly_view_label, simple_event_list_label, widgets_label, events_label).forEach {
it.setTextColor(adjustedPrimaryColor)
}
}
@ -291,7 +295,7 @@ class SettingsActivity : SimpleActivity() {
settings_reminder_sound.text = config.reminderSoundTitle
settings_reminder_sound_holder.setOnClickListener {
SelectAlarmSoundDialog(this, config.reminderSoundUri, AudioManager.STREAM_NOTIFICATION, GET_RINGTONE_URI, ALARM_SOUND_TYPE_NOTIFICATION, false,
SelectAlarmSoundDialog(this, config.reminderSoundUri, AudioManager.STREAM_ALARM, GET_RINGTONE_URI, ALARM_SOUND_TYPE_NOTIFICATION, false,
onAlarmPicked = {
if (it != null) {
updateReminderSound(it)

View File

@ -11,7 +11,6 @@ import com.simplemobiletools.calendar.adapters.EventListAdapter
import com.simplemobiletools.calendar.extensions.config
import com.simplemobiletools.calendar.extensions.seconds
import com.simplemobiletools.calendar.helpers.Formatter
import com.simplemobiletools.calendar.helpers.IS_CUSTOMIZING_COLORS
import com.simplemobiletools.calendar.helpers.MyWidgetListProvider
import com.simplemobiletools.calendar.models.ListEvent
import com.simplemobiletools.calendar.models.ListItem
@ -19,6 +18,7 @@ import com.simplemobiletools.calendar.models.ListSection
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
import com.simplemobiletools.commons.extensions.adjustAlpha
import com.simplemobiletools.commons.extensions.setFillWithStroke
import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS
import kotlinx.android.synthetic.main.widget_config_list.*
import org.joda.time.DateTime
import java.util.*
@ -32,7 +32,6 @@ class WidgetListConfigureActivity : SimpleActivity() {
private var mTextColor = 0
private var mEventsAdapter: EventListAdapter? = null
private var mIsCustomizingColors = false
public override fun onCreate(savedInstanceState: Bundle?) {
useDynamicTheme = false
@ -41,10 +40,10 @@ class WidgetListConfigureActivity : SimpleActivity() {
setContentView(R.layout.widget_config_list)
initVariables()
mIsCustomizingColors = intent.extras?.getBoolean(IS_CUSTOMIZING_COLORS) ?: false
val isCustomizingColors = intent.extras?.getBoolean(IS_CUSTOMIZING_COLORS) ?: false
mWidgetId = intent.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID) ?: AppWidgetManager.INVALID_APPWIDGET_ID
if (mWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID && !mIsCustomizingColors) {
if (mWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID && !isCustomizingColors) {
finish()
}

View File

@ -8,6 +8,7 @@ import com.simplemobiletools.calendar.activities.SimpleActivity
import com.simplemobiletools.calendar.dialogs.DeleteEventDialog
import com.simplemobiletools.calendar.extensions.config
import com.simplemobiletools.calendar.extensions.dbHelper
import com.simplemobiletools.calendar.extensions.handleEventDeleting
import com.simplemobiletools.calendar.extensions.shareEvents
import com.simplemobiletools.calendar.helpers.Formatter
import com.simplemobiletools.calendar.helpers.LOW_ALPHA
@ -111,26 +112,23 @@ class DayEventsAdapter(activity: SimpleActivity, val events: ArrayList<Event>, r
private fun askConfirmDelete() {
val eventIds = ArrayList<Int>(selectedPositions.size)
val timestamps = ArrayList<Int>(selectedPositions.size)
val eventsToDelete = ArrayList<Event>(selectedPositions.size)
selectedPositions.forEach {
eventIds.add(events[it].id)
timestamps.add(events[it].startTS)
val event = events[it]
eventsToDelete.add(event)
eventIds.add(event.id)
timestamps.add(event.startTS)
}
DeleteEventDialog(activity, eventIds) {
val eventsToDelete = ArrayList<Event>(selectedPositions.size)
selectedPositions.sortedDescending().forEach {
eventsToDelete.add(events[it])
}
val hasRepeatableEvent = eventsToDelete.any { it.repeatInterval > 0 }
DeleteEventDialog(activity, eventIds, hasRepeatableEvent) {
events.removeAll(eventsToDelete)
if (it) {
val eventIDs = Array(eventIds.size, { i -> (eventIds[i].toString()) })
activity.dbHelper.deleteEvents(eventIDs, true)
} else {
eventIds.forEachIndexed { index, value ->
activity.dbHelper.addEventRepeatException(value, timestamps[index], true)
}
}
val nonRepeatingEventIDs = eventsToDelete.filter { it.repeatInterval == 0 }.map { it.id.toString() }.toTypedArray()
activity.dbHelper.deleteEvents(nonRepeatingEventIDs, true)
val repeatingEventIDs = eventsToDelete.filter { it.repeatInterval != 0 }.map { it.id }
activity.handleEventDeleting(repeatingEventIDs, timestamps, it)
removeSelectedItems()
}
}

View File

@ -8,6 +8,7 @@ import com.simplemobiletools.calendar.activities.SimpleActivity
import com.simplemobiletools.calendar.dialogs.DeleteEventDialog
import com.simplemobiletools.calendar.extensions.config
import com.simplemobiletools.calendar.extensions.dbHelper
import com.simplemobiletools.calendar.extensions.handleEventDeleting
import com.simplemobiletools.calendar.extensions.shareEvents
import com.simplemobiletools.calendar.helpers.Formatter
import com.simplemobiletools.calendar.helpers.LOW_ALPHA
@ -29,11 +30,12 @@ class EventListAdapter(activity: SimpleActivity, var listItems: ArrayList<ListIt
recyclerView: MyRecyclerView, itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, null, itemClick) {
private val ITEM_EVENT = 0
private val ITEM_HEADER = 1
private val ITEM_EVENT_SIMPLE = 1
private val ITEM_HEADER = 2
private val topDivider = resources.getDrawable(R.drawable.divider_width)
private val allDayString = resources.getString(R.string.all_day)
private val replaceDescriptionWithLocation = activity.config.replaceDescription
private val replaceDescription = activity.config.replaceDescription
private val dimPastEvents = activity.config.dimPastEvents
private val now = getNowSeconds()
private var use24HourFormat = activity.config.use24HourFormat
@ -76,7 +78,11 @@ class EventListAdapter(activity: SimpleActivity, var listItems: ArrayList<ListIt
override fun getSelectableItemCount() = listItems.filter { it is ListEvent }.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyRecyclerViewAdapter.ViewHolder {
val layoutId = if (viewType == ITEM_EVENT) R.layout.event_list_item else R.layout.event_list_section
val layoutId = when (viewType) {
ITEM_EVENT -> R.layout.event_list_item
ITEM_EVENT_SIMPLE -> R.layout.event_list_item_simple
else -> R.layout.event_list_section
}
return createViewHolder(layoutId, parent)
}
@ -94,7 +100,17 @@ class EventListAdapter(activity: SimpleActivity, var listItems: ArrayList<ListIt
override fun getItemCount() = listItems.size
override fun getItemViewType(position: Int) = if (listItems[position] is ListEvent) ITEM_EVENT else ITEM_HEADER
override fun getItemViewType(position: Int) = if (listItems[position] is ListEvent) {
val event = listItems[position] as ListEvent
val detailField = if (replaceDescription) event.location else event.description
if (event.startTS == event.endTS && detailField.isEmpty()) {
ITEM_EVENT_SIMPLE
} else {
ITEM_EVENT
}
} else {
ITEM_HEADER
}
fun toggle24HourFormat(use24HourFormat: Boolean) {
this.use24HourFormat = use24HourFormat
@ -114,16 +130,16 @@ class EventListAdapter(activity: SimpleActivity, var listItems: ArrayList<ListIt
private fun setupListEvent(view: View, listEvent: ListEvent) {
view.apply {
event_section_title.text = listEvent.title
event_item_description.text = if (replaceDescriptionWithLocation) listEvent.location else listEvent.description
event_item_description?.text = if (replaceDescription) listEvent.location else listEvent.description
event_item_start.text = if (listEvent.isAllDay) allDayString else Formatter.getTimeFromTS(context, listEvent.startTS)
event_item_end.beInvisibleIf(listEvent.startTS == listEvent.endTS)
event_item_end?.beInvisibleIf(listEvent.startTS == listEvent.endTS)
event_item_color.applyColorFilter(listEvent.color)
if (listEvent.startTS != listEvent.endTS) {
val startCode = Formatter.getDayCodeFromTS(listEvent.startTS)
val endCode = Formatter.getDayCodeFromTS(listEvent.endTS)
event_item_end?.apply {
val startCode = Formatter.getDayCodeFromTS(listEvent.startTS)
val endCode = Formatter.getDayCodeFromTS(listEvent.endTS)
event_item_end.apply {
text = Formatter.getTimeFromTS(context, listEvent.endTS)
if (startCode != endCode) {
if (listEvent.isAllDay) {
@ -155,9 +171,9 @@ class EventListAdapter(activity: SimpleActivity, var listItems: ArrayList<ListIt
}
event_item_start.setTextColor(startTextColor)
event_item_end.setTextColor(endTextColor)
event_item_end?.setTextColor(endTextColor)
event_section_title.setTextColor(startTextColor)
event_item_description.setTextColor(startTextColor)
event_item_description?.setTextColor(startTextColor)
}
}
@ -187,31 +203,26 @@ class EventListAdapter(activity: SimpleActivity, var listItems: ArrayList<ListIt
private fun askConfirmDelete() {
val eventIds = ArrayList<Int>(selectedPositions.size)
val timestamps = ArrayList<Int>(selectedPositions.size)
val eventsToDelete = ArrayList<ListEvent>(selectedPositions.size)
selectedPositions.forEach {
selectedPositions.sortedDescending().forEach {
val item = listItems[it]
if (item is ListEvent) {
eventIds.add(item.id)
timestamps.add(item.startTS)
eventsToDelete.add(item)
}
}
DeleteEventDialog(activity, eventIds) {
val listItemsToDelete = ArrayList<ListItem>(selectedPositions.size)
selectedPositions.sortedDescending().forEach {
val listItem = listItems[it]
listItemsToDelete.add(listItem)
}
listItems.removeAll(listItemsToDelete)
val hasRepeatableEvent = eventsToDelete.any { it.isRepeatable }
DeleteEventDialog(activity, eventIds, hasRepeatableEvent) {
listItems.removeAll(eventsToDelete)
if (it) {
val eventIDs = Array(eventIds.size, { i -> (eventIds[i].toString()) })
activity.dbHelper.deleteEvents(eventIDs, true)
} else {
eventIds.forEachIndexed { index, value ->
activity.dbHelper.addEventRepeatException(value, timestamps[index], true)
}
}
val nonRepeatingEventIDs = eventsToDelete.filter { !it.isRepeatable }.map { it.id.toString() }.toTypedArray()
activity.dbHelper.deleteEvents(nonRepeatingEventIDs, true)
val repeatingEventIDs = eventsToDelete.filter { it.isRepeatable }.map { it.id }
activity.handleEventDeleting(repeatingEventIDs, timestamps, it)
listener?.refreshItems()
finishActMode()
}

View File

@ -40,8 +40,11 @@ class EventListWidgetAdapter(val context: Context) : RemoteViewsService.RemoteVi
val remoteView: RemoteViews
if (type == ITEM_EVENT) {
remoteView = RemoteViews(context.packageName, R.layout.event_list_item_widget)
setupListEvent(remoteView, events[position] as ListEvent)
val event = events[position] as ListEvent
val detailField = if (replaceDescription) event.location else event.description
val layout = if (event.startTS == event.endTS && detailField.isEmpty()) R.layout.event_list_item_widget_simple else R.layout.event_list_item_widget
remoteView = RemoteViews(context.packageName, layout)
setupListEvent(remoteView, event)
} else {
remoteView = RemoteViews(context.packageName, R.layout.event_list_section_widget)
setupListSection(remoteView, events[position] as ListSection)
@ -122,7 +125,7 @@ class EventListWidgetAdapter(val context: Context) : RemoteViewsService.RemoteVi
override fun getLoadingView() = null
override fun getViewTypeCount() = 2
override fun getViewTypeCount() = 3
override fun onCreate() {}
@ -150,7 +153,7 @@ class EventListWidgetAdapter(val context: Context) : RemoteViewsService.RemoteVi
prevCode = code
}
val listEvent = ListEvent(it.id, it.startTS, it.endTS, it.title, it.description, it.getIsAllDay(), it.color, it.location, it.isPastEvent)
val listEvent = ListEvent(it.id, it.startTS, it.endTS, it.title, it.description, it.getIsAllDay(), it.color, it.location, it.isPastEvent, it.repeatInterval > 0)
listItems.add(listEvent)
}

View File

@ -4,21 +4,23 @@ import android.app.Activity
import android.support.v7.app.AlertDialog
import android.view.ViewGroup
import com.simplemobiletools.calendar.R
import com.simplemobiletools.calendar.extensions.dbHelper
import com.simplemobiletools.calendar.helpers.DELETE_ALL_OCCURRENCES
import com.simplemobiletools.calendar.helpers.DELETE_FUTURE_OCCURRENCES
import com.simplemobiletools.calendar.helpers.DELETE_SELECTED_OCCURRENCE
import com.simplemobiletools.commons.extensions.beVisibleIf
import com.simplemobiletools.commons.extensions.setupDialogStuff
import kotlinx.android.synthetic.main.dialog_delete_event.view.*
class DeleteEventDialog(val activity: Activity, eventIds: List<Int>, val callback: (allOccurrences: Boolean) -> Unit) {
class DeleteEventDialog(val activity: Activity, eventIds: List<Int>, hasRepeatableEvent: Boolean, val callback: (deleteRule: Int) -> Unit) {
val dialog: AlertDialog?
init {
val events = activity.dbHelper.getEventsWithIds(eventIds)
val hasRepeatableEvent = events.any { it.repeatInterval > 0 }
val view = activity.layoutInflater.inflate(R.layout.dialog_delete_event, null).apply {
delete_event_repeat_description.beVisibleIf(hasRepeatableEvent)
delete_event_radio_view.beVisibleIf(hasRepeatableEvent)
if (!hasRepeatableEvent) {
delete_event_radio_view.check(R.id.delete_event_all)
}
if (eventIds.size > 1) {
delete_event_repeat_description.text = resources.getString(R.string.selection_contains_repetition)
@ -26,16 +28,20 @@ class DeleteEventDialog(val activity: Activity, eventIds: List<Int>, val callbac
}
dialog = AlertDialog.Builder(activity)
.setPositiveButton(R.string.yes, { dialog, which -> dialogConfirmed(view as ViewGroup, hasRepeatableEvent) })
.setPositiveButton(R.string.yes, { dialog, which -> dialogConfirmed(view as ViewGroup) })
.setNegativeButton(R.string.no, null)
.create().apply {
activity.setupDialogStuff(view, this)
}
}
private fun dialogConfirmed(view: ViewGroup, hasRepeatableEvent: Boolean) {
val deleteAllOccurrences = !hasRepeatableEvent || view.delete_event_radio_view.checkedRadioButtonId == R.id.delete_event_all
private fun dialogConfirmed(view: ViewGroup) {
val deleteRule = when (view.delete_event_radio_view.checkedRadioButtonId) {
R.id.delete_event_all -> DELETE_ALL_OCCURRENCES
R.id.delete_event_future -> DELETE_FUTURE_OCCURRENCES
else -> DELETE_SELECTED_OCCURRENCE
}
dialog?.dismiss()
callback(deleteAllOccurrences)
callback(deleteRule)
}
}

View File

@ -154,10 +154,10 @@ fun Context.notifyEvent(originalEvent: Event) {
if (event.repeatInterval != 0 && event.startTS - event.reminder1Minutes * 60 < currentSeconds) {
val events = dbHelper.getRepeatableEventsFor(currentSeconds - DAY_SECONDS, currentSeconds + YEAR_SECONDS, event.id)
for (currEvent in events) {
event = currEvent
if (event.startTS - event.reminder1Minutes * 60 > currentSeconds) {
if (currEvent.startTS - currEvent.reminder1Minutes * 60 > currentSeconds) {
break
}
event = currEvent
}
}
@ -189,12 +189,18 @@ fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content:
grantReadUriPermission(soundUri)
}
val channelId = "my_reminder_channel_$soundUri"
// create a new channel for every new sound uri as the new Android Oreo notification system is fundamentally broken
if (soundUri != config.lastSoundUri) {
config.lastReminderChannel = System.currentTimeMillis()
config.lastSoundUri = soundUri
}
val channelId = "simple_calendar_${config.lastReminderChannel}"
if (isOreoPlus()) {
val audioAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setLegacyStreamType(AudioManager.STREAM_NOTIFICATION)
.setLegacyStreamType(AudioManager.STREAM_ALARM)
.setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
.build()
@ -202,6 +208,7 @@ fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content:
val name = resources.getString(R.string.event_reminders)
val importance = NotificationManager.IMPORTANCE_HIGH
NotificationChannel(channelId, name, importance).apply {
setBypassDnd(true)
enableLights(true)
lightColor = event.color
enableVibration(false)
@ -213,15 +220,15 @@ fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content:
val contentTitle = if (publicVersion) resources.getString(R.string.app_name) else event.title
val contentText = if (publicVersion) resources.getString(R.string.public_event_notification_text) else content
val builder = NotificationCompat.Builder(this)
val builder = NotificationCompat.Builder(this, channelId)
.setContentTitle(contentTitle)
.setContentText(contentText)
.setSmallIcon(R.drawable.ic_calendar)
.setContentIntent(pendingIntent)
.setPriority(Notification.PRIORITY_HIGH)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setDefaults(Notification.DEFAULT_LIGHTS)
.setAutoCancel(true)
.setSound(Uri.parse(soundUri), AudioManager.STREAM_NOTIFICATION)
.setSound(Uri.parse(soundUri), AudioManager.STREAM_ALARM)
.setChannelId(channelId)
.addAction(R.drawable.ic_snooze, getString(R.string.snooze), getSnoozePendingIntent(this, event))
@ -304,7 +311,7 @@ fun Context.scheduleCalDAVSync(activate: Boolean) {
val alarm = getSystemService(Context.ALARM_SERVICE) as AlarmManager
if (activate) {
val syncCheckInterval = 4 * AlarmManager.INTERVAL_HOUR
val syncCheckInterval = 2 * AlarmManager.INTERVAL_HOUR
try {
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + syncCheckInterval, syncCheckInterval, pendingIntent)
} catch (ignored: SecurityException) {
@ -319,23 +326,27 @@ fun Context.syncCalDAVCalendars(activity: SimpleActivity?, calDAVSyncObserver: C
val uri = CalendarContract.Calendars.CONTENT_URI
contentResolver.unregisterContentObserver(calDAVSyncObserver)
contentResolver.registerContentObserver(uri, false, calDAVSyncObserver)
val accounts = HashSet<Account>()
val calendars = CalDAVHandler(applicationContext).getCalDAVCalendars(activity, config.caldavSyncedCalendarIDs)
calendars.forEach {
accounts.add(Account(it.accountName, it.accountType))
}
Bundle().apply {
putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true)
putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true)
accounts.forEach {
ContentResolver.requestSync(it, uri.authority, this)
}
}
refreshCalDAVCalendars(activity, config.caldavSyncedCalendarIDs)
}.start()
}
fun Context.refreshCalDAVCalendars(activity: SimpleActivity?, ids: String) {
val uri = CalendarContract.Calendars.CONTENT_URI
val accounts = HashSet<Account>()
val calendars = CalDAVHandler(applicationContext).getCalDAVCalendars(activity, ids)
calendars.forEach {
accounts.add(Account(it.accountName, it.accountType))
}
Bundle().apply {
putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true)
putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true)
accounts.forEach {
ContentResolver.requestSync(it, uri.authority, this)
}
}
}
fun Context.addDayNumber(rawTextColor: Int, day: DayMonthly, linearLayout: LinearLayout, dayLabelHeight: Int, callback: (Int) -> Unit) {
var textColor = rawTextColor
if (!day.isThisMonth)
@ -410,8 +421,27 @@ fun Context.getEventListItems(events: List<Event>): ArrayList<ListItem> {
listItems.add(listSection)
prevCode = code
}
val listEvent = ListEvent(it.id, it.startTS, it.endTS, it.title, it.description, it.getIsAllDay(), it.color, it.location, it.isPastEvent)
val listEvent = ListEvent(it.id, it.startTS, it.endTS, it.title, it.description, it.getIsAllDay(), it.color, it.location, it.isPastEvent, it.repeatInterval > 0)
listItems.add(listEvent)
}
return listItems
}
fun Context.handleEventDeleting(eventIds: List<Int>, timestamps: List<Int>, action: Int) {
when (action) {
DELETE_SELECTED_OCCURRENCE -> {
eventIds.forEachIndexed { index, value ->
dbHelper.addEventRepeatException(value, timestamps[index], true)
}
}
DELETE_FUTURE_OCCURRENCES -> {
eventIds.forEachIndexed { index, value ->
dbHelper.addEventRepeatLimit(value, timestamps[index])
}
}
DELETE_ALL_OCCURRENCES -> {
val eventIDs = Array(eventIds.size, { i -> (eventIds[i].toString()) })
dbHelper.deleteEvents(eventIDs, true)
}
}
}

View File

@ -38,19 +38,19 @@ class WeekFragment : Fragment(), WeeklyCalendar {
var mListener: WeekFragmentListener? = null
private var mWeekTimestamp = 0
private var mRowHeight = 0
private var mRowHeight = 0f
private var minScrollY = -1
private var maxScrollY = -1
private var mWasDestroyed = false
private var todayColumnIndex = -1
private var clickStartTime = 0L
private var primaryColor = 0
private var lastHash = 0
private var mWasDestroyed = false
private var isFragmentVisible = false
private var wasFragmentInit = false
private var wasExtraHeightAdded = false
private var dimPastEvents = true
private var clickStartTime = 0L
private var selectedGrid: View? = null
private var todayColumnIndex = -1
private var events = ArrayList<Event>()
private var allDayHolders = ArrayList<RelativeLayout>()
private var allDayRows = ArrayList<HashSet<Int>>()
@ -68,8 +68,8 @@ class WeekFragment : Fragment(), WeeklyCalendar {
it.map { eventTypeColors.put(it.id, it.color) }
}
mRowHeight = (context!!.resources.getDimension(R.dimen.weekly_view_row_height)).toInt()
minScrollY = mRowHeight * context!!.config.startWeeklyAt
mRowHeight = context!!.resources.getDimension(R.dimen.weekly_view_row_height)
minScrollY = (mRowHeight * context!!.config.startWeeklyAt).toInt()
mWeekTimestamp = arguments!!.getInt(WEEK_START_TIMESTAMP)
dimPastEvents = context!!.config.dimPastEvents
primaryColor = context!!.getAdjustedPrimaryColor()
@ -93,9 +93,6 @@ class WeekFragment : Fragment(), WeeklyCalendar {
updateScrollY(Math.max(mListener?.getCurrScrollY() ?: 0, minScrollY))
}
(0..6).map { inflater.inflate(R.layout.stroke_vertical_divider, mView.week_vertical_grid_holder) }
(0..23).map { inflater.inflate(R.layout.stroke_horizontal_divider, mView.week_horizontal_grid_holder) }
wasFragmentInit = true
return mView
}
@ -115,8 +112,8 @@ class WeekFragment : Fragment(), WeeklyCalendar {
return@onGlobalLayout
}
minScrollY = mRowHeight * context!!.config.startWeeklyAt
maxScrollY = mRowHeight * context!!.config.endWeeklyAt
minScrollY = (mRowHeight * context!!.config.startWeeklyAt).toInt()
maxScrollY = (mRowHeight * context!!.config.endWeeklyAt).toInt()
val bounds = Rect()
week_events_holder.getGlobalVisibleRect(bounds)
@ -190,14 +187,14 @@ class WeekFragment : Fragment(), WeeklyCalendar {
selectedGrid?.animation?.cancel()
selectedGrid?.beGone()
val rowHeight = resources.getDimension(R.dimen.weekly_view_row_height)
val hour = (event.y / rowHeight).toInt()
//val rowHeight = resources.getDimension(R.dimen.weekly_view_row_height)
val hour = (event.y / mRowHeight).toInt()
selectedGrid = (inflater.inflate(R.layout.week_grid_item, null, false) as ImageView).apply {
view.addView(this)
background = ColorDrawable(primaryColor)
layoutParams.width = view.width
layoutParams.height = rowHeight.toInt()
y = hour * rowHeight
layoutParams.height = mRowHeight.toInt()
y = hour * mRowHeight
applyColorFilter(primaryColor.getContrastColor())
setOnClickListener {
@ -214,19 +211,22 @@ class WeekFragment : Fragment(), WeeklyCalendar {
}
}
}
else -> {
}
}
}
override fun updateWeeklyCalendar(events: ArrayList<Event>) {
val newHash = events.hashCode()
if (context == null) {
return
}
val newEvents = context!!.getFilteredEvents(events)
val newHash = newEvents.hashCode()
if (newHash == lastHash) {
return
}
lastHash = newHash
this.events = events
this.events = newEvents
updateEvents()
}
@ -236,15 +236,13 @@ class WeekFragment : Fragment(), WeeklyCalendar {
}
activity!!.runOnUiThread {
if (context != null && isAdded) {
if (context != null && activity != null && isAdded) {
addEvents()
}
}
}
private fun addEvents() {
val filtered = context!!.getFilteredEvents(events)
initGrid()
allDayHolders.clear()
allDayRows.clear()
@ -259,7 +257,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
var hadAllDayEvent = false
val replaceDescription = context!!.config.replaceDescription
val sorted = filtered.sortedWith(compareBy({ it.startTS }, { it.endTS }, { it.title }, { if (replaceDescription) it.location else it.description }))
val sorted = events.sortedWith(compareBy({ it.startTS }, { it.endTS }, { it.title }, { if (replaceDescription) it.location else it.description }))
for (event in sorted) {
if (event.getIsAllDay() || Formatter.getDayCodeFromTS(event.startTS) != Formatter.getDayCodeFromTS(event.endTS)) {
hadAllDayEvent = true
@ -346,9 +344,6 @@ class WeekFragment : Fragment(), WeeklyCalendar {
private fun addAllDayEvent(event: Event) {
(inflater.inflate(R.layout.week_all_day_event_marker, null, false) as TextView).apply {
if (activity == null)
return
var backgroundColor = eventTypeColors.get(event.eventType, primaryColor)
var textColor = backgroundColor.getContrastColor()
if (dimPastEvents && event.isPastEvent) {
@ -404,7 +399,6 @@ class WeekFragment : Fragment(), WeeklyCalendar {
allDayHolders[drawAtLine].addView(this)
(layoutParams as RelativeLayout.LayoutParams).apply {
topMargin = mRes.getDimension(R.dimen.tiny_margin).toInt()
leftMargin = getColumnWithId(firstDayIndex).x.toInt()
bottomMargin = 1
width = getColumnWithId(Math.min(firstDayIndex + daysCnt, 6)).right - leftMargin - 1

View File

@ -10,6 +10,7 @@ import android.util.SparseIntArray
import com.simplemobiletools.calendar.activities.SimpleActivity
import com.simplemobiletools.calendar.extensions.config
import com.simplemobiletools.calendar.extensions.dbHelper
import com.simplemobiletools.calendar.extensions.refreshCalDAVCalendars
import com.simplemobiletools.calendar.extensions.scheduleCalDAVSync
import com.simplemobiletools.calendar.models.CalDAVCalendar
import com.simplemobiletools.calendar.models.Event
@ -188,7 +189,9 @@ class CalDAVHandler(val context: Context) {
var sortedColors = ArrayList<Int>(colors.size())
(0 until colors.size()).mapTo(sortedColors) { colors[it] }
sortedColors = sortedColors.distinct() as ArrayList<Int>
if (sortedColors.isNotEmpty()) {
sortedColors = sortedColors.distinct() as ArrayList<Int>
}
return sortedColors
}
@ -322,6 +325,7 @@ class CalDAVHandler(val context: Context) {
setupCalDAVEventReminders(event)
setupCalDAVEventImportId(event)
refreshCalDAVCalendar(event)
}
fun updateCalDAVEvent(event: Event) {
@ -335,6 +339,7 @@ class CalDAVHandler(val context: Context) {
setupCalDAVEventReminders(event)
setupCalDAVEventImportId(event)
refreshCalDAVCalendar(event)
}
private fun setupCalDAVEventReminders(event: Event) {
@ -412,12 +417,14 @@ class CalDAVHandler(val context: Context) {
context.contentResolver.delete(contentUri, null, null)
} catch (ignored: Exception) {
}
refreshCalDAVCalendar(event)
}
fun insertEventRepeatException(event: Event, occurrenceTS: Int): Long {
val uri = CalendarContract.Events.CONTENT_URI
val values = fillEventRepeatExceptionValues(event, occurrenceTS)
val newUri = context.contentResolver.insert(uri, values)
refreshCalDAVCalendar(event)
return java.lang.Long.parseLong(newUri.lastPathSegment)
}
@ -458,4 +465,6 @@ class CalDAVHandler(val context: Context) {
}
private fun getCalDAVEventImportId(calendarId: Int, eventId: Long) = "$CALDAV-$calendarId-$eventId"
private fun refreshCalDAVCalendar(event: Event) = context.refreshCalDAVCalendars(null, event.getCalDAVCalendarId().toString())
}

View File

@ -39,6 +39,14 @@ class Config(context: Context) : BaseConfig(context) {
get() = prefs.getString(REMINDER_SOUND_TITLE, context.getDefaultAlarmTitle(ALARM_SOUND_TYPE_NOTIFICATION))
set(reminderSoundTitle) = prefs.edit().putString(REMINDER_SOUND_TITLE, reminderSoundTitle).apply()
var lastSoundUri: String
get() = prefs.getString(LAST_SOUND_URI, "")
set(lastSoundUri) = prefs.edit().putString(LAST_SOUND_URI, lastSoundUri).apply()
var lastReminderChannel: Long
get() = prefs.getLong(LAST_REMINDER_CHANNEL_ID, 0L)
set(lastReminderChannel) = prefs.edit().putLong(LAST_REMINDER_CHANNEL_ID, lastReminderChannel).apply()
var storedView: Int
get() = prefs.getInt(VIEW, MONTHLY_VIEW)
set(view) = prefs.edit().putInt(VIEW, view).apply()

View File

@ -49,9 +49,10 @@ const val LAST_USED_LOCAL_EVENT_TYPE_ID = "last_used_local_event_type_id"
const val DISPLAY_PAST_EVENTS = "display_past_events"
const val REPLACE_DESCRIPTION = "replace_description"
const val SHOW_GRID = "show_grid"
const val IS_CUSTOMIZING_COLORS = "is_customizing_colors"
const val LOOP_REMINDERS = "loop_reminders"
const val DIM_PAST_EVENTS = "dim_past_events"
const val LAST_SOUND_URI = "last_sound_uri"
const val LAST_REMINDER_CHANNEL_ID = "last_reminder_channel_ID"
// repeat_rule for monthly and yearly repetition
const val REPEAT_SAME_DAY = 1 // i.e. 25th every month, or 3rd june (if yearly repetition)
@ -124,4 +125,8 @@ const val SOURCE_IMPORTED_ICS = "imported-ics"
const val SOURCE_CONTACT_BIRTHDAY = "contact-birthday"
const val SOURCE_CONTACT_ANNIVERSARY = "contact-anniversary"
const val DELETE_SELECTED_OCCURRENCE = 0
const val DELETE_FUTURE_OCCURRENCES = 1
const val DELETE_ALL_OCCURRENCES = 2
fun getNowSeconds() = (System.currentTimeMillis() / 1000).toInt()

View File

@ -552,6 +552,23 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
}
}
fun addEventRepeatLimit(eventId: Int, limitTS: Int) {
val values = ContentValues()
val time = Formatter.getDateTimeFromTS(limitTS)
values.put(COL_REPEAT_LIMIT, limitTS - time.hourOfDay)
val selection = "$COL_EVENT_ID = ?"
val selectionArgs = arrayOf(eventId.toString())
mDb.update(META_TABLE_NAME, values, selection, selectionArgs)
if (context.config.caldavSync) {
val event = getEventWithId(eventId)
if (event?.getCalDAVCalendarId() != 0) {
CalDAVHandler(context).updateCalDAVEvent(event!!)
}
}
}
fun deleteEventTypes(eventTypes: ArrayList<EventType>, deleteEvents: Boolean, callback: (deletedCnt: Int) -> Unit) {
var deleteIds = eventTypes.filter { it.caldavCalendarId == 0 }.map { it.id }
deleteIds = deleteIds.filter { it != DBHelper.REGULAR_EVENT_TYPE_ID } as ArrayList<Int>
@ -559,8 +576,9 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
val deletedSet = HashSet<String>()
deleteIds.map { deletedSet.add(it.toString()) }
context.config.removeDisplayEventTypes(deletedSet)
if (deleteIds.isEmpty())
if (deleteIds.isEmpty()) {
return
}
for (eventTypeId in deleteIds) {
if (deleteEvents) {
@ -756,7 +774,7 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
}
} else {
if (event.endTS >= fromTS) {
events.add(event.copy())
events.add(event.copy(isPastEvent = getIsPastEvent(event)))
} else if (event.getIsAllDay()) {
val dayCode = Formatter.getDayCodeFromTS(fromTS)
val endDayCode = Formatter.getDayCodeFromTS(event.endTS)

View File

@ -28,7 +28,7 @@ class MonthlyCalendarImpl(val mCallback: MonthlyCalendar, val mContext: Context)
val startTS = mTargetDate.minusDays(7).seconds()
val endTS = mTargetDate.plusDays(43).seconds()
mContext.dbHelper.getEvents(startTS, endTS) {
gotEvents(it as ArrayList<Event>)
gotEvents(it)
}
}
@ -131,7 +131,7 @@ class MonthlyCalendarImpl(val mCallback: MonthlyCalendar, val mContext: Context)
private fun gotEvents(events: ArrayList<Event>) {
mEvents = if (mFilterEventTypes) {
mContext.getFilteredEvents(events) as ArrayList<Event>
mContext.getFilteredEvents(events)
} else {
events
}

View File

@ -13,10 +13,7 @@ import com.simplemobiletools.calendar.activities.SplashActivity
import com.simplemobiletools.calendar.extensions.config
import com.simplemobiletools.calendar.extensions.launchNewEventIntent
import com.simplemobiletools.calendar.services.WidgetService
import com.simplemobiletools.commons.extensions.getColoredBitmap
import com.simplemobiletools.commons.extensions.setBackgroundColor
import com.simplemobiletools.commons.extensions.setText
import com.simplemobiletools.commons.extensions.setTextSize
import com.simplemobiletools.commons.extensions.*
import org.joda.time.DateTime
class MyWidgetListProvider : AppWidgetProvider() {
@ -54,7 +51,7 @@ class MyWidgetListProvider : AppWidgetProvider() {
views.setRemoteAdapter(R.id.widget_event_list, this)
}
val startActivityIntent = Intent(context, SplashActivity::class.java)
val startActivityIntent = context.getLaunchIntent() ?: Intent(context, SplashActivity::class.java)
val startActivityPendingIntent = PendingIntent.getActivity(context, 0, startActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT)
views.setPendingIntentTemplate(R.id.widget_event_list, startActivityPendingIntent)
views.setEmptyView(R.id.widget_event_list, R.id.widget_event_list_empty)
@ -83,7 +80,7 @@ class MyWidgetListProvider : AppWidgetProvider() {
}
private fun launchDayActivity(context: Context) {
Intent(context, SplashActivity::class.java).apply {
(context.getLaunchIntent() ?: Intent(context, SplashActivity::class.java)).apply {
putExtra(DAY_CODE, Formatter.getDayCodeFromDateTime(DateTime()))
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
context.startActivity(this)

View File

@ -46,7 +46,7 @@ class MyWidgetMonthlyProvider : AppWidgetProvider() {
}
private fun setupAppOpenIntent(context: Context, views: RemoteViews, id: Int, dayCode: String) {
Intent(context, SplashActivity::class.java).apply {
(context.getLaunchIntent() ?: Intent(context, SplashActivity::class.java)).apply {
putExtra(DAY_CODE, dayCode)
putExtra(OPEN_MONTH, true)
val pendingIntent = PendingIntent.getActivity(context, Integer.parseInt(dayCode.substring(0, 6)), this, 0)
@ -55,7 +55,7 @@ class MyWidgetMonthlyProvider : AppWidgetProvider() {
}
private fun setupDayOpenIntent(context: Context, views: RemoteViews, id: Int, dayCode: String) {
Intent(context, SplashActivity::class.java).apply {
(context.getLaunchIntent() ?: Intent(context, SplashActivity::class.java)).apply {
putExtra(DAY_CODE, dayCode)
val pendingIntent = PendingIntent.getActivity(context, Integer.parseInt(dayCode), this, 0)
views.setOnClickPendingIntent(id, pendingIntent)

View File

@ -14,7 +14,7 @@ class WeeklyCalendarImpl(val mCallback: WeeklyCalendar, val mContext: Context) {
val startTS = weekStartTS
val endTS = startTS + WEEK_SECONDS
mContext.dbHelper.getEvents(startTS, endTS) {
mEvents = it as ArrayList<Event>
mEvents = it
mCallback.updateWeeklyCalendar(it)
}
}

View File

@ -1,5 +1,4 @@
package com.simplemobiletools.calendar.models
data class DayMonthly(val value: Int, val isThisMonth: Boolean, val isToday: Boolean, val code: String, val weekOfYear: Int, var dayEvents: ArrayList<Event>,
var indexOnMonthView: Int) {
}
var indexOnMonthView: Int)

View File

@ -3,7 +3,6 @@ package com.simplemobiletools.calendar.models
import com.simplemobiletools.calendar.extensions.seconds
import com.simplemobiletools.calendar.helpers.*
import com.simplemobiletools.calendar.helpers.Formatter
import com.simplemobiletools.commons.helpers.DAY_SECONDS
import org.joda.time.DateTime
import java.io.Serializable
import java.util.*
@ -21,14 +20,12 @@ data class Event(var id: Int = 0, var startTS: Int = 0, var endTS: Int = 0, var
}
fun addIntervalTime(original: Event) {
when (repeatInterval) {
DAY -> {
startTS += DAY_SECONDS
endTS += DAY_SECONDS
}
val currStart = Formatter.getDateTimeFromTS(startTS)
val newStart: DateTime
newStart = when (repeatInterval) {
DAY -> currStart.plusDays(1)
else -> {
val currStart = Formatter.getDateTimeFromTS(startTS)
val newStart = when {
when {
repeatInterval % YEAR == 0 -> when (repeatRule) {
REPEAT_ORDER_WEEKDAY -> addXthDayInterval(currStart, original, false)
REPEAT_ORDER_WEEKDAY_USE_LAST -> addXthDayInterval(currStart, original, true)
@ -41,23 +38,17 @@ data class Event(var id: Int = 0, var startTS: Int = 0, var endTS: Int = 0, var
else -> currStart.plusMonths(repeatInterval / MONTH).dayOfMonth().withMaximumValue()
}
repeatInterval % WEEK == 0 -> {
// step through weekly repetition by days, as events can trigger multiple times a week
startTS += DAY_SECONDS
endTS += DAY_SECONDS
return
}
else -> {
startTS += repeatInterval
endTS += repeatInterval
return
// step through weekly repetition by days too, as events can trigger multiple times a week
currStart.plusDays(1)
}
else -> currStart.plusSeconds(repeatInterval)
}
val newStartTS = newStart.seconds()
val newEndTS = newStartTS + (endTS - startTS)
startTS = newStartTS
endTS = newEndTS
}
}
val newStartTS = newStart.seconds()
val newEndTS = newStartTS + (endTS - startTS)
startTS = newStartTS
endTS = newEndTS
}
// if an event should happen on 31st with Same Day monthly repetition, dont show it at all at months with 30 or less days

View File

@ -1,4 +1,4 @@
package com.simplemobiletools.calendar.models
data class ListEvent(var id: Int = 0, var startTS: Int = 0, var endTS: Int = 0, var title: String = "", var description: String = "",
var isAllDay: Boolean, var color: Int, var location: String = "", var isPastEvent: Boolean = false) : ListItem()
var isAllDay: Boolean, var color: Int, var location: String = "", var isPastEvent: Boolean = false, var isRepeatable: Boolean = false) : ListItem()

View File

@ -185,10 +185,12 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
weekNumberPaint.textAlign = Paint.Align.RIGHT
for (i in 0 until ROW_COUNT) {
val weekDays = days.subList(i * 7, i * 7 + 7)
weekNumberPaint.color = if (weekDays.any { it.isToday }) primaryColor else textColor
// fourth day of the week matters
val weekOfYear = days.getOrNull(i * 7 + 3)?.weekOfYear ?: 1
val id = "$weekOfYear:"
val yPos = i * dayHeight + weekDaysLetterHeight
canvas.drawText(id, horizontalOffset.toFloat() * 0.9f, yPos + paint.textSize, weekNumberPaint)
}

View File

@ -0,0 +1,35 @@
package com.simplemobiletools.calendar.views
import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import com.simplemobiletools.calendar.R
class WeeklyViewGrid(context: Context, attrs: AttributeSet, defStyle: Int) : View(context, attrs, defStyle) {
private val ROWS_CNT = 24
private val COLS_CNT = 7
private var paint = Paint(Paint.ANTI_ALIAS_FLAG)
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
init {
paint.color = context.resources.getColor(R.color.divider_grey)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
val rowHeight = height / ROWS_CNT.toFloat()
for (i in 0 until ROWS_CNT) {
val y = rowHeight * i.toFloat()
canvas.drawLine(0f, y, width.toFloat(), y, paint)
}
val rowWidth = width / COLS_CNT.toFloat()
for (i in 0 until COLS_CNT) {
val x = rowWidth * i.toFloat()
canvas.drawLine(x, 0f, x, height.toFloat(), paint)
}
}
}

View File

@ -2,9 +2,9 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="0px"
android:left="-2px"
android:right="-2px"
android:top="-2px">
android:left="-1px"
android:right="-1px"
android:top="-1px">
<shape android:shape="rectangle">
<solid android:color="@android:color/transparent"/>

View File

@ -2,9 +2,9 @@
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="0px"
android:left="-2px"
android:left="-1px"
android:right="0px"
android:top="-2px">
android:top="-1px">
<shape android:shape="rectangle">
<solid android:color="@android:color/transparent"/>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="-2px"
android:left="-2px"
android:bottom="-1px"
android:left="-1px"
android:right="0px"
android:top="-2px">
android:top="-1px">
<shape android:shape="rectangle">
<solid android:color="@android:color/transparent"/>

View File

@ -600,7 +600,7 @@
android:importantForAccessibility="no"/>
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/simple_font_size_label"
android:id="@+id/widgets_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/bigger_margin"

View File

@ -39,6 +39,14 @@
android:paddingTop="@dimen/normal_margin"
android:text="@string/delete_one_only"/>
<com.simplemobiletools.commons.views.MyCompatRadioButton
android:id="@+id/delete_event_future"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/normal_margin"
android:paddingTop="@dimen/normal_margin"
android:text="@string/delete_future_occurrences"/>
<com.simplemobiletools.commons.views.MyCompatRadioButton
android:id="@+id/delete_event_all"
android:layout_width="match_parent"

View File

@ -32,6 +32,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/event_item_start"
android:includeFontPadding="false"
android:text="15:00"
android:textSize="@dimen/day_text_size"/>
@ -57,6 +58,7 @@
android:layout_toLeftOf="@+id/event_item_color"
android:layout_toRightOf="@+id/event_item_end"
android:ellipsize="end"
android:includeFontPadding="false"
android:maxLines="1"
android:paddingRight="@dimen/activity_margin"
android:textSize="@dimen/day_text_size"

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/event_item_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:foreground="@drawable/selector"
android:paddingLeft="@dimen/activity_margin">
<RelativeLayout
android:id="@+id/event_item_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/medium_margin"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:paddingTop="@dimen/small_margin">
<TextView
android:id="@+id/event_item_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/day_text_size"
tools:text="13:00"/>
<TextView
android:id="@+id/event_section_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_margin"
android:layout_toLeftOf="@+id/event_item_color"
android:layout_toRightOf="@+id/event_item_start"
android:ellipsize="end"
android:maxLines="1"
android:paddingRight="@dimen/activity_margin"
android:textSize="@dimen/day_text_size"
tools:text="Event title"/>
<ImageView
android:id="@+id/event_item_color"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignBottom="@+id/event_section_title"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/event_section_title"
android:paddingRight="@dimen/medium_margin"
android:src="@drawable/monthly_event_dot"/>
</RelativeLayout>
</FrameLayout>

View File

@ -4,13 +4,14 @@
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/event_item_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/medium_margin">
<TextView
android:id="@+id/event_item_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/activity_margin"
android:layout_marginLeft="@dimen/medium_margin"
android:textSize="@dimen/day_text_size"
tools:text="13:00"/>
@ -19,7 +20,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/event_item_start"
android:layout_marginLeft="@dimen/activity_margin"
android:layout_marginLeft="@dimen/medium_margin"
android:includeFontPadding="false"
android:text="15:00"
android:textSize="@dimen/day_text_size"/>
@ -27,12 +29,12 @@
android:id="@+id/event_section_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/big_margin"
android:layout_marginLeft="@dimen/normal_margin"
android:layout_toLeftOf="@+id/event_item_color"
android:layout_toRightOf="@+id/event_item_start"
android:ellipsize="end"
android:maxLines="1"
android:paddingRight="@dimen/activity_margin"
android:paddingRight="@dimen/small_margin"
android:textSize="@dimen/day_text_size"
tools:text="Event title"/>
@ -41,12 +43,13 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/event_section_title"
android:layout_marginLeft="@dimen/big_margin"
android:layout_marginLeft="@dimen/normal_margin"
android:layout_toLeftOf="@+id/event_item_color"
android:layout_toRightOf="@+id/event_item_end"
android:ellipsize="end"
android:includeFontPadding="false"
android:maxLines="1"
android:paddingRight="@dimen/activity_margin"
android:paddingRight="@dimen/small_margin"
android:textSize="@dimen/day_text_size"
tools:text="Event description"/>
@ -58,7 +61,7 @@
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/event_section_title"
android:paddingRight="@dimen/activity_margin"
android:paddingRight="@dimen/medium_margin"
android:src="@drawable/monthly_event_dot"/>
</RelativeLayout>

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/event_item_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/medium_margin">
<TextView
android:id="@+id/event_item_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/medium_margin"
android:textSize="@dimen/day_text_size"
tools:text="13:00"/>
<TextView
android:id="@+id/event_section_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/normal_margin"
android:layout_toLeftOf="@+id/event_item_color"
android:layout_toRightOf="@+id/event_item_start"
android:ellipsize="end"
android:maxLines="1"
android:paddingRight="@dimen/small_margin"
android:textSize="@dimen/day_text_size"
tools:text="Event title"/>
<ImageView
android:id="@+id/event_item_color"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignBottom="@+id/event_section_title"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/event_section_title"
android:paddingRight="@dimen/medium_margin"
android:src="@drawable/monthly_event_dot"/>
</RelativeLayout>

View File

@ -6,6 +6,7 @@
android:layout_height="wrap_content"
android:drawablePadding="1dp"
android:drawableTop="@drawable/divider_width"
android:paddingTop="@dimen/medium_margin"
android:paddingBottom="@dimen/small_margin"
android:paddingTop="@dimen/small_margin"
android:textSize="@dimen/normal_text_size"
android:textStyle="bold"/>

View File

@ -5,12 +5,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/week_vertical_grid_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"/>
<com.simplemobiletools.calendar.views.MyScrollView
android:id="@+id/week_events_scrollview"
android:layout_width="match_parent"
@ -25,11 +19,10 @@
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
<com.simplemobiletools.calendar.views.WeeklyViewGrid
android:id="@+id/week_horizontal_grid_holder"
android:layout_width="match_parent"
android:layout_height="@dimen/weekly_view_events_height"
android:orientation="vertical"/>
android:layout_height="@dimen/weekly_view_events_height"/>
<LinearLayout
android:id="@+id/week_events_columns_holder"
@ -95,6 +88,7 @@
android:id="@+id/week_letters_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/stroke_bottom"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingBottom="@dimen/small_margin">

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/stroke_bottom"/>

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/stroke_right"/>

View File

@ -15,8 +15,8 @@
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1"
android:paddingLeft="@dimen/activity_margin"
android:paddingRight="@dimen/activity_margin"
android:paddingLeft="@dimen/medium_margin"
android:paddingRight="@dimen/medium_margin"
android:textSize="@dimen/normal_text_size"/>
<ImageView
@ -26,10 +26,10 @@
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:paddingBottom="@dimen/medium_margin"
android:paddingLeft="@dimen/normal_margin"
android:paddingRight="@dimen/normal_margin"
android:paddingTop="@dimen/normal_margin"
android:paddingBottom="@dimen/small_margin"
android:paddingLeft="@dimen/medium_margin"
android:paddingRight="@dimen/medium_margin"
android:paddingTop="@dimen/medium_margin"
android:scaleType="fitCenter"
android:src="@drawable/ic_plus"/>
@ -40,9 +40,8 @@
android:layout_below="@+id/widget_event_new_event"
android:clipToPadding="false"
android:divider="@null"
android:dividerHeight="@dimen/medium_margin"
android:paddingBottom="@dimen/medium_margin"
android:paddingLeft="@dimen/activity_margin"/>
android:paddingBottom="@dimen/small_margin"
android:paddingLeft="@dimen/medium_margin"/>
<TextView
android:id="@+id/widget_event_list_empty"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

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