From 52c403a7b14fa5de187f5971789a88dff279cfaa Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 27 Sep 2023 16:26:30 +0530 Subject: [PATCH 1/6] Fix attendee list visibility Broke during the recent view binding migration --- .../simplemobiletools/calendar/pro/activities/EventActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/EventActivity.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/EventActivity.kt index 917e8d556..154330dba 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/EventActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/EventActivity.kt @@ -1729,7 +1729,7 @@ class EventActivity : SimpleActivity() { autoCompleteView.focusSearch(View.FOCUS_DOWN)?.requestFocus() attendeeHolder.apply { - root.beVisible() + eventContactAttendee.beVisible() val attendeeStatusBackground = resources.getDrawable(R.drawable.attendee_status_circular_background) (attendeeStatusBackground as LayerDrawable).findDrawableByLayerId(R.id.attendee_status_circular_background) From 0241e3beead739075704f3716165f1dc240f855a Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 27 Sep 2023 23:14:07 +0530 Subject: [PATCH 2/6] Replace manual `attendees` serialization with type converter --- app/build.gradle.kts | 1 + .../calendar/pro/activities/EventActivity.kt | 16 ++++----- .../calendar/pro/helpers/CalDAVHelper.kt | 7 ++-- .../calendar/pro/helpers/Converters.kt | 14 ++++++++ .../calendar/pro/helpers/IcsImporter.kt | 2 +- .../calendar/pro/models/Attendee.kt | 35 ++++++++++++------- .../calendar/pro/models/Event.kt | 2 +- build.gradle.kts | 1 + gradle/libs.versions.toml | 2 ++ 9 files changed, 51 insertions(+), 29 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9762e9bbf..3920aeb0e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.android) alias(libs.plugins.kotlinAndroid) alias(libs.plugins.ksp) + alias(libs.plugins.parcelize) base } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/EventActivity.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/EventActivity.kt index 154330dba..3fff581c0 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/EventActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/EventActivity.kt @@ -24,8 +24,6 @@ import android.widget.RelativeLayout import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.MaterialTimePicker.INPUT_MODE_CLOCK import com.google.android.material.timepicker.TimeFormat -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken import com.simplemobiletools.calendar.pro.R import com.simplemobiletools.calendar.pro.adapters.AutoCompleteTextViewAdapter import com.simplemobiletools.calendar.pro.databinding.ActivityEventBinding @@ -171,7 +169,7 @@ class EventActivity : SimpleActivity() { putInt(REPEAT_RULE, mRepeatRule) putLong(REPEAT_LIMIT, mRepeatLimit) - putString(ATTENDEES, getAllAttendees(false)) + putParcelableArrayList(ATTENDEES, getAllAttendees(false)) putInt(AVAILABILITY, mAvailability) putInt(EVENT_COLOR, mEventColor) @@ -213,8 +211,7 @@ class EventActivity : SimpleActivity() { mRepeatRule = getInt(REPEAT_RULE) mRepeatLimit = getLong(REPEAT_LIMIT) - val token = object : TypeToken>() {}.type - mAttendees = Gson().fromJson>(getString(ATTENDEES), token) ?: ArrayList() + mAttendees = getParcelableArrayList(ATTENDEES) ?: arrayListOf() mEventTypeId = getLong(EVENT_TYPE_ID) mEventCalendarId = getInt(EVENT_CALENDAR_ID) @@ -507,8 +504,7 @@ class EventActivity : SimpleActivity() { mAvailability = mEvent.availability mEventColor = mEvent.color - val token = object : TypeToken>() {}.type - mAttendees = Gson().fromJson>(mEvent.attendees, token) ?: ArrayList() + mAttendees = mEvent.attendees.toMutableList() as ArrayList checkRepeatTexts(mRepeatInterval) checkAttendees() @@ -1310,7 +1306,7 @@ class EventActivity : SimpleActivity() { flags = mEvent.flags.addBitIf(binding.eventAllDay.isChecked, FLAG_ALL_DAY) repeatLimit = if (repeatInterval == 0) 0 else mRepeatLimit repeatRule = mRepeatRule - attendees = if (mEventCalendarId == STORED_LOCALLY_ONLY) "" else getAllAttendees(true) + attendees = if (mEventCalendarId == STORED_LOCALLY_ONLY) emptyList() else getAllAttendees(true) eventType = newEventType lastUpdated = System.currentTimeMillis() source = newSource @@ -1817,7 +1813,7 @@ class EventActivity : SimpleActivity() { } } - private fun getAllAttendees(isSavingEvent: Boolean): String { + private fun getAllAttendees(isSavingEvent: Boolean): ArrayList { var attendees = ArrayList() mSelectedContacts.forEach { attendees.add(it) @@ -1839,7 +1835,7 @@ class EventActivity : SimpleActivity() { } } - return Gson().toJson(attendees) + return attendees } private fun getNames(): List { diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/CalDAVHelper.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/CalDAVHelper.kt index a7df25fd7..f0f577e39 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/CalDAVHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/CalDAVHelper.kt @@ -7,8 +7,6 @@ import android.content.Context import android.graphics.Color import android.provider.CalendarContract.* import android.widget.Toast -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken import com.simplemobiletools.calendar.pro.R import com.simplemobiletools.calendar.pro.extensions.* import com.simplemobiletools.calendar.pro.models.* @@ -213,7 +211,7 @@ class CalDAVHelper(val context: Context) { val originalId = cursor.getStringValue(Events.ORIGINAL_ID) val originalInstanceTime = cursor.getLongValue(Events.ORIGINAL_INSTANCE_TIME) val reminders = getCalDAVEventReminders(id) - val attendees = Gson().toJson(getCalDAVEventAttendees(id)) + val attendees = getCalDAVEventAttendees(id) val availability = cursor.getIntValue(Events.AVAILABILITY) val status = cursor.getIntValue(Events.STATUS) val color = cursor.getIntValueOrNull(Events.EVENT_COLOR) @@ -394,8 +392,7 @@ class CalDAVHelper(val context: Context) { private fun setupCalDAVEventAttendees(event: Event) { clearEventAttendees(event) - val attendees = Gson().fromJson>(event.attendees, object : TypeToken>() {}.type) ?: ArrayList() - attendees.forEach { + event.attendees.forEach { val contentValues = ContentValues().apply { put(Attendees.ATTENDEE_NAME, it.name) put(Attendees.ATTENDEE_EMAIL, it.email) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/Converters.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/Converters.kt index 94472f47f..106dd0a42 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/Converters.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/Converters.kt @@ -3,10 +3,12 @@ package com.simplemobiletools.calendar.pro.helpers import androidx.room.TypeConverter import com.google.gson.Gson import com.google.gson.reflect.TypeToken +import com.simplemobiletools.calendar.pro.models.Attendee class Converters { private val gson = Gson() private val stringType = object : TypeToken>() {}.type + private val attendeeType = object : TypeToken>() {}.type @TypeConverter fun jsonToStringList(value: String): List { @@ -25,4 +27,16 @@ class Converters { @TypeConverter fun stringListToJson(list: List) = gson.toJson(list) + + @TypeConverter + fun attendeeListToJson(list: List) = gson.toJson(list) + + @TypeConverter + fun jsonToAttendeeList(value: String): List { + return try { + gson.fromJson>(value, attendeeType) ?: ArrayList() + } catch (e: Exception) { + emptyList() + } + } } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/IcsImporter.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/IcsImporter.kt index fedc6950c..e119cf0e0 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/IcsImporter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/IcsImporter.kt @@ -249,7 +249,7 @@ class IcsImporter(val activity: SimpleActivity) { curRepeatRule, curRepeatLimit, curRepeatExceptions, - "", + emptyList(), curImportId, DateTimeZone.getDefault().id, curFlags, diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Attendee.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Attendee.kt index 0309fd313..b74d147c5 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Attendee.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Attendee.kt @@ -2,14 +2,25 @@ package com.simplemobiletools.calendar.pro.models import android.content.Context import android.graphics.drawable.Drawable +import android.os.Parcelable import android.provider.CalendarContract import android.widget.ImageView import com.bumptech.glide.Glide import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.request.RequestOptions +import kotlinx.parcelize.Parcelize -data class Attendee(val contactId: Int, var name: String, val email: String, var status: Int, var photoUri: String, var isMe: Boolean, var relationship: Int) { +@Parcelize +data class Attendee( + val contactId: Int, + var name: String, + val email: String, + var status: Int, + var photoUri: String, + var isMe: Boolean, + var relationship: Int +) : Parcelable { fun getPublicName() = name.ifEmpty { email } fun updateImage(context: Context, imageView: ImageView, placeholder: Drawable) { @@ -17,21 +28,21 @@ data class Attendee(val contactId: Int, var name: String, val email: String, var imageView.setImageDrawable(placeholder) } else { val options = RequestOptions() - .diskCacheStrategy(DiskCacheStrategy.RESOURCE) - .error(placeholder) - .centerCrop() + .diskCacheStrategy(DiskCacheStrategy.RESOURCE) + .error(placeholder) + .centerCrop() Glide.with(context) - .load(photoUri) - .transition(DrawableTransitionOptions.withCrossFade()) - .placeholder(placeholder) - .apply(options) - .apply(RequestOptions.circleCropTransform()) - .into(imageView) + .load(photoUri) + .transition(DrawableTransitionOptions.withCrossFade()) + .placeholder(placeholder) + .apply(options) + .apply(RequestOptions.circleCropTransform()) + .into(imageView) } } fun showStatusImage() = status == CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED || - status == CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED || - status == CalendarContract.Attendees.ATTENDEE_STATUS_TENTATIVE + status == CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED || + status == CalendarContract.Attendees.ATTENDEE_STATUS_TENTATIVE } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Event.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Event.kt index c9d225697..28c896287 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Event.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Event.kt @@ -30,7 +30,7 @@ data class Event( @ColumnInfo(name = "repeat_rule") var repeatRule: Int = 0, @ColumnInfo(name = "repeat_limit") var repeatLimit: Long = 0L, @ColumnInfo(name = "repetition_exceptions") var repetitionExceptions: List = emptyList(), - @ColumnInfo(name = "attendees") var attendees: String = "", + @ColumnInfo(name = "attendees") var attendees: List = emptyList(), @ColumnInfo(name = "import_id") var importId: String = "", @ColumnInfo(name = "time_zone") var timeZone: String = "", @ColumnInfo(name = "flags") var flags: Int = 0, diff --git a/build.gradle.kts b/build.gradle.kts index 287277090..757129902 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,6 +2,7 @@ plugins { alias(libs.plugins.android).apply(false) alias(libs.plugins.kotlinAndroid).apply(false) alias(libs.plugins.ksp).apply(false) + alias(libs.plugins.parcelize).apply(false) } tasks.register("clean") { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0687192fc..855acea1d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -45,3 +45,5 @@ room = [ android = { id = "com.android.application", version.ref = "gradlePlugins-agp" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } + From c779aabfae4e44b3127980758d75b2acc4464e72 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 27 Sep 2023 23:22:42 +0530 Subject: [PATCH 3/6] Only allow attendee status modification by owner ACCOUNT_NAME is different from OWNER_ACCOUNT. --- .../calendar/pro/activities/EventActivity.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/EventActivity.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/EventActivity.kt index 3fff581c0..bc6f9cfb2 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/EventActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/EventActivity.kt @@ -1637,7 +1637,7 @@ class EventActivity : SimpleActivity() { private fun updateAttendees() { val currentCalendar = calDAVHelper.getCalDAVCalendars("", true).firstOrNull { it.id == mEventCalendarId } mAttendees.forEach { - it.isMe = it.email == currentCalendar?.accountName + it.isMe = it.email == currentCalendar?.ownerName } mAttendees.sortWith(compareBy @@ -1827,8 +1827,8 @@ class EventActivity : SimpleActivity() { if (mEvent.id == null && isSavingEvent && attendees.isNotEmpty()) { val currentCalendar = calDAVHelper.getCalDAVCalendars("", true).firstOrNull { it.id == mEventCalendarId } - mAvailableContacts.firstOrNull { it.email == currentCalendar?.accountName }?.apply { - attendees = attendees.filter { it.email != currentCalendar?.accountName }.toMutableList() as ArrayList + mAvailableContacts.firstOrNull { it.email == currentCalendar?.ownerName }?.apply { + attendees = attendees.filter { it.email != currentCalendar?.ownerName }.toMutableList() as ArrayList status = Attendees.ATTENDEE_STATUS_ACCEPTED relationship = Attendees.RELATIONSHIP_ORGANIZER attendees.add(this) From 2929dd147ca38fa2bedd32fb23aa76ed9a047f09 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 27 Sep 2023 23:25:08 +0530 Subject: [PATCH 4/6] Update Attendee.isMe when synchronising --- .../calendar/pro/helpers/CalDAVHelper.kt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/CalDAVHelper.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/CalDAVHelper.kt index f0f577e39..b5e3a2e87 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/CalDAVHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/CalDAVHelper.kt @@ -44,7 +44,7 @@ class CalDAVHelper(val context: Context) { } } - fetchCalDAVCalendarEvents(calendar.id, localEventType.id!!, showToasts) + fetchCalDAVCalendarEvents(calendar, localEventType.id!!, showToasts) } if (scheduleNextSync) { @@ -149,7 +149,9 @@ class CalDAVHelper(val context: Context) { } @SuppressLint("MissingPermission") - private fun fetchCalDAVCalendarEvents(calendarId: Int, eventTypeId: Long, showToasts: Boolean) { + private fun fetchCalDAVCalendarEvents(calendar: CalDAVCalendar, eventTypeId: Long, showToasts: Boolean) { + val calendarId = calendar.id + val importIdsMap = HashMap() val fetchedEventIds = ArrayList() @@ -211,7 +213,7 @@ class CalDAVHelper(val context: Context) { val originalId = cursor.getStringValue(Events.ORIGINAL_ID) val originalInstanceTime = cursor.getLongValue(Events.ORIGINAL_INSTANCE_TIME) val reminders = getCalDAVEventReminders(id) - val attendees = getCalDAVEventAttendees(id) + val attendees = getCalDAVEventAttendees(id, calendar) val availability = cursor.getIntValue(Events.AVAILABILITY) val status = cursor.getIntValue(Events.STATUS) val color = cursor.getIntValueOrNull(Events.EVENT_COLOR) @@ -570,7 +572,7 @@ class CalDAVHelper(val context: Context) { return reminders.sortedBy { it.minutes } } - private fun getCalDAVEventAttendees(eventId: Long): List { + private fun getCalDAVEventAttendees(eventId: Long, calendar: CalDAVCalendar): List { val attendees = ArrayList() val uri = Attendees.CONTENT_URI val projection = arrayOf( @@ -585,7 +587,7 @@ class CalDAVHelper(val context: Context) { val email = cursor.getStringValue(Attendees.ATTENDEE_EMAIL) ?: "" val status = cursor.getIntValue(Attendees.ATTENDEE_STATUS) val relationship = cursor.getIntValue(Attendees.ATTENDEE_RELATIONSHIP) - val attendee = Attendee(0, name, email, status, "", false, relationship) + val attendee = Attendee(0, name, email, status, "", email == calendar.ownerName, relationship) attendees.add(attendee) } From 9f8d59f0d4c19fd0daccad1e96bde2129932de04 Mon Sep 17 00:00:00 2001 From: Naveen Date: Thu, 28 Sep 2023 20:58:20 +0530 Subject: [PATCH 5/6] Strikethrough events when status is set to "Not going" --- .../activities/WidgetListConfigureActivity.kt | 100 ++++++------------ .../calendar/pro/adapters/DayEventsAdapter.kt | 2 +- .../calendar/pro/adapters/EventListAdapter.kt | 2 +- .../pro/adapters/EventListWidgetAdapter.kt | 32 +++--- .../calendar/pro/extensions/Context.kt | 5 +- .../calendar/pro/extensions/Event.kt | 2 + .../calendar/pro/extensions/ListEvent.kt | 5 + .../calendar/pro/extensions/MonthViewEvent.kt | 5 + .../calendar/pro/fragments/WeekFragment.kt | 4 +- .../pro/helpers/MyWidgetMonthlyProvider.kt | 7 +- .../calendar/pro/models/Event.kt | 5 + .../calendar/pro/models/ListEvent.kt | 36 ++++++- .../calendar/pro/models/MonthViewEvent.kt | 3 +- .../calendar/pro/views/MonthView.kt | 17 ++- 14 files changed, 125 insertions(+), 100 deletions(-) create mode 100644 app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/ListEvent.kt create mode 100644 app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/MonthViewEvent.kt diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/WidgetListConfigureActivity.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/WidgetListConfigureActivity.kt index e15266f88..f5bcd57b1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/WidgetListConfigureActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/activities/WidgetListConfigureActivity.kt @@ -232,36 +232,24 @@ class WidgetListConfigureActivity : SimpleActivity() { var time = dateTime.withHourOfDay(7) listItems.add( - ListEvent( - 1, - time.seconds(), - time.plusMinutes(30).seconds(), - getString(R.string.sample_title_1), - getString(R.string.sample_description_1), - false, - getProperPrimaryColor(), - "", - false, - false, - false, - false + ListEvent.empty.copy( + id = 1, + startTS = time.seconds(), + endTS = time.plusMinutes(30).seconds(), + title = getString(R.string.sample_title_1), + description = getString(R.string.sample_description_1), + color = getProperPrimaryColor(), ) ) time = dateTime.withHourOfDay(8) listItems.add( - ListEvent( - 2, - time.seconds(), - time.plusHours(1).seconds(), - getString(R.string.sample_title_2), - getString(R.string.sample_description_2), - false, - getProperPrimaryColor(), - "", - false, - false, - false, - false + ListEvent.empty.copy( + id = 2, + startTS = time.seconds(), + endTS = time.plusHours(1).seconds(), + title = getString(R.string.sample_title_2), + description = getString(R.string.sample_description_2), + color = getProperPrimaryColor(), ) ) @@ -272,53 +260,35 @@ class WidgetListConfigureActivity : SimpleActivity() { time = dateTime.withHourOfDay(8) listItems.add( - ListEvent( - 3, - time.seconds(), - time.plusHours(1).seconds(), - getString(R.string.sample_title_3), - "", - false, - getProperPrimaryColor(), - "", - false, - false, - false, - false + ListEvent.empty.copy( + id = 3, + startTS = time.seconds(), + endTS = time.plusHours(1).seconds(), + title = getString(R.string.sample_title_3), + description = "", + color = getProperPrimaryColor(), ) ) time = dateTime.withHourOfDay(13) listItems.add( - ListEvent( - 4, - time.seconds(), - time.plusHours(1).seconds(), - getString(R.string.sample_title_4), - getString(R.string.sample_description_4), - false, - getProperPrimaryColor(), - "", - false, - false, - false, - false + ListEvent.empty.copy( + id = 4, + startTS = time.seconds(), + endTS = time.plusHours(1).seconds(), + title = getString(R.string.sample_title_4), + description = getString(R.string.sample_description_4), + color = getProperPrimaryColor(), ) ) time = dateTime.withHourOfDay(18) listItems.add( - ListEvent( - 5, - time.seconds(), - time.plusMinutes(10).seconds(), - getString(R.string.sample_title_5), - "", - false, - getProperPrimaryColor(), - "", - false, - false, - false, - false + ListEvent.empty.copy( + id = 5, + startTS = time.seconds(), + endTS = time.plusMinutes(10).seconds(), + title = getString(R.string.sample_title_5), + description = "", + color = getProperPrimaryColor(), ) ) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/adapters/DayEventsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/adapters/DayEventsAdapter.kt index b94af644e..a9ce96abf 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/adapters/DayEventsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/adapters/DayEventsAdapter.kt @@ -90,7 +90,7 @@ class DayEventsAdapter(activity: SimpleActivity, val events: ArrayList, r eventItemHolder.isSelected = selectedKeys.contains(event.id?.toInt()) eventItemHolder.background.applyColorFilter(textColor) eventItemTitle.text = event.title - eventItemTitle.checkViewStrikeThrough(event.isTaskCompleted()) + eventItemTitle.checkViewStrikeThrough(event.shouldStrikeThrough()) eventItemTime.text = if (event.getIsAllDay()) allDayString else Formatter.getTimeFromTS(activity, event.startTS) if (event.startTS != event.endTS) { val startDayCode = Formatter.getDayCodeFromTS(event.startTS) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/adapters/EventListAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/adapters/EventListAdapter.kt index 33b541a5c..e29ef3301 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/adapters/EventListAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/adapters/EventListAdapter.kt @@ -136,7 +136,7 @@ class EventListAdapter( eventItemHolder.isSelected = selectedKeys.contains(listEvent.hashCode()) eventItemHolder.background.applyColorFilter(textColor) eventItemTitle.text = listEvent.title - eventItemTitle.checkViewStrikeThrough(listEvent.isTaskCompleted) + eventItemTitle.checkViewStrikeThrough(listEvent.shouldStrikeThrough()) eventItemTime.text = if (listEvent.isAllDay) allDayString else Formatter.getTimeFromTS(activity, listEvent.startTS) if (listEvent.startTS != listEvent.endTS) { if (!listEvent.isAllDay) { diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/adapters/EventListWidgetAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/adapters/EventListWidgetAdapter.kt index d643f3788..daa4a6bc1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/adapters/EventListWidgetAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/adapters/EventListWidgetAdapter.kt @@ -6,10 +6,7 @@ import android.graphics.Paint import android.widget.RemoteViews import android.widget.RemoteViewsService import com.simplemobiletools.calendar.pro.R -import com.simplemobiletools.calendar.pro.extensions.config -import com.simplemobiletools.calendar.pro.extensions.eventsHelper -import com.simplemobiletools.calendar.pro.extensions.getWidgetFontSize -import com.simplemobiletools.calendar.pro.extensions.seconds +import com.simplemobiletools.calendar.pro.extensions.* import com.simplemobiletools.calendar.pro.helpers.* import com.simplemobiletools.calendar.pro.models.* import com.simplemobiletools.commons.extensions.* @@ -120,7 +117,7 @@ class EventListWidgetAdapter(val context: Context, val intent: Intent) : RemoteV setViewPadding(R.id.event_item_title, normalMargin, 0, smallMargin, 0) } - if (item.isTaskCompleted) { + if (item.shouldStrikeThrough()) { setInt(R.id.event_item_title, "setPaintFlags", Paint.ANTI_ALIAS_FLAG or Paint.STRIKE_THRU_TEXT_FLAG) } else { setInt(R.id.event_item_title, "setPaintFlags", Paint.ANTI_ALIAS_FLAG) @@ -226,18 +223,19 @@ class EventListWidgetAdapter(val context: Context, val intent: Intent) : RemoteV } val listEvent = ListEvent( - event.id!!, - event.startTS, - event.endTS, - event.title, - event.description, - event.getIsAllDay(), - event.color, - event.location, - event.isPastEvent, - event.repeatInterval > 0, - event.isTask(), - event.isTaskCompleted() + id = event.id!!, + startTS = event.startTS, + endTS = event.endTS, + title = event.title, + description = event.description, + isAllDay = event.getIsAllDay(), + color = event.color, + location = event.location, + isPastEvent = event.isPastEvent, + isRepeatable = event.repeatInterval > 0, + isTask = event.isTask(), + isTaskCompleted = event.isTaskCompleted(), + isAttendeeInviteDeclined = event.isAttendeeInviteDeclined() ) listItems.add(listEvent) } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/Context.kt index ad40259a6..1b69ca2ca 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/Context.kt @@ -601,7 +601,7 @@ fun Context.addDayEvents(day: DayMonthly, linearLayout: LinearLayout, res: Resou dayMonthlyEventId.apply { setTextColor(textColor) text = it.title.replace(" ", "\u00A0") // allow word break by char - checkViewStrikeThrough(it.isTaskCompleted()) + checkViewStrikeThrough(it.shouldStrikeThrough()) contentDescription = it.title } @@ -669,7 +669,8 @@ fun Context.getEventListItems(events: List, addSectionDays: Boolean = tru it.isPastEvent, it.repeatInterval > 0, it.isTask(), - it.isTaskCompleted() + it.isTaskCompleted(), + it.isAttendeeInviteDeclined() ) listItems.add(listEvent) } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/Event.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/Event.kt index de9908b4c..c31d4f872 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/Event.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/Event.kt @@ -40,3 +40,5 @@ fun Event.maybeAdjustRepeatLimitCount(original: Event, occurrenceTS: Long) { this.repeatLimit = newRepeatLimit } } + +fun Event.shouldStrikeThrough() = isTaskCompleted() || isAttendeeInviteDeclined() diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/ListEvent.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/ListEvent.kt new file mode 100644 index 000000000..406929d18 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/ListEvent.kt @@ -0,0 +1,5 @@ +package com.simplemobiletools.calendar.pro.extensions + +import com.simplemobiletools.calendar.pro.models.ListEvent + +fun ListEvent.shouldStrikeThrough() = isTaskCompleted || isAttendeeInviteDeclined diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/MonthViewEvent.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/MonthViewEvent.kt new file mode 100644 index 000000000..440cd66aa --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/extensions/MonthViewEvent.kt @@ -0,0 +1,5 @@ +package com.simplemobiletools.calendar.pro.extensions + +import com.simplemobiletools.calendar.pro.models.MonthViewEvent + +fun MonthViewEvent.shouldStrikeThrough() = isTaskCompleted || isAttendeeInviteDeclined diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/fragments/WeekFragment.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/fragments/WeekFragment.kt index 9901b212f..691a19798 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/fragments/WeekFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/fragments/WeekFragment.kt @@ -645,7 +645,7 @@ class WeekFragment : Fragment(), WeeklyCalendar { } text = event.title - checkViewStrikeThrough(event.isTaskCompleted()) + checkViewStrikeThrough(event.shouldStrikeThrough()) contentDescription = text minHeight = if (event.startTS == event.endTS) { @@ -785,7 +785,7 @@ class WeekFragment : Fragment(), WeeklyCalendar { setTextColor(textColor) maxLines = if (event.isTask()) 1 else 2 text = event.title - checkViewStrikeThrough(event.isTaskCompleted()) + checkViewStrikeThrough(event.shouldStrikeThrough()) contentDescription = text } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/MyWidgetMonthlyProvider.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/MyWidgetMonthlyProvider.kt index b4bca7ec9..fb74792e5 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/MyWidgetMonthlyProvider.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/MyWidgetMonthlyProvider.kt @@ -12,10 +12,7 @@ import android.view.View import android.widget.RemoteViews import com.simplemobiletools.calendar.pro.R import com.simplemobiletools.calendar.pro.activities.SplashActivity -import com.simplemobiletools.calendar.pro.extensions.config -import com.simplemobiletools.calendar.pro.extensions.getWidgetFontSize -import com.simplemobiletools.calendar.pro.extensions.isWeekendIndex -import com.simplemobiletools.calendar.pro.extensions.launchNewEventOrTaskActivity +import com.simplemobiletools.calendar.pro.extensions.* import com.simplemobiletools.calendar.pro.interfaces.MonthlyCalendar import com.simplemobiletools.calendar.pro.models.DayMonthly import com.simplemobiletools.calendar.pro.models.Event @@ -155,7 +152,7 @@ class MyWidgetMonthlyProvider : AppWidgetProvider() { applyColorFilter(R.id.day_monthly_task_image, eventTextColor) setInt(R.id.day_monthly_event_background, "setColorFilter", it.color) - if (it.isTaskCompleted()) { + if (it.shouldStrikeThrough()) { setInt(R.id.day_monthly_event_id, "setPaintFlags", Paint.ANTI_ALIAS_FLAG or Paint.STRIKE_THRU_TEXT_FLAG) } else { setInt(R.id.day_monthly_event_id, "setPaintFlags", Paint.ANTI_ALIAS_FLAG) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Event.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Event.kt index 28c896287..315ed828b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Event.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/Event.kt @@ -1,5 +1,6 @@ package com.simplemobiletools.calendar.pro.models +import android.provider.CalendarContract.Attendees import androidx.collection.LongSparseArray import androidx.room.ColumnInfo import androidx.room.Entity @@ -209,4 +210,8 @@ data class Event( DateTimeZone.getDefault().id } } + + fun isAttendeeInviteDeclined() = attendees.any { + it.isMe && it.status == Attendees.ATTENDEE_STATUS_DECLINED + } } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/ListEvent.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/ListEvent.kt index 512178635..def5ce0ce 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/ListEvent.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/ListEvent.kt @@ -1,6 +1,36 @@ package com.simplemobiletools.calendar.pro.models data class ListEvent( - var id: Long, var startTS: Long, var endTS: Long, var title: String, var description: String, var isAllDay: Boolean, var color: Int, - var location: String, var isPastEvent: Boolean, var isRepeatable: Boolean, var isTask: Boolean, var isTaskCompleted: Boolean -) : ListItem() + var id: Long, + var startTS: Long, + var endTS: Long, + var title: String, + var description: String, + var isAllDay: Boolean, + var color: Int, + var location: String, + var isPastEvent: Boolean, + var isRepeatable: Boolean, + var isTask: Boolean, + var isTaskCompleted: Boolean, + var isAttendeeInviteDeclined: Boolean +) : ListItem() { + + companion object { + val empty = ListEvent( + id = 0, + startTS = 0, + endTS = 0, + title = "", + description = "", + isAllDay = false, + color = 0, + location = "", + isPastEvent = false, + isRepeatable = false, + isTask = false, + isTaskCompleted = false, + isAttendeeInviteDeclined = false + ) + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/MonthViewEvent.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/MonthViewEvent.kt index 5fa8b9ded..1caa8a4cc 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/MonthViewEvent.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/models/MonthViewEvent.kt @@ -12,5 +12,6 @@ data class MonthViewEvent( val isAllDay: Boolean, val isPastEvent: Boolean, val isTask: Boolean, - val isTaskCompleted: Boolean + val isTaskCompleted: Boolean, + val isAttendeeInviteDeclined: Boolean, ) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/views/MonthView.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/views/MonthView.kt index 6ae6180f4..3c9432024 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/views/MonthView.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/views/MonthView.kt @@ -130,8 +130,19 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con val daysCnt = getEventLastingDaysCount(event) val monthViewEvent = MonthViewEvent( - event.id!!, event.title, event.startTS, event.endTS, event.color, dayIndexOnMonthView, - daysCnt, dayIndexOnMonthView, event.getIsAllDay(), event.isPastEvent, event.isTask(), event.isTaskCompleted() + id = event.id!!, + title = event.title, + startTS = event.startTS, + endTS = event.endTS, + color = event.color, + startDayIndex = dayIndexOnMonthView, + daysCnt = daysCnt, + originalStartDayIndex = dayIndexOnMonthView, + isAllDay = event.getIsAllDay(), + isPastEvent = event.isPastEvent, + isTask = event.isTask(), + isTaskCompleted = event.isTaskCompleted(), + isAttendeeInviteDeclined = event.isAttendeeInviteDeclined() ) allEvents.add(monthViewEvent) } @@ -370,7 +381,7 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con val curPaint = Paint(eventTitlePaint) curPaint.color = paintColor - curPaint.isStrikeThruText = event.isTaskCompleted + curPaint.isStrikeThruText = event.shouldStrikeThrough() return curPaint } From 106552036eeb7ebbc788b0286b3312b89a91f905 Mon Sep 17 00:00:00 2001 From: Naveen Date: Thu, 28 Sep 2023 23:32:56 +0530 Subject: [PATCH 6/6] Return empty list on empty value --- .../simplemobiletools/calendar/pro/helpers/Converters.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/Converters.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/Converters.kt index 106dd0a42..9be7e0eb7 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/Converters.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/pro/helpers/Converters.kt @@ -29,10 +29,14 @@ class Converters { fun stringListToJson(list: List) = gson.toJson(list) @TypeConverter - fun attendeeListToJson(list: List) = gson.toJson(list) + fun attendeeListToJson(list: List): String = gson.toJson(list) @TypeConverter fun jsonToAttendeeList(value: String): List { + if (value.isEmpty()) { + return emptyList() + } + return try { gson.fromJson>(value, attendeeType) ?: ArrayList() } catch (e: Exception) {