Merge pull request #2215 from naveensingh/attendee_improvements

Attendee related improvements
This commit is contained in:
Tibor Kaputa
2023-09-28 21:38:36 +02:00
committed by GitHub
22 changed files with 190 additions and 137 deletions

View File

@@ -6,6 +6,7 @@ plugins {
alias(libs.plugins.android) alias(libs.plugins.android)
alias(libs.plugins.kotlinAndroid) alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.ksp) alias(libs.plugins.ksp)
alias(libs.plugins.parcelize)
base base
} }

View File

@@ -24,8 +24,6 @@ import android.widget.RelativeLayout
import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.MaterialTimePicker
import com.google.android.material.timepicker.MaterialTimePicker.INPUT_MODE_CLOCK import com.google.android.material.timepicker.MaterialTimePicker.INPUT_MODE_CLOCK
import com.google.android.material.timepicker.TimeFormat 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.R
import com.simplemobiletools.calendar.pro.adapters.AutoCompleteTextViewAdapter import com.simplemobiletools.calendar.pro.adapters.AutoCompleteTextViewAdapter
import com.simplemobiletools.calendar.pro.databinding.ActivityEventBinding import com.simplemobiletools.calendar.pro.databinding.ActivityEventBinding
@@ -171,7 +169,7 @@ class EventActivity : SimpleActivity() {
putInt(REPEAT_RULE, mRepeatRule) putInt(REPEAT_RULE, mRepeatRule)
putLong(REPEAT_LIMIT, mRepeatLimit) putLong(REPEAT_LIMIT, mRepeatLimit)
putString(ATTENDEES, getAllAttendees(false)) putParcelableArrayList(ATTENDEES, getAllAttendees(false))
putInt(AVAILABILITY, mAvailability) putInt(AVAILABILITY, mAvailability)
putInt(EVENT_COLOR, mEventColor) putInt(EVENT_COLOR, mEventColor)
@@ -213,8 +211,7 @@ class EventActivity : SimpleActivity() {
mRepeatRule = getInt(REPEAT_RULE) mRepeatRule = getInt(REPEAT_RULE)
mRepeatLimit = getLong(REPEAT_LIMIT) mRepeatLimit = getLong(REPEAT_LIMIT)
val token = object : TypeToken<List<Attendee>>() {}.type mAttendees = getParcelableArrayList(ATTENDEES) ?: arrayListOf()
mAttendees = Gson().fromJson<ArrayList<Attendee>>(getString(ATTENDEES), token) ?: ArrayList()
mEventTypeId = getLong(EVENT_TYPE_ID) mEventTypeId = getLong(EVENT_TYPE_ID)
mEventCalendarId = getInt(EVENT_CALENDAR_ID) mEventCalendarId = getInt(EVENT_CALENDAR_ID)
@@ -507,8 +504,7 @@ class EventActivity : SimpleActivity() {
mAvailability = mEvent.availability mAvailability = mEvent.availability
mEventColor = mEvent.color mEventColor = mEvent.color
val token = object : TypeToken<List<Attendee>>() {}.type mAttendees = mEvent.attendees.toMutableList() as ArrayList<Attendee>
mAttendees = Gson().fromJson<ArrayList<Attendee>>(mEvent.attendees, token) ?: ArrayList()
checkRepeatTexts(mRepeatInterval) checkRepeatTexts(mRepeatInterval)
checkAttendees() checkAttendees()
@@ -1310,7 +1306,7 @@ class EventActivity : SimpleActivity() {
flags = mEvent.flags.addBitIf(binding.eventAllDay.isChecked, FLAG_ALL_DAY) flags = mEvent.flags.addBitIf(binding.eventAllDay.isChecked, FLAG_ALL_DAY)
repeatLimit = if (repeatInterval == 0) 0 else mRepeatLimit repeatLimit = if (repeatInterval == 0) 0 else mRepeatLimit
repeatRule = mRepeatRule repeatRule = mRepeatRule
attendees = if (mEventCalendarId == STORED_LOCALLY_ONLY) "" else getAllAttendees(true) attendees = if (mEventCalendarId == STORED_LOCALLY_ONLY) emptyList() else getAllAttendees(true)
eventType = newEventType eventType = newEventType
lastUpdated = System.currentTimeMillis() lastUpdated = System.currentTimeMillis()
source = newSource source = newSource
@@ -1641,7 +1637,7 @@ class EventActivity : SimpleActivity() {
private fun updateAttendees() { private fun updateAttendees() {
val currentCalendar = calDAVHelper.getCalDAVCalendars("", true).firstOrNull { it.id == mEventCalendarId } val currentCalendar = calDAVHelper.getCalDAVCalendars("", true).firstOrNull { it.id == mEventCalendarId }
mAttendees.forEach { mAttendees.forEach {
it.isMe = it.email == currentCalendar?.accountName it.isMe = it.email == currentCalendar?.ownerName
} }
mAttendees.sortWith(compareBy<Attendee> mAttendees.sortWith(compareBy<Attendee>
@@ -1729,7 +1725,7 @@ class EventActivity : SimpleActivity() {
autoCompleteView.focusSearch(View.FOCUS_DOWN)?.requestFocus() autoCompleteView.focusSearch(View.FOCUS_DOWN)?.requestFocus()
attendeeHolder.apply { attendeeHolder.apply {
root.beVisible() eventContactAttendee.beVisible()
val attendeeStatusBackground = resources.getDrawable(R.drawable.attendee_status_circular_background) val attendeeStatusBackground = resources.getDrawable(R.drawable.attendee_status_circular_background)
(attendeeStatusBackground as LayerDrawable).findDrawableByLayerId(R.id.attendee_status_circular_background) (attendeeStatusBackground as LayerDrawable).findDrawableByLayerId(R.id.attendee_status_circular_background)
@@ -1817,7 +1813,7 @@ class EventActivity : SimpleActivity() {
} }
} }
private fun getAllAttendees(isSavingEvent: Boolean): String { private fun getAllAttendees(isSavingEvent: Boolean): ArrayList<Attendee> {
var attendees = ArrayList<Attendee>() var attendees = ArrayList<Attendee>()
mSelectedContacts.forEach { mSelectedContacts.forEach {
attendees.add(it) attendees.add(it)
@@ -1831,15 +1827,15 @@ class EventActivity : SimpleActivity() {
if (mEvent.id == null && isSavingEvent && attendees.isNotEmpty()) { if (mEvent.id == null && isSavingEvent && attendees.isNotEmpty()) {
val currentCalendar = calDAVHelper.getCalDAVCalendars("", true).firstOrNull { it.id == mEventCalendarId } val currentCalendar = calDAVHelper.getCalDAVCalendars("", true).firstOrNull { it.id == mEventCalendarId }
mAvailableContacts.firstOrNull { it.email == currentCalendar?.accountName }?.apply { mAvailableContacts.firstOrNull { it.email == currentCalendar?.ownerName }?.apply {
attendees = attendees.filter { it.email != currentCalendar?.accountName }.toMutableList() as ArrayList<Attendee> attendees = attendees.filter { it.email != currentCalendar?.ownerName }.toMutableList() as ArrayList<Attendee>
status = Attendees.ATTENDEE_STATUS_ACCEPTED status = Attendees.ATTENDEE_STATUS_ACCEPTED
relationship = Attendees.RELATIONSHIP_ORGANIZER relationship = Attendees.RELATIONSHIP_ORGANIZER
attendees.add(this) attendees.add(this)
} }
} }
return Gson().toJson(attendees) return attendees
} }
private fun getNames(): List<Attendee> { private fun getNames(): List<Attendee> {

View File

@@ -232,36 +232,24 @@ class WidgetListConfigureActivity : SimpleActivity() {
var time = dateTime.withHourOfDay(7) var time = dateTime.withHourOfDay(7)
listItems.add( listItems.add(
ListEvent( ListEvent.empty.copy(
1, id = 1,
time.seconds(), startTS = time.seconds(),
time.plusMinutes(30).seconds(), endTS = time.plusMinutes(30).seconds(),
getString(R.string.sample_title_1), title = getString(R.string.sample_title_1),
getString(R.string.sample_description_1), description = getString(R.string.sample_description_1),
false, color = getProperPrimaryColor(),
getProperPrimaryColor(),
"",
false,
false,
false,
false
) )
) )
time = dateTime.withHourOfDay(8) time = dateTime.withHourOfDay(8)
listItems.add( listItems.add(
ListEvent( ListEvent.empty.copy(
2, id = 2,
time.seconds(), startTS = time.seconds(),
time.plusHours(1).seconds(), endTS = time.plusHours(1).seconds(),
getString(R.string.sample_title_2), title = getString(R.string.sample_title_2),
getString(R.string.sample_description_2), description = getString(R.string.sample_description_2),
false, color = getProperPrimaryColor(),
getProperPrimaryColor(),
"",
false,
false,
false,
false
) )
) )
@@ -272,53 +260,35 @@ class WidgetListConfigureActivity : SimpleActivity() {
time = dateTime.withHourOfDay(8) time = dateTime.withHourOfDay(8)
listItems.add( listItems.add(
ListEvent( ListEvent.empty.copy(
3, id = 3,
time.seconds(), startTS = time.seconds(),
time.plusHours(1).seconds(), endTS = time.plusHours(1).seconds(),
getString(R.string.sample_title_3), title = getString(R.string.sample_title_3),
"", description = "",
false, color = getProperPrimaryColor(),
getProperPrimaryColor(),
"",
false,
false,
false,
false
) )
) )
time = dateTime.withHourOfDay(13) time = dateTime.withHourOfDay(13)
listItems.add( listItems.add(
ListEvent( ListEvent.empty.copy(
4, id = 4,
time.seconds(), startTS = time.seconds(),
time.plusHours(1).seconds(), endTS = time.plusHours(1).seconds(),
getString(R.string.sample_title_4), title = getString(R.string.sample_title_4),
getString(R.string.sample_description_4), description = getString(R.string.sample_description_4),
false, color = getProperPrimaryColor(),
getProperPrimaryColor(),
"",
false,
false,
false,
false
) )
) )
time = dateTime.withHourOfDay(18) time = dateTime.withHourOfDay(18)
listItems.add( listItems.add(
ListEvent( ListEvent.empty.copy(
5, id = 5,
time.seconds(), startTS = time.seconds(),
time.plusMinutes(10).seconds(), endTS = time.plusMinutes(10).seconds(),
getString(R.string.sample_title_5), title = getString(R.string.sample_title_5),
"", description = "",
false, color = getProperPrimaryColor(),
getProperPrimaryColor(),
"",
false,
false,
false,
false
) )
) )

View File

@@ -90,7 +90,7 @@ class DayEventsAdapter(activity: SimpleActivity, val events: ArrayList<Event>, r
eventItemHolder.isSelected = selectedKeys.contains(event.id?.toInt()) eventItemHolder.isSelected = selectedKeys.contains(event.id?.toInt())
eventItemHolder.background.applyColorFilter(textColor) eventItemHolder.background.applyColorFilter(textColor)
eventItemTitle.text = event.title eventItemTitle.text = event.title
eventItemTitle.checkViewStrikeThrough(event.isTaskCompleted()) eventItemTitle.checkViewStrikeThrough(event.shouldStrikeThrough())
eventItemTime.text = if (event.getIsAllDay()) allDayString else Formatter.getTimeFromTS(activity, event.startTS) eventItemTime.text = if (event.getIsAllDay()) allDayString else Formatter.getTimeFromTS(activity, event.startTS)
if (event.startTS != event.endTS) { if (event.startTS != event.endTS) {
val startDayCode = Formatter.getDayCodeFromTS(event.startTS) val startDayCode = Formatter.getDayCodeFromTS(event.startTS)

View File

@@ -136,7 +136,7 @@ class EventListAdapter(
eventItemHolder.isSelected = selectedKeys.contains(listEvent.hashCode()) eventItemHolder.isSelected = selectedKeys.contains(listEvent.hashCode())
eventItemHolder.background.applyColorFilter(textColor) eventItemHolder.background.applyColorFilter(textColor)
eventItemTitle.text = listEvent.title eventItemTitle.text = listEvent.title
eventItemTitle.checkViewStrikeThrough(listEvent.isTaskCompleted) eventItemTitle.checkViewStrikeThrough(listEvent.shouldStrikeThrough())
eventItemTime.text = if (listEvent.isAllDay) allDayString else Formatter.getTimeFromTS(activity, listEvent.startTS) eventItemTime.text = if (listEvent.isAllDay) allDayString else Formatter.getTimeFromTS(activity, listEvent.startTS)
if (listEvent.startTS != listEvent.endTS) { if (listEvent.startTS != listEvent.endTS) {
if (!listEvent.isAllDay) { if (!listEvent.isAllDay) {

View File

@@ -6,10 +6,7 @@ import android.graphics.Paint
import android.widget.RemoteViews import android.widget.RemoteViews
import android.widget.RemoteViewsService import android.widget.RemoteViewsService
import com.simplemobiletools.calendar.pro.R import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.extensions.config import com.simplemobiletools.calendar.pro.extensions.*
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.helpers.* import com.simplemobiletools.calendar.pro.helpers.*
import com.simplemobiletools.calendar.pro.models.* import com.simplemobiletools.calendar.pro.models.*
import com.simplemobiletools.commons.extensions.* 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) 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) setInt(R.id.event_item_title, "setPaintFlags", Paint.ANTI_ALIAS_FLAG or Paint.STRIKE_THRU_TEXT_FLAG)
} else { } else {
setInt(R.id.event_item_title, "setPaintFlags", Paint.ANTI_ALIAS_FLAG) 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( val listEvent = ListEvent(
event.id!!, id = event.id!!,
event.startTS, startTS = event.startTS,
event.endTS, endTS = event.endTS,
event.title, title = event.title,
event.description, description = event.description,
event.getIsAllDay(), isAllDay = event.getIsAllDay(),
event.color, color = event.color,
event.location, location = event.location,
event.isPastEvent, isPastEvent = event.isPastEvent,
event.repeatInterval > 0, isRepeatable = event.repeatInterval > 0,
event.isTask(), isTask = event.isTask(),
event.isTaskCompleted() isTaskCompleted = event.isTaskCompleted(),
isAttendeeInviteDeclined = event.isAttendeeInviteDeclined()
) )
listItems.add(listEvent) listItems.add(listEvent)
} }

View File

@@ -601,7 +601,7 @@ fun Context.addDayEvents(day: DayMonthly, linearLayout: LinearLayout, res: Resou
dayMonthlyEventId.apply { dayMonthlyEventId.apply {
setTextColor(textColor) setTextColor(textColor)
text = it.title.replace(" ", "\u00A0") // allow word break by char text = it.title.replace(" ", "\u00A0") // allow word break by char
checkViewStrikeThrough(it.isTaskCompleted()) checkViewStrikeThrough(it.shouldStrikeThrough())
contentDescription = it.title contentDescription = it.title
} }
@@ -669,7 +669,8 @@ fun Context.getEventListItems(events: List<Event>, addSectionDays: Boolean = tru
it.isPastEvent, it.isPastEvent,
it.repeatInterval > 0, it.repeatInterval > 0,
it.isTask(), it.isTask(),
it.isTaskCompleted() it.isTaskCompleted(),
it.isAttendeeInviteDeclined()
) )
listItems.add(listEvent) listItems.add(listEvent)
} }

View File

@@ -40,3 +40,5 @@ fun Event.maybeAdjustRepeatLimitCount(original: Event, occurrenceTS: Long) {
this.repeatLimit = newRepeatLimit this.repeatLimit = newRepeatLimit
} }
} }
fun Event.shouldStrikeThrough() = isTaskCompleted() || isAttendeeInviteDeclined()

View File

@@ -0,0 +1,5 @@
package com.simplemobiletools.calendar.pro.extensions
import com.simplemobiletools.calendar.pro.models.ListEvent
fun ListEvent.shouldStrikeThrough() = isTaskCompleted || isAttendeeInviteDeclined

View File

@@ -0,0 +1,5 @@
package com.simplemobiletools.calendar.pro.extensions
import com.simplemobiletools.calendar.pro.models.MonthViewEvent
fun MonthViewEvent.shouldStrikeThrough() = isTaskCompleted || isAttendeeInviteDeclined

View File

@@ -645,7 +645,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
} }
text = event.title text = event.title
checkViewStrikeThrough(event.isTaskCompleted()) checkViewStrikeThrough(event.shouldStrikeThrough())
contentDescription = text contentDescription = text
minHeight = if (event.startTS == event.endTS) { minHeight = if (event.startTS == event.endTS) {
@@ -785,7 +785,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
setTextColor(textColor) setTextColor(textColor)
maxLines = if (event.isTask()) 1 else 2 maxLines = if (event.isTask()) 1 else 2
text = event.title text = event.title
checkViewStrikeThrough(event.isTaskCompleted()) checkViewStrikeThrough(event.shouldStrikeThrough())
contentDescription = text contentDescription = text
} }

View File

@@ -7,8 +7,6 @@ import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.provider.CalendarContract.* import android.provider.CalendarContract.*
import android.widget.Toast 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.R
import com.simplemobiletools.calendar.pro.extensions.* import com.simplemobiletools.calendar.pro.extensions.*
import com.simplemobiletools.calendar.pro.models.* import com.simplemobiletools.calendar.pro.models.*
@@ -46,7 +44,7 @@ class CalDAVHelper(val context: Context) {
} }
} }
fetchCalDAVCalendarEvents(calendar.id, localEventType.id!!, showToasts) fetchCalDAVCalendarEvents(calendar, localEventType.id!!, showToasts)
} }
if (scheduleNextSync) { if (scheduleNextSync) {
@@ -151,7 +149,9 @@ class CalDAVHelper(val context: Context) {
} }
@SuppressLint("MissingPermission") @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<String, Event>() val importIdsMap = HashMap<String, Event>()
val fetchedEventIds = ArrayList<String>() val fetchedEventIds = ArrayList<String>()
@@ -213,7 +213,7 @@ class CalDAVHelper(val context: Context) {
val originalId = cursor.getStringValue(Events.ORIGINAL_ID) val originalId = cursor.getStringValue(Events.ORIGINAL_ID)
val originalInstanceTime = cursor.getLongValue(Events.ORIGINAL_INSTANCE_TIME) val originalInstanceTime = cursor.getLongValue(Events.ORIGINAL_INSTANCE_TIME)
val reminders = getCalDAVEventReminders(id) val reminders = getCalDAVEventReminders(id)
val attendees = Gson().toJson(getCalDAVEventAttendees(id)) val attendees = getCalDAVEventAttendees(id, calendar)
val availability = cursor.getIntValue(Events.AVAILABILITY) val availability = cursor.getIntValue(Events.AVAILABILITY)
val status = cursor.getIntValue(Events.STATUS) val status = cursor.getIntValue(Events.STATUS)
val color = cursor.getIntValueOrNull(Events.EVENT_COLOR) val color = cursor.getIntValueOrNull(Events.EVENT_COLOR)
@@ -394,8 +394,7 @@ class CalDAVHelper(val context: Context) {
private fun setupCalDAVEventAttendees(event: Event) { private fun setupCalDAVEventAttendees(event: Event) {
clearEventAttendees(event) clearEventAttendees(event)
val attendees = Gson().fromJson<ArrayList<Attendee>>(event.attendees, object : TypeToken<List<Attendee>>() {}.type) ?: ArrayList() event.attendees.forEach {
attendees.forEach {
val contentValues = ContentValues().apply { val contentValues = ContentValues().apply {
put(Attendees.ATTENDEE_NAME, it.name) put(Attendees.ATTENDEE_NAME, it.name)
put(Attendees.ATTENDEE_EMAIL, it.email) put(Attendees.ATTENDEE_EMAIL, it.email)
@@ -573,7 +572,7 @@ class CalDAVHelper(val context: Context) {
return reminders.sortedBy { it.minutes } return reminders.sortedBy { it.minutes }
} }
private fun getCalDAVEventAttendees(eventId: Long): List<Attendee> { private fun getCalDAVEventAttendees(eventId: Long, calendar: CalDAVCalendar): List<Attendee> {
val attendees = ArrayList<Attendee>() val attendees = ArrayList<Attendee>()
val uri = Attendees.CONTENT_URI val uri = Attendees.CONTENT_URI
val projection = arrayOf( val projection = arrayOf(
@@ -588,7 +587,7 @@ class CalDAVHelper(val context: Context) {
val email = cursor.getStringValue(Attendees.ATTENDEE_EMAIL) ?: "" val email = cursor.getStringValue(Attendees.ATTENDEE_EMAIL) ?: ""
val status = cursor.getIntValue(Attendees.ATTENDEE_STATUS) val status = cursor.getIntValue(Attendees.ATTENDEE_STATUS)
val relationship = cursor.getIntValue(Attendees.ATTENDEE_RELATIONSHIP) 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) attendees.add(attendee)
} }

View File

@@ -3,10 +3,12 @@ package com.simplemobiletools.calendar.pro.helpers
import androidx.room.TypeConverter import androidx.room.TypeConverter
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import com.simplemobiletools.calendar.pro.models.Attendee
class Converters { class Converters {
private val gson = Gson() private val gson = Gson()
private val stringType = object : TypeToken<List<String>>() {}.type private val stringType = object : TypeToken<List<String>>() {}.type
private val attendeeType = object : TypeToken<List<Attendee>>() {}.type
@TypeConverter @TypeConverter
fun jsonToStringList(value: String): List<String> { fun jsonToStringList(value: String): List<String> {
@@ -25,4 +27,20 @@ class Converters {
@TypeConverter @TypeConverter
fun stringListToJson(list: List<String>) = gson.toJson(list) fun stringListToJson(list: List<String>) = gson.toJson(list)
@TypeConverter
fun attendeeListToJson(list: List<Attendee>): String = gson.toJson(list)
@TypeConverter
fun jsonToAttendeeList(value: String): List<Attendee> {
if (value.isEmpty()) {
return emptyList()
}
return try {
gson.fromJson<ArrayList<Attendee>>(value, attendeeType) ?: ArrayList()
} catch (e: Exception) {
emptyList()
}
}
} }

View File

@@ -249,7 +249,7 @@ class IcsImporter(val activity: SimpleActivity) {
curRepeatRule, curRepeatRule,
curRepeatLimit, curRepeatLimit,
curRepeatExceptions, curRepeatExceptions,
"", emptyList(),
curImportId, curImportId,
DateTimeZone.getDefault().id, DateTimeZone.getDefault().id,
curFlags, curFlags,

View File

@@ -12,10 +12,7 @@ import android.view.View
import android.widget.RemoteViews import android.widget.RemoteViews
import com.simplemobiletools.calendar.pro.R import com.simplemobiletools.calendar.pro.R
import com.simplemobiletools.calendar.pro.activities.SplashActivity import com.simplemobiletools.calendar.pro.activities.SplashActivity
import com.simplemobiletools.calendar.pro.extensions.config import com.simplemobiletools.calendar.pro.extensions.*
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.interfaces.MonthlyCalendar import com.simplemobiletools.calendar.pro.interfaces.MonthlyCalendar
import com.simplemobiletools.calendar.pro.models.DayMonthly import com.simplemobiletools.calendar.pro.models.DayMonthly
import com.simplemobiletools.calendar.pro.models.Event import com.simplemobiletools.calendar.pro.models.Event
@@ -155,7 +152,7 @@ class MyWidgetMonthlyProvider : AppWidgetProvider() {
applyColorFilter(R.id.day_monthly_task_image, eventTextColor) applyColorFilter(R.id.day_monthly_task_image, eventTextColor)
setInt(R.id.day_monthly_event_background, "setColorFilter", it.color) 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) setInt(R.id.day_monthly_event_id, "setPaintFlags", Paint.ANTI_ALIAS_FLAG or Paint.STRIKE_THRU_TEXT_FLAG)
} else { } else {
setInt(R.id.day_monthly_event_id, "setPaintFlags", Paint.ANTI_ALIAS_FLAG) setInt(R.id.day_monthly_event_id, "setPaintFlags", Paint.ANTI_ALIAS_FLAG)

View File

@@ -2,14 +2,25 @@ package com.simplemobiletools.calendar.pro.models
import android.content.Context import android.content.Context
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Parcelable
import android.provider.CalendarContract import android.provider.CalendarContract
import android.widget.ImageView import android.widget.ImageView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestOptions 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 getPublicName() = name.ifEmpty { email }
fun updateImage(context: Context, imageView: ImageView, placeholder: Drawable) { 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) imageView.setImageDrawable(placeholder)
} else { } else {
val options = RequestOptions() val options = RequestOptions()
.diskCacheStrategy(DiskCacheStrategy.RESOURCE) .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.error(placeholder) .error(placeholder)
.centerCrop() .centerCrop()
Glide.with(context) Glide.with(context)
.load(photoUri) .load(photoUri)
.transition(DrawableTransitionOptions.withCrossFade()) .transition(DrawableTransitionOptions.withCrossFade())
.placeholder(placeholder) .placeholder(placeholder)
.apply(options) .apply(options)
.apply(RequestOptions.circleCropTransform()) .apply(RequestOptions.circleCropTransform())
.into(imageView) .into(imageView)
} }
} }
fun showStatusImage() = status == CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED || fun showStatusImage() = status == CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED ||
status == CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED || status == CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED ||
status == CalendarContract.Attendees.ATTENDEE_STATUS_TENTATIVE status == CalendarContract.Attendees.ATTENDEE_STATUS_TENTATIVE
} }

View File

@@ -1,5 +1,6 @@
package com.simplemobiletools.calendar.pro.models package com.simplemobiletools.calendar.pro.models
import android.provider.CalendarContract.Attendees
import androidx.collection.LongSparseArray import androidx.collection.LongSparseArray
import androidx.room.ColumnInfo import androidx.room.ColumnInfo
import androidx.room.Entity import androidx.room.Entity
@@ -30,7 +31,7 @@ data class Event(
@ColumnInfo(name = "repeat_rule") var repeatRule: Int = 0, @ColumnInfo(name = "repeat_rule") var repeatRule: Int = 0,
@ColumnInfo(name = "repeat_limit") var repeatLimit: Long = 0L, @ColumnInfo(name = "repeat_limit") var repeatLimit: Long = 0L,
@ColumnInfo(name = "repetition_exceptions") var repetitionExceptions: List<String> = emptyList(), @ColumnInfo(name = "repetition_exceptions") var repetitionExceptions: List<String> = emptyList(),
@ColumnInfo(name = "attendees") var attendees: String = "", @ColumnInfo(name = "attendees") var attendees: List<Attendee> = emptyList(),
@ColumnInfo(name = "import_id") var importId: String = "", @ColumnInfo(name = "import_id") var importId: String = "",
@ColumnInfo(name = "time_zone") var timeZone: String = "", @ColumnInfo(name = "time_zone") var timeZone: String = "",
@ColumnInfo(name = "flags") var flags: Int = 0, @ColumnInfo(name = "flags") var flags: Int = 0,
@@ -209,4 +210,8 @@ data class Event(
DateTimeZone.getDefault().id DateTimeZone.getDefault().id
} }
} }
fun isAttendeeInviteDeclined() = attendees.any {
it.isMe && it.status == Attendees.ATTENDEE_STATUS_DECLINED
}
} }

View File

@@ -1,6 +1,36 @@
package com.simplemobiletools.calendar.pro.models package com.simplemobiletools.calendar.pro.models
data class ListEvent( 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 id: Long,
var location: String, var isPastEvent: Boolean, var isRepeatable: Boolean, var isTask: Boolean, var isTaskCompleted: Boolean var startTS: Long,
) : ListItem() 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
)
}
}

View File

@@ -12,5 +12,6 @@ data class MonthViewEvent(
val isAllDay: Boolean, val isAllDay: Boolean,
val isPastEvent: Boolean, val isPastEvent: Boolean,
val isTask: Boolean, val isTask: Boolean,
val isTaskCompleted: Boolean val isTaskCompleted: Boolean,
val isAttendeeInviteDeclined: Boolean,
) )

View File

@@ -130,8 +130,19 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
val daysCnt = getEventLastingDaysCount(event) val daysCnt = getEventLastingDaysCount(event)
val monthViewEvent = MonthViewEvent( val monthViewEvent = MonthViewEvent(
event.id!!, event.title, event.startTS, event.endTS, event.color, dayIndexOnMonthView, id = event.id!!,
daysCnt, dayIndexOnMonthView, event.getIsAllDay(), event.isPastEvent, event.isTask(), event.isTaskCompleted() 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) allEvents.add(monthViewEvent)
} }
@@ -370,7 +381,7 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
val curPaint = Paint(eventTitlePaint) val curPaint = Paint(eventTitlePaint)
curPaint.color = paintColor curPaint.color = paintColor
curPaint.isStrikeThruText = event.isTaskCompleted curPaint.isStrikeThruText = event.shouldStrikeThrough()
return curPaint return curPaint
} }

View File

@@ -2,6 +2,7 @@ plugins {
alias(libs.plugins.android).apply(false) alias(libs.plugins.android).apply(false)
alias(libs.plugins.kotlinAndroid).apply(false) alias(libs.plugins.kotlinAndroid).apply(false)
alias(libs.plugins.ksp).apply(false) alias(libs.plugins.ksp).apply(false)
alias(libs.plugins.parcelize).apply(false)
} }
tasks.register<Delete>("clean") { tasks.register<Delete>("clean") {

View File

@@ -45,3 +45,5 @@ room = [
android = { id = "com.android.application", version.ref = "gradlePlugins-agp" } android = { id = "com.android.application", version.ref = "gradlePlugins-agp" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }