Merge pull request #2041 from Naveen3Singh/feature_event_color
Add support for CalDAV event colors
This commit is contained in:
commit
cf94cf5ac2
|
@ -10,6 +10,7 @@ import android.graphics.drawable.LayerDrawable
|
|||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.CalendarContract.Attendees
|
||||
import android.provider.CalendarContract.Colors
|
||||
import android.provider.ContactsContract.CommonDataKinds
|
||||
import android.provider.ContactsContract.CommonDataKinds.StructuredName
|
||||
import android.provider.ContactsContract.Data
|
||||
|
@ -76,6 +77,7 @@ class EventActivity : SimpleActivity() {
|
|||
private var mOriginalStartTS = 0L
|
||||
private var mOriginalEndTS = 0L
|
||||
private var mIsNewEvent = true
|
||||
private var mEventColor = 0
|
||||
|
||||
private lateinit var mEventStartDateTime: DateTime
|
||||
private lateinit var mEventEndDateTime: DateTime
|
||||
|
@ -164,6 +166,7 @@ class EventActivity : SimpleActivity() {
|
|||
putString(ATTENDEES, getAllAttendees(false))
|
||||
|
||||
putInt(AVAILABILITY, mAvailability)
|
||||
putInt(EVENT_COLOR, mEventColor)
|
||||
|
||||
putLong(EVENT_TYPE_ID, mEventTypeId)
|
||||
putInt(EVENT_CALENDAR_ID, mEventCalendarId)
|
||||
|
@ -196,6 +199,7 @@ class EventActivity : SimpleActivity() {
|
|||
mReminder3Type = getInt(REMINDER_3_TYPE)
|
||||
|
||||
mAvailability = getInt(AVAILABILITY)
|
||||
mEventColor = getInt(EVENT_COLOR)
|
||||
|
||||
mRepeatInterval = getInt(REPEAT_INTERVAL)
|
||||
mRepeatRule = getInt(REPEAT_RULE)
|
||||
|
@ -429,6 +433,7 @@ class EventActivity : SimpleActivity() {
|
|||
mEventTypeId != mEvent.eventType ||
|
||||
mWasCalendarChanged ||
|
||||
mIsAllDayEvent != mEvent.getIsAllDay() ||
|
||||
mEventColor != mEvent.color ||
|
||||
hasTimeChanged
|
||||
) {
|
||||
return true
|
||||
|
@ -488,6 +493,7 @@ class EventActivity : SimpleActivity() {
|
|||
mEventTypeId = mEvent.eventType
|
||||
mEventCalendarId = mEvent.getCalDAVCalendarId()
|
||||
mAvailability = mEvent.availability
|
||||
mEventColor = mEvent.color
|
||||
|
||||
val token = object : TypeToken<List<Attendee>>() {}.type
|
||||
mAttendees = Gson().fromJson<ArrayList<Attendee>>(mEvent.attendees, token) ?: ArrayList()
|
||||
|
@ -825,6 +831,28 @@ class EventActivity : SimpleActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun showEventColorDialog() {
|
||||
hideKeyboard()
|
||||
ensureBackgroundThread {
|
||||
val eventType = eventsHelper.getEventTypeWithCalDAVCalendarId(calendarId = mEventCalendarId)!!
|
||||
val eventColors = getEventColors(eventType)
|
||||
runOnUiThread {
|
||||
val currentColor = if (mEventColor == 0) {
|
||||
eventType.color
|
||||
} else {
|
||||
mEventColor
|
||||
}
|
||||
|
||||
SelectEventColorDialog(activity = this, colors = eventColors, currentColor = currentColor) { newColor ->
|
||||
if (newColor != currentColor) {
|
||||
mEventColor = newColor
|
||||
updateEventColorInfo(defaultColor = eventType.color)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkReminderTexts() {
|
||||
updateReminder1Text()
|
||||
updateReminder2Text()
|
||||
|
@ -959,6 +987,10 @@ class EventActivity : SimpleActivity() {
|
|||
updateAvailabilityImage()
|
||||
}
|
||||
}
|
||||
|
||||
event_caldav_color_holder.setOnClickListener {
|
||||
showEventColorDialog()
|
||||
}
|
||||
} else {
|
||||
updateCurrentCalendarInfo(null)
|
||||
}
|
||||
|
@ -973,7 +1005,6 @@ class EventActivity : SimpleActivity() {
|
|||
event_type_holder.beVisibleIf(currentCalendar == null)
|
||||
event_caldav_calendar_divider.beVisibleIf(currentCalendar == null)
|
||||
event_caldav_calendar_email.beGoneIf(currentCalendar == null)
|
||||
event_caldav_calendar_color.beGoneIf(currentCalendar == null)
|
||||
|
||||
if (currentCalendar == null) {
|
||||
mEventCalendarId = STORED_LOCALLY_ONLY
|
||||
|
@ -986,14 +1017,23 @@ class EventActivity : SimpleActivity() {
|
|||
event_caldav_calendar_holder.apply {
|
||||
setPadding(paddingLeft, mediumMargin, paddingRight, mediumMargin)
|
||||
}
|
||||
|
||||
event_caldav_color_image.beGone()
|
||||
event_caldav_color_holder.beGone()
|
||||
event_caldav_color_divider.beGone()
|
||||
} else {
|
||||
event_caldav_calendar_email.text = currentCalendar.accountName
|
||||
|
||||
ensureBackgroundThread {
|
||||
val calendarColor = eventsHelper.getEventTypeWithCalDAVCalendarId(currentCalendar.id)?.color ?: currentCalendar.color
|
||||
val eventType = eventsHelper.getEventTypeWithCalDAVCalendarId(currentCalendar.id)
|
||||
val calendarColor = eventType?.color ?: currentCalendar.color
|
||||
val canCustomizeColors = if (eventType != null) {
|
||||
getEventColors(eventType).isNotEmpty()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
runOnUiThread {
|
||||
event_caldav_calendar_color.setFillWithStroke(calendarColor, getProperBackgroundColor())
|
||||
event_caldav_calendar_name.apply {
|
||||
text = currentCalendar.displayName
|
||||
setPadding(paddingLeft, paddingTop, paddingRight, resources.getDimension(R.dimen.tiny_margin).toInt())
|
||||
|
@ -1002,11 +1042,31 @@ class EventActivity : SimpleActivity() {
|
|||
event_caldav_calendar_holder.apply {
|
||||
setPadding(paddingLeft, 0, paddingRight, 0)
|
||||
}
|
||||
|
||||
event_caldav_color_image.beVisibleIf(canCustomizeColors)
|
||||
event_caldav_color_holder.beVisibleIf(canCustomizeColors)
|
||||
event_caldav_color_divider.beVisibleIf(canCustomizeColors)
|
||||
if (canCustomizeColors) {
|
||||
updateEventColorInfo(calendarColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateEventColorInfo(defaultColor: Int) {
|
||||
val eventColor = if (mEventColor == 0) {
|
||||
defaultColor
|
||||
} else {
|
||||
mEventColor
|
||||
}
|
||||
event_caldav_color.setFillWithStroke(eventColor, getProperBackgroundColor())
|
||||
}
|
||||
|
||||
private fun getEventColors(eventType: EventType): IntArray {
|
||||
return calDAVHelper.getAvailableCalDAVCalendarColors(eventType, Colors.TYPE_EVENT).keys.toIntArray()
|
||||
}
|
||||
|
||||
private fun resetTime() {
|
||||
if (mEventEndDateTime.isBefore(mEventStartDateTime) &&
|
||||
mEventStartDateTime.dayOfMonth() == mEventEndDateTime.dayOfMonth() &&
|
||||
|
@ -1195,6 +1255,7 @@ class EventActivity : SimpleActivity() {
|
|||
source = newSource
|
||||
location = event_location.value
|
||||
availability = mAvailability
|
||||
color = mEventColor
|
||||
}
|
||||
|
||||
// recreate the event if it was moved in a different CalDAV calendar
|
||||
|
@ -1791,7 +1852,7 @@ class EventActivity : SimpleActivity() {
|
|||
val textColor = getProperTextColor()
|
||||
arrayOf(
|
||||
event_time_image, event_time_zone_image, event_repetition_image, event_reminder_image, event_type_image, event_caldav_calendar_image,
|
||||
event_reminder_1_type, event_reminder_2_type, event_reminder_3_type, event_attendees_image, event_availability_image
|
||||
event_reminder_1_type, event_reminder_2_type, event_reminder_3_type, event_attendees_image, event_availability_image, event_caldav_color_image
|
||||
).forEach {
|
||||
it.applyColorFilter(textColor)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package com.simplemobiletools.calendar.pro.adapters
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Color
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.simplemobiletools.calendar.pro.R
|
||||
import com.simplemobiletools.commons.extensions.applyColorFilter
|
||||
import kotlinx.android.synthetic.main.checkable_color_button.view.*
|
||||
|
||||
class CheckableColorAdapter(private val activity: Activity, private val colors: IntArray, var currentColor: Int, val callback: (color: Int) -> Unit) :
|
||||
RecyclerView.Adapter<CheckableColorAdapter.CheckableColorViewHolder>() {
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CheckableColorViewHolder {
|
||||
val itemView = LayoutInflater.from(activity).inflate(R.layout.checkable_color_button, parent, false)
|
||||
return CheckableColorViewHolder(itemView)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: CheckableColorViewHolder, position: Int) {
|
||||
val color = colors[position]
|
||||
holder.bindView(color = color, checked = color == currentColor)
|
||||
}
|
||||
|
||||
override fun getItemCount() = colors.size
|
||||
|
||||
private fun updateSelection(color: Int) {
|
||||
currentColor = color
|
||||
callback(color)
|
||||
}
|
||||
|
||||
inner class CheckableColorViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
fun bindView(color: Int, checked: Boolean) {
|
||||
itemView.checkable_color_button.apply {
|
||||
backgroundTintList = ColorStateList.valueOf(color)
|
||||
setOnClickListener {
|
||||
updateSelection(color)
|
||||
}
|
||||
|
||||
if (checked) {
|
||||
setImageResource(R.drawable.ic_check_vector)
|
||||
applyColorFilter(Color.WHITE)
|
||||
} else {
|
||||
setImageDrawable(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import android.app.Activity
|
|||
import android.widget.ImageView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.simplemobiletools.calendar.pro.R
|
||||
import com.simplemobiletools.calendar.pro.extensions.calDAVHelper
|
||||
import com.simplemobiletools.calendar.pro.extensions.eventsHelper
|
||||
import com.simplemobiletools.calendar.pro.helpers.OTHER_EVENT
|
||||
import com.simplemobiletools.calendar.pro.models.EventType
|
||||
|
@ -32,7 +33,9 @@ class EditEventTypeDialog(val activity: Activity, var eventType: EventType? = nu
|
|||
}
|
||||
}
|
||||
} else {
|
||||
SelectEventTypeColorDialog(activity, eventType!!) {
|
||||
val currentColor = eventType!!.color
|
||||
val colors = activity.calDAVHelper.getAvailableCalDAVCalendarColors(eventType!!).keys.toIntArray()
|
||||
SelectEventTypeColorDialog(activity, colors = colors, currentColor = currentColor) {
|
||||
eventType!!.color = it
|
||||
setupColor(type_color)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package com.simplemobiletools.calendar.pro.dialogs
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.simplemobiletools.calendar.pro.R
|
||||
import com.simplemobiletools.calendar.pro.adapters.CheckableColorAdapter
|
||||
import com.simplemobiletools.calendar.pro.views.AutoGridLayoutManager
|
||||
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import kotlinx.android.synthetic.main.dialog_select_color.view.*
|
||||
|
||||
class SelectEventColorDialog(val activity: Activity, val colors: IntArray, var currentColor: Int, val callback: (color: Int) -> Unit) {
|
||||
private var dialog: AlertDialog? = null
|
||||
|
||||
init {
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_select_color, null) as ViewGroup
|
||||
val colorAdapter = CheckableColorAdapter(activity, colors, currentColor) { color ->
|
||||
callback(color)
|
||||
dialog?.dismiss()
|
||||
}
|
||||
|
||||
view.color_grid.apply {
|
||||
val width = activity.resources.getDimensionPixelSize(R.dimen.smaller_icon_size)
|
||||
val spacing = activity.resources.getDimensionPixelSize(R.dimen.small_margin) * 2
|
||||
layoutManager = AutoGridLayoutManager(context = activity, itemWidth = width + spacing)
|
||||
adapter = colorAdapter
|
||||
}
|
||||
|
||||
activity.getAlertDialogBuilder()
|
||||
.apply {
|
||||
setNeutralButton(R.string.default_calendar_color) { dialog, _ ->
|
||||
callback(0)
|
||||
dialog?.dismiss()
|
||||
}
|
||||
|
||||
activity.setupDialogStuff(view, this, R.string.event_color) {
|
||||
dialog = it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,42 +2,37 @@ package com.simplemobiletools.calendar.pro.dialogs
|
|||
|
||||
import android.app.Activity
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RadioButton
|
||||
import android.widget.RadioGroup
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.simplemobiletools.calendar.pro.R
|
||||
import com.simplemobiletools.calendar.pro.extensions.calDAVHelper
|
||||
import com.simplemobiletools.calendar.pro.models.EventType
|
||||
import com.simplemobiletools.calendar.pro.adapters.CheckableColorAdapter
|
||||
import com.simplemobiletools.calendar.pro.views.AutoGridLayoutManager
|
||||
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
|
||||
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
|
||||
import com.simplemobiletools.commons.extensions.getProperBackgroundColor
|
||||
import com.simplemobiletools.commons.extensions.setFillWithStroke
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import kotlinx.android.synthetic.main.dialog_select_event_type_color.view.*
|
||||
import kotlinx.android.synthetic.main.radio_button_with_color.view.*
|
||||
import kotlinx.android.synthetic.main.dialog_select_color.view.*
|
||||
|
||||
class SelectEventTypeColorDialog(val activity: Activity, val eventType: EventType, val callback: (color: Int) -> Unit) {
|
||||
class SelectEventTypeColorDialog(val activity: Activity, val colors: IntArray, var currentColor: Int, val callback: (color: Int) -> Unit) {
|
||||
private var dialog: AlertDialog? = null
|
||||
private val radioGroup: RadioGroup
|
||||
private var wasInit = false
|
||||
private val colors = activity.calDAVHelper.getAvailableCalDAVCalendarColors(eventType)
|
||||
|
||||
init {
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_select_event_type_color, null) as ViewGroup
|
||||
radioGroup = view.dialog_select_event_type_color_radio
|
||||
view.dialog_select_event_type_other_value.setOnClickListener {
|
||||
showCustomColorPicker()
|
||||
val view = activity.layoutInflater.inflate(R.layout.dialog_select_color, null) as ViewGroup
|
||||
val colorAdapter = CheckableColorAdapter(activity, colors, currentColor) { color ->
|
||||
callback(color)
|
||||
dialog?.dismiss()
|
||||
}
|
||||
|
||||
colors.forEachIndexed { index, value ->
|
||||
addRadioButton(index, value)
|
||||
view.color_grid.apply {
|
||||
val width = activity.resources.getDimensionPixelSize(R.dimen.smaller_icon_size)
|
||||
val spacing = activity.resources.getDimensionPixelSize(R.dimen.small_margin) * 2
|
||||
layoutManager = AutoGridLayoutManager(context = activity, itemWidth = width + spacing)
|
||||
adapter = colorAdapter
|
||||
}
|
||||
|
||||
wasInit = true
|
||||
activity.getAlertDialogBuilder()
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.apply {
|
||||
activity.setupDialogStuff(view, this) { alertDialog ->
|
||||
dialog = alertDialog
|
||||
activity.setupDialogStuff(view, this, R.string.color) {
|
||||
dialog = it
|
||||
}
|
||||
|
||||
if (colors.isEmpty()) {
|
||||
|
@ -46,34 +41,12 @@ class SelectEventTypeColorDialog(val activity: Activity, val eventType: EventTyp
|
|||
}
|
||||
}
|
||||
|
||||
private fun addRadioButton(colorKey: Int, color: Int) {
|
||||
val view = activity.layoutInflater.inflate(R.layout.radio_button_with_color, null)
|
||||
(view.dialog_radio_button as RadioButton).apply {
|
||||
text = if (color == 0) activity.getString(R.string.transparent) else String.format("#%06X", 0xFFFFFF and color)
|
||||
isChecked = color == eventType.color
|
||||
id = colorKey
|
||||
}
|
||||
|
||||
view.dialog_radio_color.setFillWithStroke(color, activity.getProperBackgroundColor())
|
||||
view.setOnClickListener {
|
||||
viewClicked(colorKey)
|
||||
}
|
||||
radioGroup.addView(view, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
|
||||
}
|
||||
|
||||
private fun viewClicked(colorKey: Int) {
|
||||
if (!wasInit)
|
||||
return
|
||||
|
||||
callback(colors[colorKey])
|
||||
dialog?.dismiss()
|
||||
}
|
||||
|
||||
private fun showCustomColorPicker() {
|
||||
ColorPickerDialog(activity, eventType.color) { wasPositivePressed, color ->
|
||||
ColorPickerDialog(activity, currentColor) { wasPositivePressed, color ->
|
||||
if (wasPositivePressed) {
|
||||
callback(color)
|
||||
}
|
||||
|
||||
dialog?.dismiss()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -557,9 +557,13 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
|||
|
||||
val dayColumn = dayColumns[dayOfWeek]
|
||||
(inflater.inflate(R.layout.week_event_marker, null, false) as ConstraintLayout).apply {
|
||||
var backgroundColor = eventTypeColors.get(event.eventType, primaryColor)
|
||||
var backgroundColor = if (event.color == 0) {
|
||||
eventTypeColors.get(event.eventType, primaryColor)
|
||||
} else {
|
||||
event.color
|
||||
}
|
||||
var textColor = backgroundColor.getContrastColor()
|
||||
val currentEventWeeklyView = eventTimeRanges[currentDayCode]!!.get(event.id)
|
||||
val currentEventWeeklyView = eventTimeRanges[currentDayCode]!![event.id]
|
||||
|
||||
val adjustAlpha = if (event.isTask()) {
|
||||
dimCompletedTasks && event.isTaskCompleted()
|
||||
|
|
|
@ -4,8 +4,8 @@ import android.annotation.SuppressLint
|
|||
import android.content.ContentUris
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.provider.CalendarContract.*
|
||||
import android.util.SparseIntArray
|
||||
import android.widget.Toast
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
|
@ -20,6 +20,7 @@ import org.joda.time.DateTimeZone
|
|||
import org.joda.time.format.DateTimeFormat
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
class CalDAVHelper(val context: Context) {
|
||||
|
@ -84,8 +85,9 @@ class CalDAVHelper(val context: Context) {
|
|||
val accountType = cursor.getStringValue(Calendars.ACCOUNT_TYPE)
|
||||
val ownerName = cursor.getStringValue(Calendars.OWNER_ACCOUNT) ?: ""
|
||||
val color = cursor.getIntValue(Calendars.CALENDAR_COLOR)
|
||||
val displayColor = getDisplayColorFromColor(color)
|
||||
val accessLevel = cursor.getIntValue(Calendars.CALENDAR_ACCESS_LEVEL)
|
||||
val calendar = CalDAVCalendar(id, displayName, accountName, accountType, ownerName, color, accessLevel)
|
||||
val calendar = CalDAVCalendar(id, displayName, accountName, accountType, ownerName, displayColor, accessLevel)
|
||||
calendars.add(calendar)
|
||||
}
|
||||
|
||||
|
@ -116,35 +118,33 @@ class CalDAVHelper(val context: Context) {
|
|||
|
||||
private fun getCalDAVColorKey(eventType: EventType): String? {
|
||||
val colors = getAvailableCalDAVCalendarColors(eventType)
|
||||
val colorKey = colors.indexOf(eventType.color)
|
||||
return if (colorKey > 0) {
|
||||
colorKey.toString()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
return colors[eventType.color]
|
||||
}
|
||||
|
||||
// darkens the given color to ensure that white text is clearly visible on top of it
|
||||
private fun getDisplayColorFromColor(color: Int): Int {
|
||||
val hsv = FloatArray(3)
|
||||
Color.colorToHSV(color, hsv)
|
||||
hsv[1] = min(hsv[1] * SATURATION_ADJUST, 1.0f)
|
||||
hsv[2] = hsv[2] * INTENSITY_ADJUST
|
||||
return Color.HSVToColor(hsv)
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun getAvailableCalDAVCalendarColors(eventType: EventType): ArrayList<Int> {
|
||||
val colors = SparseIntArray()
|
||||
fun getAvailableCalDAVCalendarColors(eventType: EventType, colorType: Int = Colors.TYPE_CALENDAR): Map<Int, String> {
|
||||
val colors = mutableMapOf<Int, String>()
|
||||
val uri = Colors.CONTENT_URI
|
||||
val projection = arrayOf(Colors.COLOR, Colors.COLOR_KEY)
|
||||
val selection = "${Colors.COLOR_TYPE} = ? AND ${Colors.ACCOUNT_NAME} = ?"
|
||||
val selectionArgs = arrayOf(Colors.TYPE_CALENDAR.toString(), eventType.caldavEmail)
|
||||
val selectionArgs = arrayOf(colorType.toString(), eventType.caldavEmail)
|
||||
|
||||
context.queryCursor(uri, projection, selection, selectionArgs) { cursor ->
|
||||
val colorKey = cursor.getIntValue(Colors.COLOR_KEY)
|
||||
val colorKey = cursor.getStringValue(Colors.COLOR_KEY)
|
||||
val color = cursor.getIntValue(Colors.COLOR)
|
||||
colors.put(colorKey, color)
|
||||
val displayColor = getDisplayColorFromColor(color)
|
||||
colors[displayColor] = colorKey
|
||||
}
|
||||
|
||||
var sortedColors = ArrayList<Int>(colors.size())
|
||||
(0 until colors.size()).mapTo(sortedColors) { colors[it] }
|
||||
if (sortedColors.isNotEmpty()) {
|
||||
sortedColors = sortedColors.distinct() as ArrayList<Int>
|
||||
}
|
||||
|
||||
return sortedColors
|
||||
return colors.toSortedMap(HsvColorComparator())
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
|
@ -181,7 +181,8 @@ class CalDAVHelper(val context: Context) {
|
|||
Events.EVENT_TIMEZONE,
|
||||
Events.CALENDAR_TIME_ZONE,
|
||||
Events.DELETED,
|
||||
Events.AVAILABILITY
|
||||
Events.AVAILABILITY,
|
||||
Events.EVENT_COLOR
|
||||
)
|
||||
|
||||
val selection = "${Events.CALENDAR_ID} = $calendarId"
|
||||
|
@ -210,6 +211,12 @@ class CalDAVHelper(val context: Context) {
|
|||
val reminders = getCalDAVEventReminders(id)
|
||||
val attendees = Gson().toJson(getCalDAVEventAttendees(id))
|
||||
val availability = cursor.getIntValue(Events.AVAILABILITY)
|
||||
val color = cursor.getIntValueOrNull(Events.EVENT_COLOR)
|
||||
val displayColor = if (color != null) {
|
||||
getDisplayColorFromColor(color)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
||||
if (endTS == 0L) {
|
||||
val duration = cursor.getStringValue(Events.DURATION) ?: ""
|
||||
|
@ -230,7 +237,8 @@ class CalDAVHelper(val context: Context) {
|
|||
reminder2?.minutes ?: REMINDER_OFF, reminder3?.minutes ?: REMINDER_OFF,
|
||||
reminder1?.type ?: REMINDER_NOTIFICATION, reminder2?.type ?: REMINDER_NOTIFICATION,
|
||||
reminder3?.type ?: REMINDER_NOTIFICATION, repeatRule.repeatInterval, repeatRule.repeatRule,
|
||||
repeatRule.repeatLimit, ArrayList(), attendees, importId, eventTimeZone, allDay, eventTypeId, source = source, availability = availability
|
||||
repeatRule.repeatLimit, ArrayList(), attendees, importId, eventTimeZone, allDay, eventTypeId,
|
||||
source = source, availability = availability, color = displayColor
|
||||
)
|
||||
|
||||
if (event.getIsAllDay()) {
|
||||
|
@ -291,7 +299,6 @@ class CalDAVHelper(val context: Context) {
|
|||
|
||||
existingEvent.apply {
|
||||
this.id = null
|
||||
color = 0
|
||||
lastUpdated = 0L
|
||||
repetitionExceptions = ArrayList()
|
||||
}
|
||||
|
@ -394,14 +401,23 @@ class CalDAVHelper(val context: Context) {
|
|||
}
|
||||
|
||||
private fun fillEventContentValues(event: Event): ContentValues {
|
||||
val calendarId = event.getCalDAVCalendarId()
|
||||
return ContentValues().apply {
|
||||
put(Events.CALENDAR_ID, event.getCalDAVCalendarId())
|
||||
put(Events.CALENDAR_ID, calendarId)
|
||||
put(Events.TITLE, event.title)
|
||||
put(Events.DESCRIPTION, event.description)
|
||||
put(Events.EVENT_LOCATION, event.location)
|
||||
put(Events.STATUS, Events.STATUS_CONFIRMED)
|
||||
put(Events.AVAILABILITY, event.availability)
|
||||
|
||||
if (event.color == 0) {
|
||||
put(Events.EVENT_COLOR_KEY, "")
|
||||
} else {
|
||||
val eventType = eventsHelper.getEventTypeWithCalDAVCalendarId(calendarId)!!
|
||||
val colors = getAvailableCalDAVCalendarColors(eventType, Colors.TYPE_EVENT)
|
||||
put(Events.EVENT_COLOR_KEY, colors[event.color])
|
||||
}
|
||||
|
||||
val repeatRule = Parser().getRepeatCode(event)
|
||||
if (repeatRule.isEmpty()) {
|
||||
putNull(Events.RRULE)
|
||||
|
@ -534,4 +550,9 @@ class CalDAVHelper(val context: Context) {
|
|||
private fun getCalDAVEventImportId(calendarId: Int, eventId: Long) = "$CALDAV-$calendarId-$eventId"
|
||||
|
||||
private fun refreshCalDAVCalendar(event: Event) = context.refreshCalDAVCalendars(event.getCalDAVCalendarId().toString(), false)
|
||||
|
||||
companion object {
|
||||
private const val INTENSITY_ADJUST = 0.8f
|
||||
private const val SATURATION_ADJUST = 1.3f
|
||||
}
|
||||
}
|
||||
|
|
|
@ -255,6 +255,7 @@ const val AVAILABILITY = "AVAILABILITY"
|
|||
const val EVENT_TYPE_ID = "EVENT_TYPE_ID"
|
||||
const val EVENT_CALENDAR_ID = "EVENT_CALENDAR_ID"
|
||||
const val IS_NEW_EVENT = "IS_NEW_EVENT"
|
||||
const val EVENT_COLOR = "EVENT_COLOR"
|
||||
|
||||
// actions
|
||||
const val ACTION_MARK_COMPLETED = "ACTION_MARK_COMPLETED"
|
||||
|
|
|
@ -337,7 +337,10 @@ class EventsHelper(val context: Context) {
|
|||
}
|
||||
}
|
||||
}
|
||||
it.color = eventTypeColors.get(it.eventType) ?: context.getProperPrimaryColor()
|
||||
|
||||
if (it.color == 0) {
|
||||
it.color = eventTypeColors.get(it.eventType) ?: context.getProperPrimaryColor()
|
||||
}
|
||||
}
|
||||
|
||||
callback(events)
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package com.simplemobiletools.calendar.pro.helpers
|
||||
|
||||
import android.graphics.Color
|
||||
|
||||
/**
|
||||
* A color comparator which compares based on hue, saturation, and value.
|
||||
* Source: AOSP Color picker, https://cs.android.com/android/platform/superproject/+/master:frameworks/opt/colorpicker/src/com/android/colorpicker/HsvColorComparator.java
|
||||
*/
|
||||
class HsvColorComparator : Comparator<Int?> {
|
||||
override fun compare(lhs: Int?, rhs: Int?): Int {
|
||||
val hsv = FloatArray(3)
|
||||
Color.colorToHSV(lhs!!, hsv)
|
||||
val hue1 = hsv[0]
|
||||
val sat1 = hsv[1]
|
||||
val val1 = hsv[2]
|
||||
val hsv2 = FloatArray(3)
|
||||
Color.colorToHSV(rhs!!, hsv2)
|
||||
val hue2 = hsv2[0]
|
||||
val sat2 = hsv2[1]
|
||||
val val2 = hsv2[2]
|
||||
if (hue1 < hue2) {
|
||||
return 1
|
||||
} else if (hue1 > hue2) {
|
||||
return -1
|
||||
} else {
|
||||
if (sat1 < sat2) {
|
||||
return 1
|
||||
} else if (sat1 > sat2) {
|
||||
return -1
|
||||
} else {
|
||||
if (val1 < val2) {
|
||||
return 1
|
||||
} else if (val1 > val2) {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.simplemobiletools.calendar.pro.views
|
||||
|
||||
import android.content.Context
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
* RecyclerView GridLayoutManager but with automatic spanCount calculation
|
||||
* @param itemWidth: Grid item width in pixels. Will be used to calculate span count.
|
||||
*/
|
||||
class AutoGridLayoutManager(
|
||||
context: Context,
|
||||
private var itemWidth: Int
|
||||
) : GridLayoutManager(context, 1) {
|
||||
|
||||
init {
|
||||
require(itemWidth >= 0)
|
||||
}
|
||||
|
||||
override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) {
|
||||
val width = width
|
||||
val height = height
|
||||
if (itemWidth > 0 && width > 0 && height > 0) {
|
||||
val totalSpace = if (orientation == VERTICAL) {
|
||||
width - paddingRight - paddingLeft
|
||||
} else {
|
||||
height - paddingTop - paddingBottom
|
||||
}
|
||||
spanCount = max(1, totalSpace / itemWidth)
|
||||
}
|
||||
super.onLayoutChildren(recycler, state)
|
||||
}
|
||||
}
|
|
@ -507,10 +507,63 @@
|
|||
android:importantForAccessibility="no" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/event_caldav_calendar_image"
|
||||
android:id="@+id/event_caldav_color_image"
|
||||
android:layout_width="@dimen/smaller_icon_size"
|
||||
android:layout_height="@dimen/smaller_icon_size"
|
||||
android:layout_below="@+id/event_availability_divider"
|
||||
android:layout_alignTop="@+id/event_caldav_color_holder"
|
||||
android:layout_alignBottom="@+id/event_caldav_color_holder"
|
||||
android:layout_marginStart="@dimen/normal_margin"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_color_vector" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/event_caldav_color_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/event_availability_divider"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:layout_marginBottom="@dimen/medium_margin"
|
||||
android:layout_toEndOf="@+id/event_caldav_color_image"
|
||||
android:background="?attr/selectableItemBackground">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/event_color_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/small_margin"
|
||||
android:layout_marginEnd="@dimen/medium_margin"
|
||||
android:layout_toStartOf="@+id/event_caldav_color"
|
||||
android:paddingTop="@dimen/normal_margin"
|
||||
android:paddingBottom="@dimen/normal_margin"
|
||||
android:text="@string/event_color"
|
||||
android:textSize="@dimen/day_text_size" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/event_caldav_color"
|
||||
android:layout_width="@dimen/color_sample_size"
|
||||
android:layout_height="@dimen/color_sample_size"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="@dimen/activity_margin"
|
||||
android:clickable="false" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/event_caldav_color_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/divider_height"
|
||||
android:layout_below="@+id/event_caldav_color_image"
|
||||
android:layout_marginTop="@dimen/medium_margin"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/event_caldav_calendar_image"
|
||||
android:layout_width="@dimen/smaller_icon_size"
|
||||
android:layout_height="@dimen/smaller_icon_size"
|
||||
android:layout_below="@+id/event_caldav_color_divider"
|
||||
android:layout_alignTop="@+id/event_caldav_calendar_holder"
|
||||
android:layout_alignEnd="@+id/event_time_image"
|
||||
android:layout_alignBottom="@+id/event_caldav_calendar_holder"
|
||||
|
@ -523,7 +576,7 @@
|
|||
android:id="@+id/event_caldav_calendar_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/event_availability_divider"
|
||||
android:layout_below="@+id/event_caldav_color_divider"
|
||||
android:layout_toEndOf="@+id/event_caldav_calendar_image"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:visibility="gone">
|
||||
|
@ -533,7 +586,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/small_margin"
|
||||
android:layout_toStartOf="@+id/event_caldav_calendar_color"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:paddingTop="@dimen/medium_margin"
|
||||
|
@ -548,7 +600,6 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/event_caldav_calendar_name"
|
||||
android:layout_marginStart="@dimen/small_margin"
|
||||
android:layout_toStartOf="@+id/event_caldav_calendar_color"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:paddingEnd="@dimen/medium_margin"
|
||||
|
@ -556,15 +607,6 @@
|
|||
android:textSize="@dimen/meta_text_size"
|
||||
tools:text="hello@simplemobiletools.com" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/event_caldav_calendar_color"
|
||||
android:layout_width="@dimen/color_sample_size"
|
||||
android:layout_height="@dimen/color_sample_size"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="@dimen/activity_margin"
|
||||
android:clickable="false" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<ImageView
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?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:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/small_margin">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/checkable_color_button"
|
||||
android:layout_width="@dimen/smaller_icon_size"
|
||||
android:layout_height="@dimen/smaller_icon_size"
|
||||
android:background="@drawable/button_background_rounded"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="@dimen/medium_margin"
|
||||
tools:src="@drawable/ic_check_vector" />
|
||||
|
||||
</FrameLayout>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/color_grid_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/big_margin"
|
||||
android:paddingBottom="@dimen/medium_margin">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/color_grid"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:overScrollMode="ifContentScrolls"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:itemCount="16"
|
||||
tools:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||
tools:listitem="@layout/checkable_color_button"
|
||||
tools:spanCount="6" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,45 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/dialog_select_event_type_color_scrollview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/dialog_select_event_type_other_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/dialog_select_event_type_other_value"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingStart="@dimen/big_margin"
|
||||
android:paddingTop="@dimen/activity_margin"
|
||||
android:paddingEnd="@dimen/activity_margin"
|
||||
android:paddingBottom="@dimen/activity_margin"
|
||||
android:text="@string/select_a_different_caldav_color"
|
||||
android:textSize="@dimen/normal_text_size"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dialog_select_event_type_other_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/divider_height"
|
||||
android:layout_below="@+id/dialog_select_event_type_other_value"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no"
|
||||
android:visibility="gone" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/dialog_select_event_type_color_radio"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/dialog_select_event_type_other_divider"
|
||||
android:paddingStart="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/normal_margin"
|
||||
android:paddingEnd="@dimen/activity_margin"
|
||||
android:paddingBottom="@dimen/normal_margin" />
|
||||
|
||||
</RelativeLayout>
|
||||
</ScrollView>
|
Loading…
Reference in New Issue