diff --git a/app/detekt-baseline.xml b/app/detekt-baseline.xml index 8f2feccdc..65084db15 100644 --- a/app/detekt-baseline.xml +++ b/app/detekt-baseline.xml @@ -7,34 +7,34 @@ ComplexCondition:EventListWidgetAdapter.kt$EventListWidgetAdapter$item.isTask && item.isTaskCompleted && dimCompletedTasks || dimPastEvents && item.isPastEvent && !item.isTask ComplexCondition:EventsHelper.kt$EventsHelper$addToCalDAV && config.caldavSync && event.source != SOURCE_SIMPLE_CALENDAR && event.source != SOURCE_IMPORTED_ICS ComplexCondition:EventsHelper.kt$EventsHelper$addToCalDAV && event.source != SOURCE_SIMPLE_CALENDAR && event.source != SOURCE_IMPORTED_ICS && config.caldavSync - ComplexCondition:EventsHelper.kt$EventsHelper$originalEvent != null && (birthDayEventId != -1L && it.eventType == birthDayEventId) or (anniversaryEventId != -1L && it.eventType == anniversaryEventId) + ComplexCondition:EventsHelper.kt$EventsHelper$originalEvent != null && (birthDayEventId != -1L && it.calendarId == birthDayEventId) or (anniversaryEventId != -1L && it.calendarId == anniversaryEventId) ComplexCondition:MainActivity.kt$MainActivity$mStoredFirstDayOfWeek != config.firstDayOfWeek || mStoredUse24HourFormat != config.use24HourFormat || mStoredMidnightSpan != config.showMidnightSpanningEventsAtTop || mStoredStartWeekWithCurrentDay != config.startWeekWithCurrentDay ComplexCondition:MainActivity.kt$MainActivity$mStoredTextColor != getProperTextColor() || mStoredBackgroundColor != getProperBackgroundColor() || mStoredPrimaryColor != getProperPrimaryColor() || mStoredDayCode != Formatter.getTodayCode() || mStoredDimPastEvents != config.dimPastEvents || mStoredDimCompletedTasks != config.dimCompletedTasks || mStoredHighlightWeekends != config.highlightWeekends || mStoredHighlightWeekendsColor != config.highlightWeekendsColor ComplexCondition:MonthView.kt$MonthView$isMonthDayView && !isDaySelected && !day.isToday && day.dayEvents.isNotEmpty() - ComplexCondition:SettingsActivity.kt$SettingsActivity$requestCode == PICK_EVENTS_EXPORT_FILE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null - ComplexCondition:SettingsActivity.kt$SettingsActivity$requestCode == PICK_EVENTS_IMPORT_SOURCE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null - ComplexCondition:SettingsActivity.kt$SettingsActivity$requestCode == PICK_SETTINGS_IMPORT_SOURCE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null + ComplexCondition:SettingsActivity.kt$SettingsActivity$requestCode == PICK_EVENTS_EXPORT_FILE_INTENT && resultCode == RESULT_OK && resultData != null && resultData.data != null + ComplexCondition:SettingsActivity.kt$SettingsActivity$requestCode == PICK_EVENTS_IMPORT_SOURCE_INTENT && resultCode == RESULT_OK && resultData != null && resultData.data != null + ComplexCondition:SettingsActivity.kt$SettingsActivity$requestCode == PICK_SETTINGS_IMPORT_SOURCE_INTENT && resultCode == RESULT_OK && resultData != null && resultData.data != null ComplexCondition:TaskActivity.kt$TaskActivity$config.wasAlarmWarningShown || (mReminder1Minutes == REMINDER_OFF && mReminder2Minutes == REMINDER_OFF && mReminder3Minutes == REMINDER_OFF) ComplexCondition:TaskActivity.kt$TaskActivity$day == MONDAY_BIT || day == TUESDAY_BIT || day == WEDNESDAY_BIT || day == THURSDAY_BIT || day == FRIDAY_BIT || day == SATURDAY_BIT || day == SUNDAY_BIT ComplexCondition:WeekFragment.kt$WeekFragment$doesEventFit && (!isRepeatingOverlappingEvent || isAllDayEvent || isRowValidForEvent) ConstructorParameterNaming:Task.kt$Task$@ColumnInfo(name = "task_id") var task_id: Long - CyclomaticComplexMethod:CalDAVHelper.kt$CalDAVHelper$@SuppressLint("MissingPermission") private fun fetchCalDAVCalendarEvents( calendar: CalDAVCalendar, eventTypeId: Long, showToasts: Boolean, ) - CyclomaticComplexMethod:Context.kt$@SuppressLint("NewApi") fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content: String, publicVersion: Boolean = false): Notification? + CyclomaticComplexMethod:CalDAVHelper.kt$CalDAVHelper$@SuppressLint("MissingPermission") private fun fetchCalDAVCalendarEvents( calendar: CalDAVCalendar, localCalendarId: Long, showToasts: Boolean, ) + CyclomaticComplexMethod:Context.kt$@SuppressLint("NewApi") fun Context.getNotification( pendingIntent: PendingIntent, event: Event, content: String, publicVersion: Boolean = false ): Notification? CyclomaticComplexMethod:Context.kt$fun Context.notifyEvent(originalEvent: Event) CyclomaticComplexMethod:DayEventsAdapter.kt$DayEventsAdapter$private fun setupView(view: View, event: Event) CyclomaticComplexMethod:EventActivity.kt$EventActivity$private fun getOrderString(repeatRule: Int): String - CyclomaticComplexMethod:EventActivity.kt$EventActivity$private fun gotEvent( savedInstanceState: Bundle?, localEventType: EventType?, event: Event?, ) + CyclomaticComplexMethod:EventActivity.kt$EventActivity$private fun gotEvent( savedInstanceState: Bundle?, localCalendar: CalendarEntity?, event: Event?, ) CyclomaticComplexMethod:EventActivity.kt$EventActivity$private fun isEventChanged(): Boolean CyclomaticComplexMethod:EventActivity.kt$EventActivity$private fun saveEvent() CyclomaticComplexMethod:EventListAdapter.kt$EventListAdapter$private fun setupListEvent(view: View, listEvent: ListEvent) CyclomaticComplexMethod:EventListWidgetAdapter.kt$EventListWidgetAdapter$private fun setupListEvent(remoteView: RemoteViews, item: ListEvent) CyclomaticComplexMethod:EventsHelper.kt$EventsHelper$fun getEventsSync( fromTS: Long, toTS: Long, eventId: Long = -1L, applyTypeFilter: Boolean, searchQuery: String = "", callback: (events: ArrayList<Event>) -> Unit ) - CyclomaticComplexMethod:EventsHelper.kt$EventsHelper$private fun getEventsRepeatingTillDateOrForever(fromTS: Long, toTS: Long, startTimes: LongSparseArray<Long>, event: Event): ArrayList<Event> + CyclomaticComplexMethod:EventsHelper.kt$EventsHelper$private fun getEventsRepeatingTillDateOrForever( fromTS: Long, toTS: Long, startTimes: LongSparseArray<Long>, event: Event ): ArrayList<Event> CyclomaticComplexMethod:IcsExporter.kt$IcsExporter$private fun writeEvent(writer: BufferedWriter, event: Event) CyclomaticComplexMethod:IcsExporter.kt$IcsExporter$private fun writeTask(writer: BufferedWriter, task: Event) - CyclomaticComplexMethod:IcsImporter.kt$IcsImporter$fun importEvents( path: String, defaultEventTypeId: Long, calDAVCalendarId: Int, overrideFileEventTypes: Boolean, eventReminders: ArrayList<Int>? = null, loadFromAssets: Boolean = false, ): ImportResult + CyclomaticComplexMethod:IcsImporter.kt$IcsImporter$fun importEvents( path: String, defaultCalendarId: Long, calDAVCalendarId: Int, overrideFileCalendars: Boolean, eventReminders: ArrayList<Int>? = null, loadFromAssets: Boolean = false, ): ImportResult CyclomaticComplexMethod:MainActivity.kt$MainActivity$override fun onResume() - CyclomaticComplexMethod:MainActivity.kt$MainActivity$private fun addContactEvents(birthdays: Boolean, reminders: ArrayList<Int>, initEventsFound: Int, initEventsAdded: Int, callback: (Int) -> Unit) + CyclomaticComplexMethod:MainActivity.kt$MainActivity$private fun addContactEvents( birthdays: Boolean, reminders: ArrayList<Int>, initEventsFound: Int, initEventsAdded: Int, callback: (Int) -> Unit ) CyclomaticComplexMethod:MainActivity.kt$MainActivity$private fun addPrivateEvents( birthdays: Boolean, contacts: ArrayList<SimpleContact>, reminders: ArrayList<Int>, callback: (eventsFound: Int, eventsAdded: Int) -> Unit ) CyclomaticComplexMethod:MainActivity.kt$MainActivity$private fun setupOptionsMenu() CyclomaticComplexMethod:MonthView.kt$MonthView$override fun onDraw(canvas: Canvas) @@ -43,7 +43,7 @@ CyclomaticComplexMethod:SettingsActivity.kt$SettingsActivity$override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) CyclomaticComplexMethod:SettingsActivity.kt$SettingsActivity$private fun parseFile(inputStream: InputStream?) CyclomaticComplexMethod:TaskActivity.kt$TaskActivity$private fun getOrderString(repeatRule: Int): String - CyclomaticComplexMethod:TaskActivity.kt$TaskActivity$private fun gotTask(savedInstanceState: Bundle?, localEventType: EventType?, task: Event?) + CyclomaticComplexMethod:TaskActivity.kt$TaskActivity$private fun gotTask(savedInstanceState: Bundle?, localCalendar: CalendarEntity?, task: Event?) CyclomaticComplexMethod:TaskActivity.kt$TaskActivity$private fun saveTask() CyclomaticComplexMethod:WeekFragment.kt$WeekFragment$@SuppressLint("NewApi") private fun addAllDayEvent(event: Event) CyclomaticComplexMethod:WeekFragment.kt$WeekFragment$private fun addEvents(events: ArrayList<Event>) @@ -55,7 +55,7 @@ EmptyFunctionBlock:EventListFragment.kt$EventListFragment${} EmptyFunctionBlock:EventListWidgetAdapter.kt$EventListWidgetAdapter${} EmptyFunctionBlock:EventListWidgetAdapterEmpty.kt$EventListWidgetAdapterEmpty${} - EmptyFunctionBlock:ManageEventTypesAdapter.kt$ManageEventTypesAdapter${} + EmptyFunctionBlock:ManageCalendarsAdapter.kt$ManageCalendarsAdapter${} EmptyFunctionBlock:MonthDayFragment.kt$MonthDayFragment${} EmptyFunctionBlock:MonthDayFragmentsHolder.kt$MonthDayFragmentsHolder${} EmptyFunctionBlock:MonthDayFragmentsHolder.kt$MonthDayFragmentsHolder.<no name provided>${} @@ -69,19 +69,20 @@ ForbiddenComment:AutoCompleteTextViewAdapter.kt$AutoCompleteTextViewAdapter$// TODO: Dark text color is set for dynamic theme only because light themes are ImplicitDefaultLocale:SettingsActivity.kt$SettingsActivity$String.format("%02d:00", hours) LargeClass:EventActivity.kt$EventActivity : SimpleActivity + LargeClass:EventsHelper.kt$EventsHelper LargeClass:MainActivity.kt$MainActivity : SimpleActivityRefreshRecyclerViewListener LargeClass:SettingsActivity.kt$SettingsActivity : SimpleActivity LargeClass:TaskActivity.kt$TaskActivity : SimpleActivity LargeClass:WeekFragment.kt$WeekFragment : FragmentWeeklyCalendar - LongMethod:CalDAVHelper.kt$CalDAVHelper$@SuppressLint("MissingPermission") private fun fetchCalDAVCalendarEvents( calendar: CalDAVCalendar, eventTypeId: Long, showToasts: Boolean, ) - LongMethod:EventActivity.kt$EventActivity$private fun gotEvent( savedInstanceState: Bundle?, localEventType: EventType?, event: Event?, ) + LongMethod:CalDAVHelper.kt$CalDAVHelper$@SuppressLint("MissingPermission") private fun fetchCalDAVCalendarEvents( calendar: CalDAVCalendar, localCalendarId: Long, showToasts: Boolean, ) + LongMethod:EventActivity.kt$EventActivity$private fun gotEvent( savedInstanceState: Bundle?, localCalendar: CalendarEntity?, event: Event?, ) LongMethod:EventActivity.kt$EventActivity$private fun saveEvent() - LongMethod:IcsImporter.kt$IcsImporter$fun importEvents( path: String, defaultEventTypeId: Long, calDAVCalendarId: Int, overrideFileEventTypes: Boolean, eventReminders: ArrayList<Int>? = null, loadFromAssets: Boolean = false, ): ImportResult + LongMethod:IcsImporter.kt$IcsImporter$fun importEvents( path: String, defaultCalendarId: Long, calDAVCalendarId: Int, overrideFileCalendars: Boolean, eventReminders: ArrayList<Int>? = null, loadFromAssets: Boolean = false, ): ImportResult LongMethod:MyTimeZones.kt$fun getAllTimeZones() LongMethod:WeekFragment.kt$WeekFragment$private fun addEvents(events: ArrayList<Event>) - LongParameterList:SelectEventTypeDialog.kt$SelectEventTypeDialog$( val activity: Activity, val currEventType: Long, val showCalDAVCalendars: Boolean, val showNewEventTypeOption: Boolean, val addLastUsedOneAsFirstOption: Boolean, val showOnlyWritable: Boolean, var showManageEventTypes: Boolean, val callback: (eventType: EventType) -> Unit ) + LongParameterList:SelectCalendarDialog.kt$SelectCalendarDialog$( val activity: Activity, val currCalendar: Long, val showCalDAVCalendars: Boolean, val showNewCalendarOption: Boolean, val addLastUsedOneAsFirstOption: Boolean, val showOnlyWritable: Boolean, var showManageCalendars: Boolean, val callback: (calendar: CalendarEntity) -> Unit ) LoopWithTooManyJumpStatements:IcsImporter.kt$IcsImporter$while - LoopWithTooManyJumpStatements:ManageEventTypesAdapter.kt$ManageEventTypesAdapter$for + LoopWithTooManyJumpStatements:ManageCalendarsAdapter.kt$ManageCalendarsAdapter$for LoopWithTooManyJumpStatements:WeekFragment.kt$WeekFragment$do MagicNumber:AutomaticBackupReceiver.kt$AutomaticBackupReceiver$3000 MagicNumber:CalDAVCalendar.kt$CalDAVCalendar$500 @@ -181,16 +182,13 @@ MagicNumber:Parser.kt$Parser$6 MagicNumber:Parser.kt$Parser$60 MagicNumber:Parser.kt$Parser$7 - MagicNumber:QuickFilterEventTypeAdapter.kt$QuickFilterEventTypeAdapter.QuickFilterViewHolder$300 + MagicNumber:QuickFilterCalendarAdapter.kt$QuickFilterCalendarAdapter.QuickFilterViewHolder$300 MagicNumber:RepeatLimitTypePickerDialog.kt$RepeatLimitTypePickerDialog$23 MagicNumber:RepeatLimitTypePickerDialog.kt$RepeatLimitTypePickerDialog$59 MagicNumber:RepeatRuleWeeklyDialog.kt$RepeatRuleWeeklyDialog$6 MagicNumber:RepeatRuleWeeklyDialog.kt$RepeatRuleWeeklyDialog$7 - MagicNumber:SelectEventTypeDialog.kt$SelectEventTypeDialog$2L MagicNumber:SetRemindersDialog.kt$SetRemindersDialog$60 MagicNumber:SettingsActivity.kt$SettingsActivity$16 - MagicNumber:SettingsActivity.kt$SettingsActivity$3 - MagicNumber:SettingsActivity.kt$SettingsActivity$4 MagicNumber:SettingsActivity.kt$SettingsActivity$60 MagicNumber:SimpleActivity.kt$SimpleActivity$3000L MagicNumber:SmallMonthView.kt$SmallMonthView$0.41f @@ -255,55 +253,10 @@ MaxLineLength:CalDAVHelper.kt$CalDAVHelper$// store the event in the local db only if it is an occurrence that has been modified and not deleted MaxLineLength:CheckableColorAdapter.kt$CheckableColorAdapter$class MaxLineLength:CheckableColorAdapter.kt$CheckableColorAdapter.CheckableColorViewHolder$inner - MaxLineLength:Config.kt$Config$caldavSyncedCalendarIds.split(",").filter { it.trim().isNotEmpty() }.map { Integer.parseInt(it) }.toMutableList() as ArrayList<Int> - MaxLineLength:Config.kt$Config$get() = prefs.getString(ANNIVERSARY_REMINDERS, REMINDER_DEFAULT_VALUE)!!.split(",").map { it.toInt() }.toMutableList() as ArrayList<Int> - MaxLineLength:Config.kt$Config$get() = prefs.getString(BIRTHDAY_REMINDERS, REMINDER_DEFAULT_VALUE)!!.split(",").map { it.toInt() }.toMutableList() as ArrayList<Int> - MaxLineLength:Config.kt$Config$get() = prefs.getString(REMINDER_SOUND_URI, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION).toString())!! - MaxLineLength:Config.kt$Config$set(addAnniversariesAutomatically) = prefs.edit().putBoolean(ADD_ANNIVERSARIES_AUTOMATICALLY, addAnniversariesAutomatically).apply() - MaxLineLength:Config.kt$Config$set(addBirthdaysAutomatically) = prefs.edit().putBoolean(ADD_BIRTHDAYS_AUTOMATICALLY, addBirthdaysAutomatically).apply() - MaxLineLength:Config.kt$Config$set(anniversaryReminders) = prefs.edit().putString(ANNIVERSARY_REMINDERS, anniversaryReminders.joinToString(",")).apply() - MaxLineLength:Config.kt$Config$set(autoBackupEventTypes) = prefs.edit().remove(AUTO_BACKUP_EVENT_TYPES).putStringSet(AUTO_BACKUP_EVENT_TYPES, autoBackupEventTypes).apply() - MaxLineLength:Config.kt$Config$set(displayEventTypes) = prefs.edit().remove(DISPLAY_EVENT_TYPES).putStringSet(DISPLAY_EVENT_TYPES, displayEventTypes).apply() - MaxLineLength:Config.kt$Config$set(lastEventReminderMinutes) = prefs.edit().putInt(LAST_EVENT_REMINDER_MINUTES, lastEventReminderMinutes).apply() - MaxLineLength:Config.kt$Config$set(lastEventReminderMinutes2) = prefs.edit().putInt(LAST_EVENT_REMINDER_MINUTES_2, lastEventReminderMinutes2).apply() - MaxLineLength:Config.kt$Config$set(lastEventReminderMinutes3) = prefs.edit().putInt(LAST_EVENT_REMINDER_MINUTES_3, lastEventReminderMinutes3).apply() - MaxLineLength:Config.kt$Config$set(lastUsedIgnoreEventTypesState) = prefs.edit().putBoolean(LAST_USED_IGNORE_EVENT_TYPES_STATE, lastUsedIgnoreEventTypesState).apply() - MaxLineLength:Config.kt$Config$set(lastUsedLocalEventTypeId) = prefs.edit().putLong(LAST_USED_LOCAL_EVENT_TYPE_ID, lastUsedLocalEventTypeId).apply() - MaxLineLength:Config.kt$Config$set(lastUsedShowListWidgetHeader) = prefs.edit().putBoolean(LAST_USED_SHOW_LIST_WIDGET_HEADER, lastUsedShowListWidgetHeader).apply() - MaxLineLength:Config.kt$Config$set(quickFilterEventTypes) = prefs.edit().remove(QUICK_FILTER_EVENT_TYPES).putStringSet(QUICK_FILTER_EVENT_TYPES, quickFilterEventTypes).apply() - MaxLineLength:Config.kt$Config$set(startWeekWithCurrentDay) = prefs.edit().putBoolean(START_WEEK_WITH_CURRENT_DAY, startWeekWithCurrentDay).apply() - MaxLineLength:Config.kt$Config$set(usePreviousEventReminders) = prefs.edit().putBoolean(USE_PREVIOUS_EVENT_REMINDERS, usePreviousEventReminders).apply() - MaxLineLength:Config.kt$Config$set(wasFilteredOutWarningShown) = prefs.edit().putBoolean(WAS_FILTERED_OUT_WARNING_SHOWN, wasFilteredOutWarningShown).apply() - MaxLineLength:Config.kt$Config$set(weeklyViewItemHeightMultiplier) = prefs.edit().putFloat(WEEKLY_VIEW_ITEM_HEIGHT_MULTIPLIER, weeklyViewItemHeightMultiplier).apply() MaxLineLength:Constants.kt$4 MaxLineLength:Context.kt$// Assume this is a manual synchronisation when we showToasts to the user (swipe refresh, MainMenu-> refresh caldav calendars, ...) MaxLineLength:Context.kt$// if the default event start time is set to "Next full hour" and the event is created before midnight, it could change the day MaxLineLength:Context.kt$IcsExporter.ExportResult.EXPORT_PARTIAL -> toast(org.fossify.commons.R.string.exporting_some_entries_failed) - MaxLineLength:Context.kt$PendingIntent.getActivity(context, event.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) - MaxLineLength:Context.kt$PendingIntent.getBroadcast(this, id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE).cancel() - MaxLineLength:Context.kt$PendingIntent.getService(context, event.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) - MaxLineLength:Context.kt$addAction(R.drawable.ic_task_vector, getString(R.string.mark_completed), getMarkCompletedPendingIntent(this@getNotification, event)) - MaxLineLength:Context.kt$alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + syncCheckInterval, syncCheckInterval, pendingIntent) - MaxLineLength:Context.kt$arrayOf(currEvent.reminder3Minutes, currEvent.reminder2Minutes, currEvent.reminder1Minutes).filter { it != REMINDER_OFF }.max() - MaxLineLength:Context.kt$eventStartTS = if (currEvent.getIsAllDay()) Formatter.getDayStartTS(Formatter.getDayCodeFromTS(currEvent.startTS)) else currEvent.startTS - MaxLineLength:Context.kt$fun - MaxLineLength:Context.kt$private fun getFormattedEventTime(startTime: String, endTime: String) - MaxLineLength:Context.kt$return PendingIntent.getActivity(context, event.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) - MaxLineLength:Context.kt$return PendingIntent.getBroadcast(this, AUTOMATIC_BACKUP_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) - MaxLineLength:Context.kt$return PendingIntent.getBroadcast(this, event.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) - MaxLineLength:Context.kt$return PendingIntent.getService(context, task.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) - MaxLineLength:Context.kt$seconds % MONTH == 0 -> resources.getQuantityString(org.fossify.commons.R.plurals.months, seconds / MONTH, seconds / MONTH) - MaxLineLength:Context.kt$seconds % WEEK == 0 -> resources.getQuantityString(org.fossify.commons.R.plurals.weeks, seconds / WEEK, seconds / WEEK) - MaxLineLength:Context.kt$seconds % YEAR == 0 -> resources.getQuantityString(org.fossify.commons.R.plurals.years, seconds / YEAR, seconds / YEAR) - MaxLineLength:Context.kt$val - MaxLineLength:Context.kt$val dayBits = withFirstDayOfWeekToFront(listOf(MONDAY_BIT, TUESDAY_BIT, WEDNESDAY_BIT, THURSDAY_BIT, FRIDAY_BIT, SATURDAY_BIT, SUNDAY_BIT)) - MaxLineLength:Context.kt$val eventLayoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) - MaxLineLength:Context.kt$val events = eventsHelper.getRepeatableEventsFor(currentSeconds - WEEK_SECONDS, currentSeconds + YEAR_SECONDS, event.id!!) - MaxLineLength:Context.kt$val msg = String.format(getString(org.fossify.commons.R.string.time_remaining), formatSecondsToTimeString(secondsTillNotification.toInt())) - MaxLineLength:Context.kt$val oldChannelId = "simple_calendar_${config.lastReminderChannel}_${config.reminderAudioStream}_${event.eventType}" - MaxLineLength:Context.kt$val snoozeClass = if (context.config.useSameSnooze) SnoozeService::class.java else SnoozeReminderActivity::class.java - MaxLineLength:Context.kt$val weekDays = withFirstDayOfWeekToFront(resources.getStringArray(org.fossify.commons.R.array.week_days_short).toList()) - MaxLineLength:Context.kt$var eventStartTS = if (event.getIsAllDay()) Formatter.getDayStartTS(Formatter.getDayCodeFromTS(event.startTS)) else event.startTS MaxLineLength:CustomPeriodPickerDialog.kt$CustomPeriodPickerDialog$private MaxLineLength:DayEventsAdapter.kt$DayEventsAdapter$class MaxLineLength:DayEventsAdapter.kt$DayEventsAdapter$eventItemDescription.text = if (replaceDescriptionWithLocation) event.location else event.description.replace("\n", " ") @@ -311,13 +264,8 @@ MaxLineLength:DayEventsAdapter.kt$DayEventsAdapter$val nonRepeatingEventIDs = eventsToDelete.asSequence().filter { it.repeatInterval == 0 }.mapNotNull { it.id }.toMutableList() MaxLineLength:DayEventsAdapter.kt$DayEventsAdapter$val repeatingEventIDs = eventsToDelete.asSequence().filter { it.repeatInterval != 0 }.mapNotNull { it.id }.toList() MaxLineLength:DayFragment.kt$DayFragment$val - MaxLineLength:EditEventTypeDialog.kt$EditEventTypeDialog$activity - MaxLineLength:EditEventTypeDialog.kt$EditEventTypeDialog$class MaxLineLength:EditRepeatingEventDialog.kt$EditRepeatingEventDialog$class MaxLineLength:Event.kt$Event$// if an event should happen on 31st with Same Day monthly repetition, dont show it at all at months with 30 or less days - MaxLineLength:Event.kt$Event$fun getCalDAVCalendarId() - MaxLineLength:Event.kt$Event$wantedDay = properMonth.dayOfMonth + ((properMonth.dayOfMonth().maximumValue - properMonth.dayOfMonth) / 7) * 7 - MaxLineLength:Event.kt$Event$while MaxLineLength:EventActivity.kt$EventActivity$if MaxLineLength:EventListAdapter.kt$EventListAdapter$activity: SimpleActivity MaxLineLength:EventListAdapter.kt$EventListAdapter$eventItemDescription.text = if (replaceDescription) listEvent.location else listEvent.description.replace("\n", " ") @@ -326,38 +274,22 @@ MaxLineLength:EventListAdapter.kt$EventListAdapter$if MaxLineLength:EventListAdapter.kt$EventListAdapter$listItems.filter { it is ListEvent && selectedKeys.contains(it.hashCode()) }.map { (it as ListEvent).id }.toMutableList() as ArrayList<Long> MaxLineLength:EventListAdapter.kt$EventListAdapter$val eventsToDelete = listItems.filter { selectedKeys.contains((it as? ListEvent)?.hashCode()) } as List<ListEvent> - MaxLineLength:EventListFragment.kt$EventListFragment$(binding.calendarEventsList.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(firstNonPastSectionIndex, 0) - MaxLineLength:EventListFragment.kt$EventListFragment$binding.calendarEventsList.smoothScrollBy(0, requireContext().resources.getDimension(R.dimen.endless_scroll_move_height).toInt()) - MaxLineLength:EventListFragment.kt$EventListFragment$val lastPosition = (binding.calendarEventsList.layoutManager as MyLinearLayoutManager).findLastVisibleItemPosition() MaxLineLength:EventListWidgetAdapter.kt$EventListWidgetAdapter$if MaxLineLength:EventListWidgetAdapter.kt$EventListWidgetAdapter$} MaxLineLength:EventsDao.kt$EventsDao$//val selection = "$COL_REMINDER_MINUTES != -1 AND ($COL_START_TS > ? OR $COL_REPEAT_INTERVAL != 0) AND $COL_START_TS != 0" MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE reminder_1_minutes != -1 AND (start_ts > :currentTS OR repeat_interval != 0) AND start_ts != 0") - MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts <= :toTS AND end_ts >= :fromTS AND start_ts != 0 AND repeat_interval = 0 AND event_type IN (:eventTypeIds) AND (title LIKE :searchQuery OR location LIKE :searchQuery OR description LIKE :searchQuery)") - MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts <= :toTS AND end_ts >= :fromTS AND start_ts != 0 AND repeat_interval = 0 AND event_type IN (:eventTypeIds)") - MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts <= :toTS AND start_ts != 0 AND repeat_interval != 0 AND event_type IN (:eventTypeIds) AND (title LIKE :searchQuery OR location LIKE :searchQuery OR description LIKE :searchQuery)") - MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts <= :toTS AND start_ts != 0 AND repeat_interval != 0 AND event_type IN (:eventTypeIds)") - MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts <= :toTS AND start_ts >= :fromTS AND event_type IN (:eventTypeIds) AND type = $TYPE_TASK") - MaxLineLength:EventsDao.kt$EventsDao$fun + MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts <= :toTS AND end_ts >= :fromTS AND start_ts != 0 AND repeat_interval = 0 AND event_type IN (:calendarIds) AND (title LIKE :searchQuery OR location LIKE :searchQuery OR description LIKE :searchQuery)") + MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts <= :toTS AND end_ts >= :fromTS AND start_ts != 0 AND repeat_interval = 0 AND event_type IN (:calendarIds)") + MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts <= :toTS AND start_ts != 0 AND repeat_interval != 0 AND event_type IN (:calendarIds) AND (title LIKE :searchQuery OR location LIKE :searchQuery OR description LIKE :searchQuery)") + MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts <= :toTS AND start_ts != 0 AND repeat_interval != 0 AND event_type IN (:calendarIds)") + MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts <= :toTS AND start_ts >= :fromTS AND event_type IN (:calendarIds) AND type = $TYPE_TASK") MaxLineLength:EventsDatabase.kt$EventsDatabase.Companion.<no name provided>$execSQL("CREATE TABLE IF NOT EXISTS `tasks` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `task_id` INTEGER NOT NULL, `start_ts` INTEGER NOT NULL, `flags` INTEGER NOT NULL)") MaxLineLength:EventsDatabase.kt$EventsDatabase.Companion.<no name provided>$execSQL("CREATE TABLE IF NOT EXISTS `widgets` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `widget_id` INTEGER NOT NULL, `period` INTEGER NOT NULL)") MaxLineLength:EventsDatabase.kt$EventsDatabase.Companion.<no name provided>$execSQL("CREATE TABLE `tasks` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `task_id` INTEGER NOT NULL, `start_ts` INTEGER NOT NULL, `flags` INTEGER NOT NULL, CONSTRAINT fk_task_id FOREIGN KEY (task_id) REFERENCES events(id) ON DELETE CASCADE)") - MaxLineLength:EventsHelper.kt$EventsHelper$eventTypeId = createPredefinedEventType(anniversaries, R.color.default_anniversaries_color, ANNIVERSARY_EVENT) - MaxLineLength:EventsHelper.kt$EventsHelper$events.addAll(eventsDB.getOneTimeEventsFromToWithTypes(toTS, fromTS, typesList).toMutableList() as ArrayList<Event>) - MaxLineLength:EventsHelper.kt$EventsHelper$eventsDB.getOneTimeEventsFromToWithTypesForSearch(toTS, fromTS, typesList, "%$searchQuery%").toMutableList() as ArrayList<Event> - MaxLineLength:EventsHelper.kt$EventsHelper$eventsDB.getRepeatableEventsOrTasksWithTypes(toTS, context.config.getDisplayEventTypessAsList()).toMutableList() as ArrayList<Event> - MaxLineLength:EventsHelper.kt$EventsHelper$eventsDB.getRepeatableEventsOrTasksWithTypesForSearch(toTS, context.config.getDisplayEventTypessAsList(), "%$searchQuery%") - MaxLineLength:EventsHelper.kt$EventsHelper$fun MaxLineLength:EventsHelper.kt$EventsHelper$if - MaxLineLength:EventsHelper.kt$EventsHelper$it.caldavCalendarId == 0 || caldavCalendars.firstOrNull { it.id == eventType.caldavCalendarId }?.canWrite() == true - MaxLineLength:EventsHelper.kt$EventsHelper$private - MaxLineLength:EventsHelper.kt$EventsHelper$val previousOccurrenceTS = occurrenceTS - event.repeatInterval // always update repeat limit of the occurrence preceding the one being edited - MaxLineLength:EventsHelper.kt$EventsHelper$val typesToDelete = eventTypes.asSequence().filter { it.caldavCalendarId == 0 && it.id != REGULAR_EVENT_TYPE_ID }.toMutableList() + MaxLineLength:EventsHelper.kt$EventsHelper$occurrenceTS - event.repeatInterval + MaxLineLength:ExportEventsDialog.kt$ExportEventsDialog$(binding.exportEventsTypesList.adapter as FilterCalendarAdapter).getSelectedItemsList() MaxLineLength:ExportEventsDialog.kt$ExportEventsDialog$exportEventsFilename.setText("${activity.getString(R.string.events)}_${activity.getCurrentFormattedDateTime()}") - MaxLineLength:ExportEventsDialog.kt$ExportEventsDialog$val eventTypes = (binding.exportEventsTypesList.adapter as FilterEventTypeAdapter).getSelectedItemsList() - MaxLineLength:FilterEventTypeAdapter.kt$FilterEventTypeAdapter$class - MaxLineLength:FilterEventTypeAdapter.kt$FilterEventTypeAdapter$override fun onBindViewHolder(holder: EventTypeViewHolder, position: Int) - MaxLineLength:FilterEventTypeAdapter.kt$FilterEventTypeAdapter.EventTypeViewHolder$filterEventTypeCheckbox.setColors(activity.getProperTextColor(), activity.getProperPrimaryColor(), activity.getProperBackgroundColor()) MaxLineLength:Formatter.kt$Formatter$DateTimeFormat.forPattern(DAYCODE_PATTERN).withZone(DateTimeZone.getDefault()).parseLocalDate(dayCode).toDateTimeAtStartOfDay() MaxLineLength:Formatter.kt$Formatter$fun MaxLineLength:Formatter.kt$Formatter$fun getDate(context: Context, dateTime: DateTime, addDayOfWeek: Boolean = true) @@ -371,39 +303,11 @@ MaxLineLength:IcsImporter.kt$IcsImporter$// if an event contains the RECURRENCE-ID field, it is an exception to a recurring event, so update its parent too MaxLineLength:IcsImporter.kt$IcsImporter$// repeating event exceptions can have the same import id as their parents, so pick the latest event to update MaxLineLength:IcsImporter.kt$IcsImporter$// some RRULEs need to know the events start datetime. If it's yet unknown, postpone RRULE parsing - MaxLineLength:IcsImporter.kt$IcsImporter$Reminder(curReminderMinutes.getOrElse(0) { REMINDER_OFF }, curReminderActions.getOrElse(0) { REMINDER_NOTIFICATION }) - MaxLineLength:IcsImporter.kt$IcsImporter$Reminder(curReminderMinutes.getOrElse(1) { REMINDER_OFF }, curReminderActions.getOrElse(1) { REMINDER_NOTIFICATION }) - MaxLineLength:IcsImporter.kt$IcsImporter$Reminder(curReminderMinutes.getOrElse(2) { REMINDER_OFF }, curReminderActions.getOrElse(2) { REMINDER_NOTIFICATION }) - MaxLineLength:IcsImporter.kt$IcsImporter$if - MaxLineLength:IcsImporter.kt$IcsImporter$line.substring(TRANSP.length).let { curAvailability = if (it == TRANSPARENT) Events.AVAILABILITY_FREE else Events.AVAILABILITY_BUSY } - MaxLineLength:IcsImporter.kt$IcsImporter$reminders = reminders.sortedBy { it.minutes }.sortedBy { it.minutes == REMINDER_OFF }.toMutableList() as ArrayList<Reminder> - MaxLineLength:IcsImporter.kt$IcsImporter$val eventToUpdate = existingEvents.filter { curImportId.isNotEmpty() && curImportId == it.importId }.maxByOrNull { it.lastUpdated } - MaxLineLength:IcsImporter.kt$IcsImporter$val source = if (calDAVCalendarId == 0 || eventType?.isSyncedEventType() == false) SOURCE_IMPORTED_ICS else "$CALDAV-$calDAVCalendarId" - MaxLineLength:IcsImporter.kt$IcsImporter$var - MaxLineLength:ImportEventsDialog.kt$ImportEventsDialog$val isLastCaldavCalendarOK = config.caldavSync && config.getSyncedCalendarIdsAsList().contains(config.lastUsedCaldavCalendarId) - MaxLineLength:ImportEventsDialog.kt$ImportEventsDialog$val lastUsedCalDAVCalendar = activity.eventsHelper.getEventTypeWithCalDAVCalendarId(config.lastUsedCaldavCalendarId) - MaxLineLength:ImportEventsDialog.kt$ImportEventsDialog$val result = IcsImporter(activity).importEvents(path, currEventTypeId, currEventTypeCalDAVCalendarId, overrideFileEventTypes) + MaxLineLength:IcsImporter.kt$IcsImporter$if (calDAVCalendarId == 0 || calendar?.isSyncedCalendar() == false) SOURCE_IMPORTED_ICS else "$CALDAV-$calDAVCalendarId" MaxLineLength:ListSectionDay.kt$ListSectionDay : ListItem - MaxLineLength:MainActivity.kt$MainActivity$(newEventDrawable as LayerDrawable).findDrawableByLayerId(R.id.shortcut_event_background).applyColorFilter(appIconColor) - MaxLineLength:MainActivity.kt$MainActivity$(newTaskDrawable as LayerDrawable).findDrawableByLayerId(R.id.shortcut_task_background).applyColorFilter(appIconColor) MaxLineLength:MainActivity.kt$MainActivity$// private contacts are created in Simple Contacts Pro, so we can guarantee that they exist only in these 2 formats - MaxLineLength:MainActivity.kt$MainActivity$binding.searchResultsList.smoothScrollBy(0, resources.getDimension(R.dimen.endless_scroll_move_height).toInt()) - MaxLineLength:MainActivity.kt$MainActivity$binding.swipeRefreshLayout.isEnabled = config.caldavSync && config.pullToRefresh && config.storedView != WEEKLY_VIEW - MaxLineLength:MainActivity.kt$MainActivity$faqItems.add(FAQItem(org.fossify.commons.R.string.faq_2_title_commons, org.fossify.commons.R.string.faq_2_text_commons)) - MaxLineLength:MainActivity.kt$MainActivity$faqItems.add(FAQItem(org.fossify.commons.R.string.faq_6_title_commons, org.fossify.commons.R.string.faq_6_text_commons)) - MaxLineLength:MainActivity.kt$MainActivity$faqItems.add(FAQItem(org.fossify.commons.R.string.faq_7_title_commons, org.fossify.commons.R.string.faq_7_text_commons)) - MaxLineLength:MainActivity.kt$MainActivity$findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations) MaxLineLength:MainActivity.kt$MainActivity$if - MaxLineLength:MainActivity.kt$MainActivity$it.title.contains(currentSearchQuery, true) || it.location.contains(currentSearchQuery, true) - MaxLineLength:MainActivity.kt$MainActivity$null - MaxLineLength:MainActivity.kt$MainActivity$private - MaxLineLength:MainActivity.kt$MainActivity$reminder3Minutes = reminders[2] - MaxLineLength:MainActivity.kt$MainActivity$repeatInterval = YEAR - MaxLineLength:MainActivity.kt$MainActivity$val eventTypeId = if (birthdays) eventsHelper.getLocalBirthdaysEventTypeId() else eventsHelper.getAnniversariesEventTypeId() - MaxLineLength:MainActivity.kt$MainActivity$val lastPosition = (binding.searchResultsList.layoutManager as MyLinearLayoutManager).findLastVisibleItemPosition() MaxLineLength:MainActivity.kt$MainActivity$|| - MaxLineLength:ManageAutomaticBackupsDialog.kt$ManageAutomaticBackupsDialog$activity - MaxLineLength:ManageEventTypesAdapter.kt$ManageEventTypesAdapter$activity: SimpleActivity MaxLineLength:MonthDayFragment.kt$MonthDayFragment$binding.monthDaySelectedDayLabel.text = Formatter.getDateFromCode(requireActivity(), mSelectedDayCode, false) MaxLineLength:MonthDayFragment.kt$MonthDayFragment$override MaxLineLength:MonthDayFragment.kt$MonthDayFragment$shownMonthDateTime.year == startDateTime.year && shownMonthDateTime.monthOfYear == startDateTime.monthOfYear @@ -447,61 +351,23 @@ MaxLineLength:ReminderWarningDialog.kt$ReminderWarningDialog$activity MaxLineLength:RepeatLimitTypePickerDialog.kt$RepeatLimitTypePickerDialog$class MaxLineLength:RepeatLimitTypePickerDialog.kt$RepeatLimitTypePickerDialog$private - MaxLineLength:SelectCalendarsDialog.kt$SelectCalendarsDialog$CalendarItemAccountBinding.inflate(activity.layoutInflater, binding.dialogSelectCalendarsHolder, false) - MaxLineLength:SelectCalendarsDialog.kt$SelectCalendarsDialog$CalendarItemCalendarBinding.inflate(activity.layoutInflater, binding.dialogSelectCalendarsHolder, false) - MaxLineLength:SelectEventCalendarDialog.kt$SelectEventCalendarDialog$class - MaxLineLength:SelectEventCalendarDialog.kt$SelectEventCalendarDialog$radioGroup.addView(radioBinding.root, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)) MaxLineLength:SelectEventColorDialog.kt$SelectEventColorDialog$class - MaxLineLength:SelectEventTypeColorDialog.kt$SelectEventTypeColorDialog$class - MaxLineLength:SelectEventTypeDialog.kt$SelectEventTypeDialog$radioGroup.addView(radioBinding.root, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)) - MaxLineLength:SelectEventTypeDialog.kt$SelectEventTypeDialog$val activity: Activity - MaxLineLength:SelectEventTypeDialog.kt$SelectEventTypeDialog$val addLastUsedOneAsFirstOption: Boolean - MaxLineLength:SelectEventTypeDialog.kt$SelectEventTypeDialog$val lastUsedEventType = EventType(LAST_USED_EVENT_TYPE_ID, activity.getString(R.string.last_used_one), Color.TRANSPARENT, 0) - MaxLineLength:SelectEventTypeDialog.kt$SelectEventTypeDialog$val newEventType = EventType(NEW_EVENT_TYPE_ID, activity.getString(R.string.add_new_type), Color.TRANSPARENT, 0) - MaxLineLength:SelectEventTypesDialog.kt$SelectEventTypesDialog$class MaxLineLength:SelectTimeZoneAdapter.kt$SelectTimeZoneAdapter$class - MaxLineLength:SetRemindersDialog.kt$SetRemindersDialog$class - MaxLineLength:SetRemindersDialog.kt$SetRemindersDialog$val tempReminders = arrayListOf(mReminder1Minutes, mReminder2Minutes, mReminder3Minutes).filter { it != REMINDER_OFF }.sorted() MaxLineLength:SettingsActivity.kt$SettingsActivity$IcsExporter.ExportResult.EXPORT_PARTIAL -> org.fossify.commons.R.string.exporting_some_entries_failed - MaxLineLength:SettingsActivity.kt$SettingsActivity$PermissionRequiredDialog(this, org.fossify.commons.R.string.allow_notifications_reminders, { openNotificationSettings() }) - MaxLineLength:SettingsActivity.kt$SettingsActivity$arrayOf(settingsDefaultReminder1Holder, settingsDefaultReminder2Holder, settingsDefaultReminder3Holder) MaxLineLength:SettingsActivity.kt$SettingsActivity$settingsUseEnglishHolder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") && !isTiramisuPlus()) - MaxLineLength:SettingsActivity.kt$SettingsActivity$val eventType = EventType(null, it.displayName, it.color, it.id, it.displayName, it.accountName) - MaxLineLength:SettingsActivity.kt$SettingsActivity$val events = eventsHelper.getEventsToExport(eventTypes, config.exportEvents, config.exportTasks, config.exportPastEntries) - MaxLineLength:SettingsActivity.kt$SettingsActivity$val reminders = sortedSetOf(config.defaultReminder1, config.defaultReminder2, config.defaultReminder3).filter { it != REMINDER_OFF } MaxLineLength:SettingsActivity.kt$SettingsActivity$} MaxLineLength:SimpleActivity.kt$SimpleActivity$// caldav refresh content observer triggers multiple times in a row at updating, so call the callback only a few seconds after the (hopefully) last one MaxLineLength:TaskActivity.kt$TaskActivity$// the stored value might be incorrect so update it (e.g. user completed the task via notification action before editing) - MaxLineLength:TaskActivity.kt$TaskActivity$ColorPickerDialog - MaxLineLength:TaskActivity.kt$TaskActivity$DELETE_SELECTED_OCCURRENCE -> eventsHelper.deleteRepeatingEventOccurrence(mTask.id!!, mTaskOccurrenceTS, false) - MaxLineLength:TaskActivity.kt$TaskActivity$PermissionRequiredDialog(this, org.fossify.commons.R.string.allow_notifications_reminders, { openNotificationSettings() }) MaxLineLength:TaskActivity.kt$TaskActivity$binding.taskRepetitionRuleHolder.beVisibleIf(mRepeatInterval.isXWeeklyRepetition() || mRepeatInterval.isXMonthlyRepetition() || mRepeatInterval.isXYearlyRepetition()) MaxLineLength:TaskActivity.kt$TaskActivity$if - MaxLineLength:TaskActivity.kt$TaskActivity$items.add(RadioItem(REPEAT_ORDER_WEEKDAY_USE_LAST, getRepeatXthDayInMonthString(true, REPEAT_ORDER_WEEKDAY_USE_LAST))) - MaxLineLength:TaskActivity.kt$TaskActivity$items.add(RadioItem(REPEAT_ORDER_WEEKDAY_USE_LAST, getRepeatXthDayString(true, REPEAT_ORDER_WEEKDAY_USE_LAST))) - MaxLineLength:TaskActivity.kt$TaskActivity$mEventTypeId = if (config.defaultEventTypeId == -1L) config.lastUsedLocalEventTypeId else config.defaultEventTypeId - MaxLineLength:TaskActivity.kt$TaskActivity$mReminder1Minutes = if (usePreviousEventReminders && lastEventReminderMinutes1 >= -1) lastEventReminderMinutes1 else defaultReminder1 - MaxLineLength:TaskActivity.kt$TaskActivity$mReminder2Minutes = if (usePreviousEventReminders && lastEventReminderMinutes2 >= -1) lastEventReminderMinutes2 else defaultReminder2 - MaxLineLength:TaskActivity.kt$TaskActivity$mReminder3Minutes = if (usePreviousEventReminders && lastEventReminderMinutes3 >= -1) lastEventReminderMinutes3 else defaultReminder3 - MaxLineLength:TaskActivity.kt$TaskActivity$private fun isLastDayOfTheMonth() - MaxLineLength:TaskActivity.kt$TaskActivity$reminders = reminders.filter { it.minutes != REMINDER_OFF }.sortedBy { it.minutes }.toMutableList() as ArrayList<Reminder> - MaxLineLength:TaskActivity.kt$TaskActivity$this - MaxLineLength:TaskActivity.kt$TaskActivity$val - MaxLineLength:TaskActivity.kt$TaskActivity$val everyString = getString(if (isMaleGender(mTaskDateTime.dayOfWeek)) R.string.every_m else R.string.every_f) + MaxLineLength:TaskActivity.kt$TaskActivity$if (usePreviousEventReminders && lastEventReminderMinutes1 >= -1) lastEventReminderMinutes1 else defaultReminder1 + MaxLineLength:TaskActivity.kt$TaskActivity$if (usePreviousEventReminders && lastEventReminderMinutes2 >= -1) lastEventReminderMinutes2 else defaultReminder2 + MaxLineLength:TaskActivity.kt$TaskActivity$if (usePreviousEventReminders && lastEventReminderMinutes3 >= -1) lastEventReminderMinutes3 else defaultReminder3 MaxLineLength:WeekFragment.kt$WeekFragment$((currentEventWeeklyView.range.upper - currentEventWeeklyView.range.lower) * minuteHeight).toInt() - 1 MaxLineLength:WeekFragment.kt$WeekFragment$// fix a visual glitch with all-day events or events lasting multiple days starting at midnight on monday, being shown the previous week too MaxLineLength:WeekFragment.kt$WeekFragment$// we need to refresh all fragments because they can contain future occurrences - MaxLineLength:WeekFragment.kt$WeekFragment$DragEvent.ACTION_DRAG_STARTED -> dragEvent.clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN) - MaxLineLength:WeekFragment.kt$WeekFragment$compareBy<Event> { it.startTS }.thenBy { it.endTS }.thenBy { it.title }.thenBy { if (replaceDescription) it.location else it.description } - MaxLineLength:WeekFragment.kt$WeekFragment$context?.eventsHelper + MaxLineLength:WeekFragment.kt$WeekFragment$dayColumns.indexOfFirst { it.tag.toInt() == dayCodeStart || it.tag.toInt() in (dayCodeStart + 1)..dayCodeEnd } MaxLineLength:WeekFragment.kt$WeekFragment$eventWeeklyView.range.upper > eventWeeklyViewToCheck.range.lower - MaxLineLength:WeekFragment.kt$WeekFragment$scrollView.layoutParams.height = fullHeight - res.getDimension(org.fossify.commons.R.dimen.one_dp).toInt() - MaxLineLength:WeekFragment.kt$WeekFragment$val (eventId, originalStartTS, originalEndTS) = dragEvent.clipData.getItemAt(0).text.toString().split(";").map { it.toLong() } - MaxLineLength:WeekFragment.kt$WeekFragment$val clipData = ClipData.newPlainText(WEEKLY_EVENT_ID_LABEL, "${event.id};${event.startTS};${event.endTS}") - MaxLineLength:WeekFragment.kt$WeekFragment$val dayOfWeek = dayColumns.indexOfFirst { it.tag.toInt() == dayCodeStart || it.tag.toInt() in (dayCodeStart + 1)..dayCodeEnd } - MaxLineLength:WeekFragment.kt$WeekFragment$val isRowValidForEvent = lastEvent == null || firstEventRowIdx!! + repeatingEventIndex == index && lastEventRowIdx!! < index - MaxLineLength:WeekFragment.kt$WeekFragment$val isStartTimeDay = Formatter.getDateTimeFromTS(maxTS) == Formatter.getDateTimeFromTS(maxTS).withTimeAtStartOfDay() - MaxLineLength:WeekFragment.kt$WeekFragment$val numDays = Days.daysBetween(Formatter.getDateTimeFromTS(minTS).toLocalDate(), Formatter.getDateTimeFromTS(maxTS).toLocalDate()).days MaxLineLength:WeekFragmentsHolder.kt$WeekFragmentsHolder$binding.weekViewDaysCount.text = requireContext().resources.getQuantityString(org.fossify.commons.R.plurals.days, cnt, cnt) MaxLineLength:WidgetDateConfigureActivity.kt$WidgetDateConfigureActivity$if MaxLineLength:WidgetListConfigureActivity.kt$WidgetListConfigureActivity$EventListAdapter(this@WidgetListConfigureActivity, getListItems(), false, null, configWidgetPreview.configEventsList) {} @@ -518,13 +384,13 @@ NestedBlockDepth:CalDAVHelper.kt$CalDAVHelper$fun refreshCalendars(showToasts: Boolean, scheduleNextSync: Boolean, callback: () -> Unit) NestedBlockDepth:Context.kt$inline fun Context.queryCursorInlined( uri: Uri, projection: Array<String>, selection: String? = null, selectionArgs: Array<String>? = null, sortOrder: String? = null, showErrors: Boolean = false, callback: (cursor: Cursor) -> Unit ) NestedBlockDepth:DayEventsAdapter.kt$DayEventsAdapter$private fun setupView(view: View, event: Event) - NestedBlockDepth:EventActivity.kt$EventActivity$private fun gotEvent( savedInstanceState: Bundle?, localEventType: EventType?, event: Event?, ) + NestedBlockDepth:EventActivity.kt$EventActivity$private fun gotEvent( savedInstanceState: Bundle?, localCalendar: CalendarEntity?, event: Event?, ) NestedBlockDepth:EventsHelper.kt$EventsHelper$fun getEventsSync( fromTS: Long, toTS: Long, eventId: Long = -1L, applyTypeFilter: Boolean, searchQuery: String = "", callback: (events: ArrayList<Event>) -> Unit ) - NestedBlockDepth:EventsHelper.kt$EventsHelper$fun insertOrUpdateEventTypeSync(eventType: EventType): Long - NestedBlockDepth:EventsHelper.kt$EventsHelper$private fun getEventsRepeatingTillDateOrForever(fromTS: Long, toTS: Long, startTimes: LongSparseArray<Long>, event: Event): ArrayList<Event> - NestedBlockDepth:EventsHelper.kt$EventsHelper$private fun getEventsRepeatingXTimes(fromTS: Long, toTS: Long, startTimes: LongSparseArray<Long>, event: Event): ArrayList<Event> + NestedBlockDepth:EventsHelper.kt$EventsHelper$fun insertOrUpdateCalendarSync(calendar: CalendarEntity): Long + NestedBlockDepth:EventsHelper.kt$EventsHelper$private fun getEventsRepeatingTillDateOrForever( fromTS: Long, toTS: Long, startTimes: LongSparseArray<Long>, event: Event ): ArrayList<Event> + NestedBlockDepth:EventsHelper.kt$EventsHelper$private fun getEventsRepeatingXTimes( fromTS: Long, toTS: Long, startTimes: LongSparseArray<Long>, event: Event ): ArrayList<Event> NestedBlockDepth:IcsExporter.kt$IcsExporter$private fun fillReminders(event: Event, out: BufferedWriter, reminderLabel: String) - NestedBlockDepth:IcsImporter.kt$IcsImporter$fun importEvents( path: String, defaultEventTypeId: Long, calDAVCalendarId: Int, overrideFileEventTypes: Boolean, eventReminders: ArrayList<Int>? = null, loadFromAssets: Boolean = false, ): ImportResult + NestedBlockDepth:IcsImporter.kt$IcsImporter$fun importEvents( path: String, defaultCalendarId: Long, calDAVCalendarId: Int, overrideFileCalendars: Boolean, eventReminders: ArrayList<Int>? = null, loadFromAssets: Boolean = false, ): ImportResult NestedBlockDepth:IcsImporter.kt$IcsImporter$private fun getTimestamp(fullString: String): Long NestedBlockDepth:MainActivity.kt$MainActivity$private fun addPrivateEvents( birthdays: Boolean, contacts: ArrayList<SimpleContact>, reminders: ArrayList<Int>, callback: (eventsFound: Int, eventsAdded: Int) -> Unit ) NestedBlockDepth:MainActivity.kt$MainActivity$private fun checkIsViewIntent() @@ -568,7 +434,7 @@ TooManyFunctions:EventsHelper.kt$EventsHelper TooManyFunctions:Formatter.kt$Formatter TooManyFunctions:MainActivity.kt$MainActivity : SimpleActivityRefreshRecyclerViewListener - TooManyFunctions:ManageEventTypesAdapter.kt$ManageEventTypesAdapter : MyRecyclerViewAdapter + TooManyFunctions:ManageCalendarsAdapter.kt$ManageCalendarsAdapter : MyRecyclerViewAdapter TooManyFunctions:MonthDayFragment.kt$MonthDayFragment : FragmentMonthlyCalendarRefreshRecyclerViewListener TooManyFunctions:MonthDayFragmentsHolder.kt$MonthDayFragmentsHolder : MyFragmentHolderNavigationListener TooManyFunctions:MonthFragmentsHolder.kt$MonthFragmentsHolder : MyFragmentHolderNavigationListener @@ -583,17 +449,17 @@ TooManyFunctions:WidgetMonthlyConfigureActivity.kt$WidgetMonthlyConfigureActivity : SimpleActivityMonthlyCalendar TooManyFunctions:YearFragmentsHolder.kt$YearFragmentsHolder : MyFragmentHolderNavigationListener UnusedPrivateProperty:YearlyCalendarImpl.kt$YearlyCalendarImpl$i + VariableNaming:CalendarPickerActivity.kt$CalendarPickerActivity$private val TYPE_EVENT = 0 + VariableNaming:CalendarPickerActivity.kt$CalendarPickerActivity$private val TYPE_TASK = 1 VariableNaming:DayFragmentsHolder.kt$DayFragmentsHolder$private val PREFILLED_DAYS = 251 VariableNaming:EventActivity.kt$EventActivity$private val LAT_LON_PATTERN = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)([,;])\\s*[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)\$" VariableNaming:EventActivity.kt$EventActivity$private val SELECT_TIME_ZONE_INTENT = 1 VariableNaming:EventListWidgetAdapter.kt$EventListWidgetAdapter$private val ITEM_EVENT = 0 VariableNaming:EventListWidgetAdapter.kt$EventListWidgetAdapter$private val ITEM_SECTION_DAY = 1 VariableNaming:EventListWidgetAdapter.kt$EventListWidgetAdapter$private val ITEM_SECTION_MONTH = 2 - VariableNaming:EventTypePickerActivity.kt$EventTypePickerActivity$private val TYPE_EVENT = 0 - VariableNaming:EventTypePickerActivity.kt$EventTypePickerActivity$private val TYPE_TASK = 1 VariableNaming:IcsExporter.kt$IcsExporter$private val MAX_LINE_LENGTH = 75 - VariableNaming:ManageEventTypesAdapter.kt$ManageEventTypesAdapter$private val DELETE_EVENTS = 1 - VariableNaming:ManageEventTypesAdapter.kt$ManageEventTypesAdapter$private val MOVE_EVENTS = 0 + VariableNaming:ManageCalendarsAdapter.kt$ManageCalendarsAdapter$private val DELETE_EVENTS = 1 + VariableNaming:ManageCalendarsAdapter.kt$ManageCalendarsAdapter$private val MOVE_EVENTS = 0 VariableNaming:MonthDayFragmentsHolder.kt$MonthDayFragmentsHolder$private val PREFILLED_MONTHS = 251 VariableNaming:MonthFragmentsHolder.kt$MonthFragmentsHolder$private val PREFILLED_MONTHS = 251 VariableNaming:MonthlyCalendarImpl.kt$MonthlyCalendarImpl$private val DAYS_CNT = 42 @@ -606,12 +472,6 @@ VariableNaming:MyWidgetMonthlyProvider.kt$MyWidgetMonthlyProvider$private val NEW_EVENT = "new_event" VariableNaming:MyWidgetMonthlyProvider.kt$MyWidgetMonthlyProvider$private val NEXT = "next" VariableNaming:MyWidgetMonthlyProvider.kt$MyWidgetMonthlyProvider$private val PREV = "prev" - VariableNaming:SelectEventTypeDialog.kt$SelectEventTypeDialog$private val LAST_USED_EVENT_TYPE_ID = -1L - VariableNaming:SelectEventTypeDialog.kt$SelectEventTypeDialog$private val NEW_EVENT_TYPE_ID = -2L - VariableNaming:SettingsActivity.kt$SettingsActivity$private val GET_RINGTONE_URI = 1 - VariableNaming:SettingsActivity.kt$SettingsActivity$private val PICK_EVENTS_EXPORT_FILE_INTENT = 4 - VariableNaming:SettingsActivity.kt$SettingsActivity$private val PICK_EVENTS_IMPORT_SOURCE_INTENT = 3 - VariableNaming:SettingsActivity.kt$SettingsActivity$private val PICK_SETTINGS_IMPORT_SOURCE_INTENT = 2 VariableNaming:SimpleActivity.kt$SimpleActivity$val CALDAV_REFRESH_DELAY = 3000L VariableNaming:WeekFragment.kt$WeekFragment$private val MAX_SCALE_FACTOR = 5f VariableNaming:WeekFragment.kt$WeekFragment$private val MIN_SCALE_DIFFERENCE = 0.02f @@ -630,25 +490,12 @@ WildcardImport:DayEventsAdapter.kt$import org.fossify.calendar.extensions.* WildcardImport:DayFragment.kt$import org.fossify.calendar.helpers.* WildcardImport:DayFragment.kt$import org.fossify.commons.extensions.* - WildcardImport:EditEventTypeDialog.kt$import org.fossify.commons.extensions.* - WildcardImport:Event.kt$import org.fossify.calendar.helpers.* WildcardImport:EventListAdapter.kt$import org.fossify.calendar.extensions.* WildcardImport:EventListAdapter.kt$import org.fossify.calendar.helpers.* - WildcardImport:EventListFragment.kt$import org.fossify.calendar.extensions.* - WildcardImport:EventListFragment.kt$import org.fossify.calendar.helpers.* - WildcardImport:EventListFragment.kt$import org.fossify.commons.extensions.* WildcardImport:EventListWidgetAdapter.kt$import org.fossify.calendar.extensions.* WildcardImport:EventListWidgetAdapter.kt$import org.fossify.calendar.helpers.* WildcardImport:EventListWidgetAdapter.kt$import org.fossify.calendar.models.* WildcardImport:EventListWidgetAdapter.kt$import org.fossify.commons.extensions.* - WildcardImport:EventTypesDao.kt$import androidx.room.* - WildcardImport:EventsDao.kt$import org.fossify.calendar.helpers.* - WildcardImport:EventsHelper.kt$import org.fossify.calendar.extensions.* - WildcardImport:ExportEventsDialog.kt$import org.fossify.commons.extensions.* - WildcardImport:ImportEventsDialog.kt$import org.fossify.commons.extensions.* - WildcardImport:ManageAutomaticBackupsDialog.kt$import org.fossify.commons.extensions.* - WildcardImport:ManageEventTypesAdapter.kt$import android.view.* - WildcardImport:ManageEventTypesAdapter.kt$import org.fossify.commons.extensions.* WildcardImport:MonthDayFragment.kt$import org.fossify.calendar.extensions.* WildcardImport:MonthView.kt$import android.graphics.* WildcardImport:MonthView.kt$import org.fossify.calendar.extensions.* @@ -659,27 +506,7 @@ WildcardImport:Parser.kt$import org.fossify.commons.helpers.* WildcardImport:ReminderWarningDialog.kt$import org.fossify.commons.extensions.* WildcardImport:RepeatLimitTypePickerDialog.kt$import org.fossify.commons.extensions.* - WildcardImport:SelectEventCalendarDialog.kt$import org.fossify.commons.extensions.* - WildcardImport:SelectEventTypeDialog.kt$import org.fossify.commons.extensions.* - WildcardImport:SetRemindersDialog.kt$import org.fossify.commons.extensions.* - WildcardImport:SettingsActivity.kt$import org.fossify.calendar.dialogs.* - WildcardImport:SettingsActivity.kt$import org.fossify.calendar.extensions.* - WildcardImport:SettingsActivity.kt$import org.fossify.calendar.helpers.* - WildcardImport:SettingsActivity.kt$import org.fossify.commons.dialogs.* - WildcardImport:SettingsActivity.kt$import org.fossify.commons.extensions.* - WildcardImport:SettingsActivity.kt$import org.fossify.commons.helpers.* WildcardImport:SplashActivity.kt$import org.fossify.calendar.helpers.* - WildcardImport:TaskActivity.kt$import org.fossify.calendar.dialogs.* - WildcardImport:TaskActivity.kt$import org.fossify.calendar.extensions.* - WildcardImport:TaskActivity.kt$import org.fossify.calendar.helpers.* - WildcardImport:TaskActivity.kt$import org.fossify.commons.extensions.* - WildcardImport:TaskActivity.kt$import org.fossify.commons.helpers.* - WildcardImport:WeekFragment.kt$import android.view.* - WildcardImport:WeekFragment.kt$import org.fossify.calendar.databinding.* - WildcardImport:WeekFragment.kt$import org.fossify.calendar.extensions.* - WildcardImport:WeekFragment.kt$import org.fossify.calendar.helpers.* - WildcardImport:WeekFragment.kt$import org.fossify.commons.extensions.* - WildcardImport:WeekFragment.kt$import org.fossify.commons.helpers.* WildcardImport:WeekFragmentsHolder.kt$import org.fossify.calendar.extensions.* WildcardImport:WeekFragmentsHolder.kt$import org.fossify.commons.extensions.* WildcardImport:WidgetDateConfigureActivity.kt$import org.fossify.commons.extensions.* diff --git a/app/lint-baseline.xml b/app/lint-baseline.xml index 9c3b9380f..7bf6ddd51 100644 --- a/app/lint-baseline.xml +++ b/app/lint-baseline.xml @@ -8,7 +8,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -63,7 +63,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -74,7 +74,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -216,18 +216,18 @@ errorLine1="distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -267,11 +267,11 @@ @@ -404,7 +404,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -437,7 +437,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -448,7 +448,7 @@ errorLine2=" ^"> @@ -459,7 +459,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -470,7 +470,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -895,7 +895,7 @@ @@ -3919,7 +3919,7 @@ errorLine1=" android:background="?attr/selectableItemBackground"" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -4191,7 +4191,7 @@ + + + + + - - - - - @@ -4417,7 +4417,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4428,25 +4428,25 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4472,7 +4472,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4483,18 +4483,18 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4505,18 +4505,18 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4527,40 +4527,40 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4571,40 +4571,40 @@ errorLine2=" ~~~~~~~~~~~~"> + errorLine1=" set(displayCalendars) = prefs.edit().remove(DISPLAY_CALENDARS)" + errorLine2=" ~~~~~~~~~~~~"> + line="97" + column="33"/> + errorLine1=" set(quickFilterCalendars) = prefs.edit().remove(QUICK_FILTER_CALENDARS)" + errorLine2=" ~~~~~~~~~~~~"> + line="102" + column="37"/> @@ -4615,7 +4615,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4626,7 +4626,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4637,62 +4637,62 @@ errorLine2=" ~~~~~~~~~~~~"> + errorLine1=" set(lastUsedLocalCalendarId) = prefs.edit()" + errorLine2=" ~~~~~~~~~~~~"> + line="136" + column="40"/> + errorLine1=" set(lastUsedIgnoreCalendarsState) = prefs.edit()" + errorLine2=" ~~~~~~~~~~~~"> + line="141" + column="45"/> @@ -4703,7 +4703,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4714,7 +4714,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4725,29 +4725,29 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4758,7 +4758,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4769,7 +4769,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4780,7 +4780,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4791,18 +4791,18 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4813,7 +4813,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4824,73 +4824,73 @@ errorLine2=" ~~~~~~~~~~~~"> - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + @@ -4901,7 +4901,7 @@ errorLine2=" ~~~~~~~~~~~~"> @@ -4912,113 +4912,14 @@ errorLine2=" ~~~~~~~~~~~~"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5088,7 +5088,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5099,54 +5099,10 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - - - - - - - - - - - - - - - - @@ -5275,7 +5231,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5286,7 +5242,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5297,7 +5253,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5308,7 +5264,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5319,7 +5275,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -5451,7 +5407,7 @@ errorLine2=" ^"> @@ -5462,7 +5418,7 @@ errorLine2=" ^"> @@ -5758,7 +5714,7 @@ errorLine1=" <ImageView" errorLine2=" ~~~~~~~~~"> @@ -5802,7 +5758,7 @@ errorLine1=" <ImageView" errorLine2=" ~~~~~~~~~"> @@ -5912,7 +5868,7 @@ errorLine1=" <ImageView" errorLine2=" ~~~~~~~~~"> @@ -5923,7 +5879,7 @@ errorLine1=" <ImageView" errorLine2=" ~~~~~~~~~"> @@ -5934,7 +5890,7 @@ errorLine1=" <ImageView" errorLine2=" ~~~~~~~~~"> @@ -6155,7 +6111,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -6177,7 +6133,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -6561,7 +6517,7 @@ errorLine1=" android:paddingStart="@dimen/small_margin" />" errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> @@ -6572,7 +6528,7 @@ errorLine1=" android:paddingStart="@dimen/activity_margin">" errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ca5e03034..7c6cbf715 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -200,7 +200,7 @@ () + private var mStoredCalendars = ArrayList() private var mOriginalTimeZone = DateTimeZone.getDefault().id private var mOriginalStartTS = 0L private var mOriginalEndTS = 0L @@ -232,7 +232,8 @@ class EventActivity : SimpleActivity() { val eventId = intent.getLongExtra(EVENT_ID, 0L) ensureBackgroundThread { - mStoredEventTypes = eventTypesDB.getEventTypes().toMutableList() as ArrayList + mStoredCalendars = + calendarsDB.getCalendars().toMutableList() as ArrayList val event = eventsDB.getEventWithId(eventId) if (eventId != 0L && event == null) { hideKeyboard() @@ -240,11 +241,11 @@ class EventActivity : SimpleActivity() { return@ensureBackgroundThread } - val localEventType = - mStoredEventTypes.firstOrNull { it.id == config.lastUsedLocalEventTypeId } + val localCalendar = + mStoredCalendars.firstOrNull { it.id == config.lastUsedLocalCalendarId } runOnUiThread { if (!isDestroyed && !isFinishing) { - gotEvent(savedInstanceState, localEventType, event) + gotEvent(savedInstanceState, localCalendar, event) } } } @@ -326,7 +327,7 @@ class EventActivity : SimpleActivity() { putInt(STATUS, mStatus) putInt(EVENT_COLOR, mEventColor) - putLong(EVENT_TYPE_ID, mEventTypeId) + putLong(CALENDAR_ID, mCalendarId) putInt(EVENT_CALENDAR_ID, mEventCalendarId) putBoolean(IS_NEW_EVENT, mIsNewEvent) putLong(ORIGINAL_START_TS, mOriginalStartTS) @@ -369,10 +370,11 @@ class EventActivity : SimpleActivity() { mAttendees = Gson().fromJson>(getString(ATTENDEES), token) ?: ArrayList() mOriginalAttendees = - Gson().fromJson>(getString(ORIGINAL_ATTENDEES), token) ?: ArrayList() + Gson().fromJson>(getString(ORIGINAL_ATTENDEES), token) + ?: ArrayList() mEvent.attendees = mAttendees - mEventTypeId = getLong(EVENT_TYPE_ID) + mCalendarId = getLong(CALENDAR_ID) mEventCalendarId = getInt(EVENT_CALENDAR_ID) mIsNewEvent = getBoolean(IS_NEW_EVENT) mOriginalStartTS = getLong(ORIGINAL_START_TS) @@ -382,7 +384,7 @@ class EventActivity : SimpleActivity() { checkRepeatTexts(mRepeatInterval) checkRepeatRule() updateTexts() - updateEventType() + updateLocalCalendar() updateCalDAVCalendar() checkAttendees() updateActionBarTitle() @@ -391,7 +393,7 @@ class EventActivity : SimpleActivity() { override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) { if ( requestCode == SELECT_TIME_ZONE_INTENT - && resultCode == Activity.RESULT_OK && resultData?.hasExtra(TIME_ZONE) == true + && resultCode == RESULT_OK && resultData?.hasExtra(TIME_ZONE) == true ) { val timeZone = resultData.getSerializableExtra(TIME_ZONE) as MyTimeZone mEvent.timeZone = timeZone.zoneName @@ -402,17 +404,17 @@ class EventActivity : SimpleActivity() { private fun gotEvent( savedInstanceState: Bundle?, - localEventType: EventType?, + localCalendar: CalendarEntity?, event: Event?, ) = binding.apply { - if (localEventType == null || localEventType.caldavCalendarId != 0) { - config.lastUsedLocalEventTypeId = LOCAL_CALENDAR_ID + if (localCalendar == null || localCalendar.caldavCalendarId != 0) { + config.lastUsedLocalCalendarId = LOCAL_CALENDAR_ID } - mEventTypeId = if (config.defaultEventTypeId == -1L) { - config.lastUsedLocalEventTypeId + mCalendarId = if (config.defaultCalendarId == -1L) { + config.lastUsedLocalCalendarId } else { - config.defaultEventTypeId + config.defaultCalendarId } if (event != null) { @@ -460,7 +462,7 @@ class EventActivity : SimpleActivity() { if (savedInstanceState == null) { updateTexts() - updateEventType() + updateLocalCalendar() updateCalDAVCalendar() } @@ -543,7 +545,7 @@ class EventActivity : SimpleActivity() { } } - eventTypeHolder.setOnClickListener { showEventTypeDialog() } + calendarHolder.setOnClickListener { showCalendarDialog() } eventAllDay.apply { isChecked = mEvent.getIsAllDay() jumpDrawablesToCurrentState() @@ -656,7 +658,7 @@ class EventActivity : SimpleActivity() { mAvailability != mEvent.availability || mAccessLevel != mEvent.accessLevel || mStatus != mEvent.status || - mEventTypeId != mEvent.eventType || + mCalendarId != mEvent.calendarId || mWasCalendarChanged || mIsAllDayEvent != mEvent.getIsAllDay() || mEventColor != mEvent.color || @@ -671,7 +673,7 @@ class EventActivity : SimpleActivity() { } return currentAttendees.zip(originalAttendees).any { (first, second) -> - first.email != second.email || + first.email != second.email || first.status != second.status || first.relationship != second.relationship } @@ -728,7 +730,7 @@ class EventActivity : SimpleActivity() { mRepeatInterval = mEvent.repeatInterval mRepeatLimit = mEvent.repeatLimit mRepeatRule = mEvent.repeatRule - mEventTypeId = mEvent.eventType + mCalendarId = mEvent.calendarId mEventCalendarId = mEvent.getCalDAVCalendarId() mAvailability = mEvent.availability mAccessLevel = mEvent.accessLevel @@ -746,9 +748,9 @@ class EventActivity : SimpleActivity() { window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE) binding.eventTitle.requestFocus() binding.eventToolbar.title = getString(R.string.new_event) - if (config.defaultEventTypeId != -1L) { - config.lastUsedCaldavCalendarId = mStoredEventTypes - .firstOrNull { it.id == config.defaultEventTypeId }?.caldavCalendarId + if (config.defaultCalendarId != -1L) { + config.lastUsedCaldavCalendarId = mStoredCalendars + .firstOrNull { it.id == config.defaultCalendarId }?.caldavCalendarId ?: 0 } @@ -816,7 +818,7 @@ class EventActivity : SimpleActivity() { reminder3Minutes = mReminder3Minutes reminder3Type = mReminder3Type status = mStatus - eventType = mEventTypeId + calendarId = mCalendarId } } @@ -1132,20 +1134,20 @@ class EventActivity : SimpleActivity() { else -> getRepeatXthDayInMonthString(false, mRepeatRule) } - private fun showEventTypeDialog() { + private fun showCalendarDialog() { hideKeyboard() - SelectEventTypeDialog( + SelectCalendarDialog( activity = this, - currEventType = mEventTypeId, + currCalendar = mCalendarId, showCalDAVCalendars = false, - showNewEventTypeOption = true, + showNewCalendarOption = true, addLastUsedOneAsFirstOption = false, showOnlyWritable = true, - showManageEventTypes = true + showManageCalendars = true ) { - mEventTypeId = it.id!! - updateEventType() + mCalendarId = it.id!! + updateLocalCalendar() } } @@ -1162,9 +1164,9 @@ class EventActivity : SimpleActivity() { } private fun showCustomEventColorDialog() { - val eventType = eventTypesDB.getEventTypeWithId(mEventTypeId)!! + val calendar = calendarsDB.getCalendarWithId(mCalendarId)!! val currentColor = if (mEventColor == 0) { - eventType.color + calendar.color } else { mEventColor } @@ -1176,18 +1178,18 @@ class EventActivity : SimpleActivity() { addDefaultColorButton = true ) { wasPositivePressed, newColor -> if (wasPositivePressed) { - gotNewEventColor(newColor, currentColor, eventType.color) + gotNewEventColor(newColor, currentColor, calendar.color) } } } } private fun showCalDAVEventColorDialog() { - val eventType = - eventsHelper.getEventTypeWithCalDAVCalendarId(calendarId = mEventCalendarId)!! - val eventColors = getEventColors(eventType) + val calendar = + eventsHelper.getCalendarWithCalDAVCalendarId(calendarId = mEventCalendarId)!! + val eventColors = getEventColors(calendar) val currentColor = if (mEventColor == 0) { - eventType.color + calendar.color } else { mEventColor } @@ -1198,7 +1200,7 @@ class EventActivity : SimpleActivity() { colors = eventColors, currentColor = currentColor ) { newColor -> - gotNewEventColor(newColor, currentColor, eventType.color) + gotNewEventColor(newColor, currentColor, calendar.color) } } } @@ -1376,13 +1378,13 @@ class EventActivity : SimpleActivity() { binding.eventRepetition.text = getRepetitionText(mRepeatInterval) } - private fun updateEventType() { + private fun updateLocalCalendar() { ensureBackgroundThread { - val eventType = eventTypesDB.getEventTypeWithId(mEventTypeId) - if (eventType != null) { + val calendar = calendarsDB.getCalendarWithId(mCalendarId) + if (calendar != null) { runOnUiThread { - binding.eventType.text = eventType.title - updateEventColorInfo(eventType.color) + binding.calendar.text = calendar.title + updateEventColorInfo(calendar.color) } } } @@ -1412,8 +1414,8 @@ class EventActivity : SimpleActivity() { hideKeyboard() SelectEventCalendarDialog(this, calendars, mEventCalendarId) { if (mEventCalendarId != STORED_LOCALLY_ONLY && it == STORED_LOCALLY_ONLY) { - mEventTypeId = config.lastUsedLocalEventTypeId - updateEventType() + mCalendarId = config.lastUsedLocalCalendarId + updateLocalCalendar() } mWasCalendarChanged = true mEventCalendarId = it @@ -1442,8 +1444,8 @@ class EventActivity : SimpleActivity() { calendars.firstOrNull { it.id == calendarId } private fun updateCurrentCalendarInfo(currentCalendar: CalDAVCalendar?) = binding.apply { - eventTypeImage.beVisibleIf(currentCalendar == null) - eventTypeHolder.beVisibleIf(currentCalendar == null) + calendarImage.beVisibleIf(currentCalendar == null) + calendarHolder.beVisibleIf(currentCalendar == null) eventCaldavCalendarDivider.beVisibleIf(currentCalendar == null) eventCaldavCalendarEmail.beGoneIf(currentCalendar == null) @@ -1461,13 +1463,13 @@ class EventActivity : SimpleActivity() { } ensureBackgroundThread { - val eventType = eventTypesDB.getEventTypeWithId(mEventTypeId) + val calendar = calendarsDB.getCalendarWithId(mCalendarId) runOnUiThread { - eventColorImage.beVisibleIf(eventType != null) - eventColorHolder.beVisibleIf(eventType != null) - eventColorDivider.beVisibleIf(eventType != null) - if (eventType != null) { - updateEventColorInfo(eventType.color) + eventColorImage.beVisibleIf(calendar != null) + eventColorHolder.beVisibleIf(calendar != null) + eventColorDivider.beVisibleIf(calendar != null) + if (calendar != null) { + updateEventColorInfo(calendar.color) } } } @@ -1475,10 +1477,10 @@ class EventActivity : SimpleActivity() { eventCaldavCalendarEmail.text = currentCalendar.accountName ensureBackgroundThread { - val eventType = eventsHelper.getEventTypeWithCalDAVCalendarId(currentCalendar.id) - val calendarColor = eventType?.color ?: currentCalendar.color - val canCustomizeColors = if (eventType != null) { - getEventColors(eventType).isNotEmpty() + val localCalendar = eventsHelper.getCalendarWithCalDAVCalendarId(currentCalendar.id) + val calendarColor = localCalendar?.color ?: currentCalendar.color + val canCustomizeColors = if (localCalendar != null) { + getEventColors(localCalendar).isNotEmpty() } else { false } @@ -1518,9 +1520,9 @@ class EventActivity : SimpleActivity() { binding.eventColor.setFillWithStroke(eventColor, getProperBackgroundColor()) } - private fun getEventColors(eventType: EventType): IntArray { + private fun getEventColors(calendar: CalendarEntity): IntArray { return calDAVHelper.getAvailableCalDAVCalendarColors( - eventType = eventType, + calendar = calendar, colorType = Colors.TYPE_EVENT ).keys.toIntArray() } @@ -1548,7 +1550,8 @@ class EventActivity : SimpleActivity() { // when converting from all-day to timed for the first time, // set default start time and duration to avoid spanning into next day if (!isAllDay && mEvent.getIsAllDay() && !mConvertedFromOriginalAllDay) { - val defaultStartTS = getNewEventTimestampFromCode(Formatter.getDayCodeFromDateTime(mEventStartDateTime)) + val defaultStartTS = + getNewEventTimestampFromCode(Formatter.getDayCodeFromDateTime(mEventStartDateTime)) val defaultStartTime = Formatter.getDateTimeFromTS(defaultStartTS) val defaultDurationMinutes = config.defaultDuration val endTime = defaultStartTime.plusMinutes(defaultDurationMinutes) @@ -1681,13 +1684,13 @@ class EventActivity : SimpleActivity() { generateImportId() } - val newEventType = + val newCalendarId = if ( !config.caldavSync || config.lastUsedCaldavCalendarId == 0 || mEventCalendarId == STORED_LOCALLY_ONLY ) { - mEventTypeId + mCalendarId } else { calDAVHelper.getCalDAVCalendars("", true).firstOrNull { it.id == mEventCalendarId } ?.apply { @@ -1699,12 +1702,12 @@ class EventActivity : SimpleActivity() { } } - eventsHelper.getEventTypeWithCalDAVCalendarId(mEventCalendarId)?.id - ?: config.lastUsedLocalEventTypeId + eventsHelper.getCalendarWithCalDAVCalendarId(mEventCalendarId)?.id + ?: config.lastUsedLocalCalendarId } val newSource = if (!config.caldavSync || mEventCalendarId == STORED_LOCALLY_ONLY) { - config.lastUsedLocalEventTypeId = newEventType + config.lastUsedLocalCalendarId = newCalendarId SOURCE_SIMPLE_CALENDAR } else { "$CALDAV-$mEventCalendarId" @@ -1764,7 +1767,7 @@ class EventActivity : SimpleActivity() { repeatRule = mRepeatRule attendees = if (mEventCalendarId == STORED_LOCALLY_ONLY) emptyList() else getAllAttendees(true) - eventType = newEventType + calendarId = newCalendarId lastUpdated = System.currentTimeMillis() source = newSource location = binding.eventLocation.value @@ -2491,7 +2494,7 @@ class EventActivity : SimpleActivity() { eventTimeZoneImage, eventRepetitionImage, eventReminderImage, - eventTypeImage, + calendarImage, eventCaldavCalendarImage, eventReminder1Type, eventReminder2Type, diff --git a/app/src/main/kotlin/org/fossify/calendar/activities/MainActivity.kt b/app/src/main/kotlin/org/fossify/calendar/activities/MainActivity.kt index 24219c543..17d767410 100644 --- a/app/src/main/kotlin/org/fossify/calendar/activities/MainActivity.kt +++ b/app/src/main/kotlin/org/fossify/calendar/activities/MainActivity.kt @@ -15,10 +15,10 @@ import android.view.MenuItem import android.widget.Toast import org.fossify.calendar.R import org.fossify.calendar.adapters.EventListAdapter -import org.fossify.calendar.adapters.QuickFilterEventTypeAdapter +import org.fossify.calendar.adapters.QuickFilterCalendarAdapter import org.fossify.calendar.databases.EventsDatabase import org.fossify.calendar.databinding.ActivityMainBinding -import org.fossify.calendar.dialogs.SelectEventTypesDialog +import org.fossify.calendar.dialogs.SelectCalendarsDialog import org.fossify.calendar.dialogs.SelectHolidayTypesDialog import org.fossify.calendar.dialogs.SetRemindersDialog import org.fossify.calendar.extensions.addImportIdsToTasks @@ -138,6 +138,7 @@ import org.joda.time.DateTime import org.joda.time.DateTimeZone import java.text.SimpleDateFormat import java.util.Locale +import androidx.core.graphics.drawable.toDrawable class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { override var isSearchBarEnabled = true @@ -177,7 +178,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { setupOptionsMenu() refreshMenuItems() setupEdgeToEdge( - padBottomImeAndSystem = listOf(binding.searchHolder, binding.quickEventTypeFilter), + padBottomImeAndSystem = listOf(binding.searchHolder, binding.quickCalendarFilter), ) checkWhatsNewDialog() @@ -256,8 +257,8 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { updateViewPager() } - eventsHelper.getEventTypes(this, false) { - val newShouldFilterBeVisible = it.size > 1 || config.displayEventTypes.isEmpty() + eventsHelper.getCalendars(this, false) { + val newShouldFilterBeVisible = it.size > 1 || config.displayCalendars.isEmpty() if (newShouldFilterBeVisible != mShouldFilterBeVisible) { mShouldFilterBeVisible = newShouldFilterBeVisible refreshMenuItems() @@ -277,14 +278,15 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { storeStateVariables() updateWidgets() updateTextColors(calendarCoordinator) - fabExtendedOverlay.background = ColorDrawable(getProperBackgroundColor().adjustAlpha(0.8f)) + fabExtendedOverlay.background = + getProperBackgroundColor().adjustAlpha(0.8f).toDrawable() fabEventLabel.setTextColor(getProperTextColor()) fabTaskLabel.setTextColor(getProperTextColor()) fabTaskIcon.drawable.applyColorFilter(mStoredPrimaryColor.getContrastColor()) fabTaskIcon.background.applyColorFilter(mStoredPrimaryColor) - searchHolder.background = ColorDrawable(getProperBackgroundColor()) + searchHolder.background = getProperBackgroundColor().toDrawable() checkSwipeRefreshAvailability() checkShortcuts() @@ -318,15 +320,18 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { hideExtendedFab() } - shouldGoToTodayBeVisible = currentFragments.lastOrNull()?.shouldGoToTodayBeVisible() ?: false + shouldGoToTodayBeVisible = + currentFragments.lastOrNull()?.shouldGoToTodayBeVisible() ?: false binding.mainMenu.requireToolbar().menu.apply { goToTodayButton = findItem(R.id.go_to_today) findItem(R.id.print).isVisible = config.storedView != MONTHLY_DAILY_VIEW findItem(R.id.filter).isVisible = mShouldFilterBeVisible - findItem(R.id.go_to_today).isVisible = shouldGoToTodayBeVisible && !binding.mainMenu.isSearchOpen + findItem(R.id.go_to_today).isVisible = + shouldGoToTodayBeVisible && !binding.mainMenu.isSearchOpen findItem(R.id.go_to_date).isVisible = config.storedView != EVENTS_LIST_VIEW findItem(R.id.refresh_caldav_calendars).isVisible = config.caldavSync - findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations) + findItem(R.id.more_apps_from_us).isVisible = + !resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations) } } @@ -375,10 +380,12 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { hideExtendedFab() true } + currentFragments.size > 1 -> { removeTopFragment() true } + else -> false } } @@ -409,17 +416,18 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { } private fun setupQuickFilter() { - eventsHelper.getEventTypes(this, false) { - val quickFilterEventTypes = config.quickFilterEventTypes - binding.quickEventTypeFilter.adapter = QuickFilterEventTypeAdapter(this, it, quickFilterEventTypes) { - if (config.displayEventTypes.isEmpty() && !config.wasFilteredOutWarningShown) { - toast(R.string.everything_filtered_out, Toast.LENGTH_LONG) - config.wasFilteredOutWarningShown = true - } + eventsHelper.getCalendars(this, false) { + val quickFilterCalendars = config.quickFilterCalendars + binding.quickCalendarFilter.adapter = + QuickFilterCalendarAdapter(this, it, quickFilterCalendars) { + if (config.displayCalendars.isEmpty() && !config.wasFilteredOutWarningShown) { + toast(R.string.everything_filtered_out, Toast.LENGTH_LONG) + config.wasFilteredOutWarningShown = true + } - refreshViewPager() - updateWidgets() - } + refreshViewPager() + updateWidgets() + } } } @@ -476,7 +484,8 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { private fun getNewEventShortcut(appIconColor: Int): ShortcutInfo { val newEvent = getString(R.string.new_event) val newEventDrawable = resources.getDrawable(R.drawable.shortcut_event, theme) - (newEventDrawable as LayerDrawable).findDrawableByLayerId(R.id.shortcut_event_background).applyColorFilter(appIconColor) + (newEventDrawable as LayerDrawable).findDrawableByLayerId(R.id.shortcut_event_background) + .applyColorFilter(appIconColor) val newEventBitmap = newEventDrawable.convertToBitmap() val newEventIntent = Intent(this, SplashActivity::class.java) @@ -493,7 +502,8 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { private fun getNewTaskShortcut(appIconColor: Int): ShortcutInfo { val newTask = getString(R.string.new_task) val newTaskDrawable = resources.getDrawable(R.drawable.shortcut_task, theme) - (newTaskDrawable as LayerDrawable).findDrawableByLayerId(R.id.shortcut_task_background).applyColorFilter(appIconColor) + (newTaskDrawable as LayerDrawable).findDrawableByLayerId(R.id.shortcut_task_background) + .applyColorFilter(appIconColor) val newTaskBitmap = newTaskDrawable.convertToBitmap() val newTaskIntent = Intent(this, SplashActivity::class.java) newTaskIntent.action = SHORTCUT_NEW_TASK @@ -540,7 +550,10 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { private fun checkIsViewIntent() { if (intent?.action == Intent.ACTION_VIEW && intent.data != null) { val uri = intent.data - if (uri?.authority?.equals("com.android.calendar") == true || uri?.authority?.substringAfter("@") == "com.android.calendar") { + if ( + uri?.authority?.equals("com.android.calendar") == true + || uri?.authority?.substringAfter("@") == "com.android.calendar" + ) { if (uri.path!!.startsWith("/events")) { ensureBackgroundThread { // intents like content://com.android.calendar/events/1756 @@ -556,7 +569,10 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { toast(R.string.caldav_event_not_found, Toast.LENGTH_LONG) } } - } else if (uri.path!!.startsWith("/time") || intent?.extras?.getBoolean("DETAIL_VIEW", false) == true) { + } else if ( + uri.path!!.startsWith("/time") + || intent?.extras?.getBoolean("DETAIL_VIEW", false) == true + ) { // clicking date on a third party widget: content://com.android.calendar/time/1507309245683 // or content://0@com.android.calendar/time/1584958526435 val timestamp = uri.pathSegments.last() @@ -588,7 +604,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { RadioItem(EVENTS_LIST_VIEW, getString(R.string.simple_event_list)) ) - RadioGroupDialog(this, items, config.storedView) { + RadioGroupDialog(activity = this, items = items, checkedItemId = config.storedView) { resetActionBarTitle() closeSearch() updateView(it as Int) @@ -614,9 +630,9 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { } private fun showFilterDialog() { - SelectEventTypesDialog(this, config.displayEventTypes) { - if (config.displayEventTypes != it) { - config.displayEventTypes = it + SelectCalendarsDialog(activity = this, selectedCalendars = config.displayCalendars) { + if (config.displayCalendars != it) { + config.displayCalendars = it refreshViewPager() setupQuickFilter() @@ -666,7 +682,10 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { private fun addHolidays() { getHolidayRadioItems { items -> RadioGroupDialog(this, items) { any -> - SelectHolidayTypesDialog(this, any as HolidayInfo) { pathsToImport -> + SelectHolidayTypesDialog( + activity = this, + holidayInfo = any as HolidayInfo + ) { pathsToImport -> SetRemindersDialog(this, OTHER_EVENT) { reminders -> toast(org.fossify.commons.R.string.importing) ensureBackgroundThread { @@ -689,9 +708,9 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { } private fun importHolidays(path: String, reminders: ArrayList): ImportResult { - var eventTypeId = eventsHelper.getEventTypeIdWithClass(HOLIDAY_EVENT) - if (eventTypeId == -1L) { - eventTypeId = eventsHelper.createPredefinedEventType( + var calendarId = eventsHelper.getCalendarIdWithClass(HOLIDAY_EVENT) + if (calendarId == -1L) { + calendarId = eventsHelper.createPredefinedCalendar( title = getString(R.string.holidays), colorResId = R.color.default_holidays_color, type = HOLIDAY_EVENT, @@ -701,9 +720,9 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { return IcsImporter(this).importEvents( path = path, - defaultEventTypeId = eventTypeId, + defaultCalendarId = calendarId, calDAVCalendarId = 0, - overrideFileEventTypes = false, + overrideFileCalendars = false, eventReminders = reminders, loadFromAssets = true ) @@ -717,9 +736,19 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { val privateCursor = getMyContactsCursor(false, false) ensureBackgroundThread { - val privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor) - addPrivateEvents(true, privateContacts, reminders) { eventsFound, eventsAdded -> - addContactEvents(true, reminders, eventsFound, eventsAdded) { + val privateContacts = + MyContactsContentProvider.getSimpleContacts(this, privateCursor) + addPrivateEvents( + birthdays = true, + contacts = privateContacts, + reminders = reminders + ) { eventsFound, eventsAdded -> + addContactEvents( + birthdays = true, + reminders = reminders, + initEventsFound = eventsFound, + initEventsAdded = eventsAdded + ) { when { it > 0 -> { toast(R.string.birthdays_added) @@ -748,9 +777,19 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { val privateCursor = getMyContactsCursor(false, false) ensureBackgroundThread { - val privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor) - addPrivateEvents(false, privateContacts, reminders) { eventsFound, eventsAdded -> - addContactEvents(false, reminders, eventsFound, eventsAdded) { + val privateContacts = + MyContactsContentProvider.getSimpleContacts(this, privateCursor) + addPrivateEvents( + birthdays = false, + contacts = privateContacts, + reminders = reminders + ) { eventsFound, eventsAdded -> + addContactEvents( + birthdays = false, + reminders = reminders, + initEventsFound = eventsFound, + initEventsAdded = eventsAdded + ) { when { it > 0 -> { toast(R.string.anniversaries_added) @@ -772,7 +811,10 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { } private fun addBirthdaysAnniversariesAtStart() { - if ((!config.addBirthdaysAutomatically && !config.addAnniversariesAutomatically) || !hasPermission(PERMISSION_READ_CONTACTS)) { + if ( + (!config.addBirthdaysAutomatically && !config.addAnniversariesAutomatically) + || !hasPermission(PERMISSION_READ_CONTACTS) + ) { return } @@ -781,8 +823,17 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { ensureBackgroundThread { val privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor) if (config.addBirthdaysAutomatically) { - addPrivateEvents(true, privateContacts, config.birthdayReminders) { eventsFound, eventsAdded -> - addContactEvents(true, config.birthdayReminders, eventsFound, eventsAdded) { + addPrivateEvents( + birthdays = true, + contacts = privateContacts, + reminders = config.birthdayReminders + ) { eventsFound, eventsAdded -> + addContactEvents( + birthdays = true, + reminders = config.birthdayReminders, + initEventsFound = eventsFound, + initEventsAdded = eventsAdded + ) { if (it > 0) { toast(R.string.birthdays_added) updateViewPager() @@ -793,8 +844,17 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { } if (config.addAnniversariesAutomatically) { - addPrivateEvents(false, privateContacts, config.anniversaryReminders) { eventsFound, eventsAdded -> - addContactEvents(false, config.anniversaryReminders, eventsFound, eventsAdded) { + addPrivateEvents( + birthdays = false, + contacts = privateContacts, + reminders = config.anniversaryReminders + ) { eventsFound, eventsAdded -> + addContactEvents( + birthdays = false, + reminders = config.anniversaryReminders, + initEventsFound = eventsFound, + initEventsAdded = eventsAdded + ) { if (it > 0) { toast(R.string.anniversaries_added) updateViewPager() @@ -817,7 +877,13 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { ) } - private fun addContactEvents(birthdays: Boolean, reminders: ArrayList, initEventsFound: Int, initEventsAdded: Int, callback: (Int) -> Unit) { + private fun addContactEvents( + birthdays: Boolean, + reminders: ArrayList, + initEventsFound: Int, + initEventsAdded: Int, + callback: (Int) -> Unit + ) { var eventsFound = initEventsFound var eventsAdded = initEventsAdded val uri = Data.CONTENT_URI @@ -829,7 +895,8 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { ) val selection = "${Data.MIMETYPE} = ? AND ${CommonDataKinds.Event.TYPE} = ?" - val type = if (birthdays) CommonDataKinds.Event.TYPE_BIRTHDAY else CommonDataKinds.Event.TYPE_ANNIVERSARY + val type = + if (birthdays) CommonDataKinds.Event.TYPE_BIRTHDAY else CommonDataKinds.Event.TYPE_ANNIVERSARY val selectionArgs = arrayOf(CommonDataKinds.Event.CONTENT_ITEM_TYPE, type.toString()) val dateFormats = getDateFormats() @@ -840,10 +907,17 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { importIDs[it.importId] = it.startTS } - val eventTypeId = if (birthdays) eventsHelper.getLocalBirthdaysEventTypeId() else eventsHelper.getAnniversariesEventTypeId() + val calendarId = + if (birthdays) eventsHelper.getLocalBirthdaysCalendarId() else eventsHelper.getAnniversariesCalendarId() val source = if (birthdays) SOURCE_CONTACT_BIRTHDAY else SOURCE_CONTACT_ANNIVERSARY - queryCursor(uri, projection, selection, selectionArgs, showErrors = true) { cursor -> + queryCursor( + uri = uri, + projection = projection, + selection = selection, + selectionArgs = selectionArgs, + showErrors = true + ) { cursor -> val contactId = cursor.getIntValue(CommonDataKinds.Event.CONTACT_ID).toString() val name = cursor.getStringValue(Contacts.DISPLAY_NAME) val startDate = cursor.getStringValue(CommonDataKinds.Event.START_DATE) @@ -859,11 +933,24 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { } val timestamp = date.time / 1000L - val lastUpdated = cursor.getLongValue(CommonDataKinds.Event.CONTACT_LAST_UPDATED_TIMESTAMP) + val lastUpdated = + cursor.getLongValue(CommonDataKinds.Event.CONTACT_LAST_UPDATED_TIMESTAMP) val event = Event( - null, timestamp, timestamp, name, reminder1Minutes = reminders[0], reminder2Minutes = reminders[1], - reminder3Minutes = reminders[2], importId = contactId, timeZone = DateTimeZone.getDefault().id, flags = flags, - repeatInterval = YEAR, repeatRule = REPEAT_SAME_DAY, eventType = eventTypeId, source = source, lastUpdated = lastUpdated + id = null, + startTS = timestamp, + endTS = timestamp, + title = name, + reminder1Minutes = reminders[0], + reminder2Minutes = reminders[1], + reminder3Minutes = reminders[2], + importId = contactId, + timeZone = DateTimeZone.getDefault().id, + flags = flags, + repeatInterval = YEAR, + repeatRule = REPEAT_SAME_DAY, + calendarId = calendarId, + source = source, + lastUpdated = lastUpdated ) val importIDsToDelete = ArrayList() @@ -914,10 +1001,12 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { } try { - val eventTypeId = if (birthdays) eventsHelper.getLocalBirthdaysEventTypeId() else eventsHelper.getAnniversariesEventTypeId() + val calendarId = + if (birthdays) eventsHelper.getLocalBirthdaysCalendarId() else eventsHelper.getAnniversariesCalendarId() val source = if (birthdays) SOURCE_CONTACT_BIRTHDAY else SOURCE_CONTACT_ANNIVERSARY - val existingEvents = if (birthdays) eventsDB.getBirthdays() else eventsDB.getAnniversaries() + val existingEvents = + if (birthdays) eventsDB.getBirthdays() else eventsDB.getAnniversaries() val importIDs = HashMap() existingEvents.forEach { importIDs[it.importId] = it.startTS @@ -935,7 +1024,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { "yyyy-MM-dd" } - var flags = if (missingYear) { + val flags = if (missingYear) { FLAG_ALL_DAY or FLAG_MISSING_YEAR } else { FLAG_ALL_DAY @@ -947,9 +1036,21 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { val timestamp = date.time / 1000L val lastUpdated = System.currentTimeMillis() val event = Event( - null, timestamp, timestamp, contact.name, reminder1Minutes = reminders[0], reminder2Minutes = reminders[1], - reminder3Minutes = reminders[2], importId = contact.contactId.toString(), timeZone = DateTimeZone.getDefault().id, flags = flags, - repeatInterval = YEAR, repeatRule = REPEAT_SAME_DAY, eventType = eventTypeId, source = source, lastUpdated = lastUpdated + id = null, + startTS = timestamp, + endTS = timestamp, + title = contact.name, + reminder1Minutes = reminders[0], + reminder2Minutes = reminders[1], + reminder3Minutes = reminders[2], + importId = contact.contactId.toString(), + timeZone = DateTimeZone.getDefault().id, + flags = flags, + repeatInterval = YEAR, + repeatRule = REPEAT_SAME_DAY, + calendarId = calendarId, + source = source, + lastUpdated = lastUpdated ) val importIDsToDelete = ArrayList() @@ -1002,8 +1103,10 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { val fragmentDate = fragment.getCurrentDate() val viewOrder = arrayListOf(DAILY_VIEW, WEEKLY_VIEW, MONTHLY_VIEW, YEARLY_VIEW) - val currentViewIndex = viewOrder.indexOf(if (currentView == MONTHLY_DAILY_VIEW) MONTHLY_VIEW else currentView) - val newViewIndex = viewOrder.indexOf(if (newView == MONTHLY_DAILY_VIEW) MONTHLY_VIEW else newView) + val currentViewIndex = + viewOrder.indexOf(if (currentView == MONTHLY_DAILY_VIEW) MONTHLY_VIEW else currentView) + val newViewIndex = + viewOrder.indexOf(if (newView == MONTHLY_DAILY_VIEW) MONTHLY_VIEW else newView) return if (fragmentDate != null && currentViewIndex <= newViewIndex) { getDateCodeFormatForView(newView, fragmentDate) @@ -1037,8 +1140,16 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { when (config.storedView) { DAILY_VIEW -> bundle.putString(DAY_CODE, fixedDayCode ?: Formatter.getTodayCode()) - WEEKLY_VIEW -> bundle.putString(WEEK_START_DATE_TIME, fixedDayCode ?: getFirstDayOfWeek(DateTime())) - MONTHLY_VIEW, MONTHLY_DAILY_VIEW -> bundle.putString(DAY_CODE, fixedDayCode ?: Formatter.getTodayCode()) + WEEKLY_VIEW -> bundle.putString( + WEEK_START_DATE_TIME, + fixedDayCode ?: getFirstDayOfWeek(DateTime()) + ) + + MONTHLY_VIEW, MONTHLY_DAILY_VIEW -> bundle.putString( + DAY_CODE, + fixedDayCode ?: Formatter.getTodayCode() + ) + YEARLY_VIEW -> bundle.putString(YEAR_TO_OPEN, fixedDayCode) } @@ -1083,21 +1194,24 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { } else { R.drawable.ic_today_vector } - val newDrawable = resources.getColoredDrawableWithColor(newDrawableId, getProperPrimaryColor()) + val newDrawable = + resources.getColoredDrawableWithColor(newDrawableId, getProperPrimaryColor()) binding.calendarFab.setImageDrawable(newDrawable) } private fun openNewEvent() { hideKeyboard() val lastFragment = currentFragments.last() - val allowChangingDay = lastFragment !is DayFragmentsHolder && lastFragment !is MonthDayFragmentsHolder + val allowChangingDay = + lastFragment !is DayFragmentsHolder && lastFragment !is MonthDayFragmentsHolder launchNewEventIntent(lastFragment.getNewEventDayCode(), allowChangingDay) } private fun openNewTask() { hideKeyboard() val lastFragment = currentFragments.last() - val allowChangingDay = lastFragment !is DayFragmentsHolder && lastFragment !is MonthDayFragmentsHolder + val allowChangingDay = + lastFragment !is DayFragmentsHolder && lastFragment !is MonthDayFragmentsHolder launchNewTaskIntent(lastFragment.getNewEventDayCode(), allowChangingDay) } @@ -1128,7 +1242,8 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { bundle.putString(DAY_CODE, Formatter.getDayCodeFromDateTime(dateTime)) fragment.arguments = bundle try { - supportFragmentManager.beginTransaction().add(R.id.fragments_holder, fragment).commitNow() + supportFragmentManager.beginTransaction().add(R.id.fragments_holder, fragment) + .commitNow() showBackNavigationArrow() } catch (e: Exception) { } @@ -1169,7 +1284,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { binding.calendarFab.beGoneIf( currentFragments.size == 1 && - (config.storedView == YEARLY_VIEW || config.storedView == WEEKLY_VIEW) + (config.storedView == YEARLY_VIEW || config.storedView == WEEKLY_VIEW) ) if (currentFragments.size > 1) { showBackNavigationArrow() @@ -1202,23 +1317,53 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { val licenses = LICENSE_JODA val faqItems = arrayListOf( - FAQItem("${getString(R.string.faq_2_title)} ${getString(R.string.faq_2_title_extra)}", R.string.faq_2_text), + FAQItem( + title = "${getString(R.string.faq_2_title)} ${getString(R.string.faq_2_title_extra)}", + text = R.string.faq_2_text + ), FAQItem(R.string.faq_5_title, R.string.faq_5_text), FAQItem(R.string.faq_3_title, R.string.faq_3_text), FAQItem(R.string.faq_6_title, R.string.faq_6_text), FAQItem(R.string.faq_1_title, R.string.faq_1_text), - FAQItem(org.fossify.commons.R.string.faq_1_title_commons, org.fossify.commons.R.string.faq_1_text_commons), - FAQItem(org.fossify.commons.R.string.faq_4_title_commons, org.fossify.commons.R.string.faq_4_text_commons), + FAQItem( + title = org.fossify.commons.R.string.faq_1_title_commons, + text = org.fossify.commons.R.string.faq_1_text_commons + ), + FAQItem( + title = org.fossify.commons.R.string.faq_4_title_commons, + text = org.fossify.commons.R.string.faq_4_text_commons + ), FAQItem(R.string.faq_4_title, R.string.faq_4_text) ) if (!resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations)) { - faqItems.add(FAQItem(org.fossify.commons.R.string.faq_2_title_commons, org.fossify.commons.R.string.faq_2_text_commons)) - faqItems.add(FAQItem(org.fossify.commons.R.string.faq_6_title_commons, org.fossify.commons.R.string.faq_6_text_commons)) - faqItems.add(FAQItem(org.fossify.commons.R.string.faq_7_title_commons, org.fossify.commons.R.string.faq_7_text_commons)) + faqItems.add( + FAQItem( + title = org.fossify.commons.R.string.faq_2_title_commons, + text = org.fossify.commons.R.string.faq_2_text_commons + ) + ) + faqItems.add( + FAQItem( + title = org.fossify.commons.R.string.faq_6_title_commons, + text = org.fossify.commons.R.string.faq_6_text_commons + ) + ) + faqItems.add( + FAQItem( + title = org.fossify.commons.R.string.faq_7_title_commons, + text = org.fossify.commons.R.string.faq_7_text_commons + ) + ) } - startAboutActivity(R.string.app_name, licenses, org.fossify.calendar.BuildConfig.VERSION_NAME, faqItems, true) + startAboutActivity( + appNameId = R.string.app_name, + licenseMask = licenses, + versionName = org.fossify.calendar.BuildConfig.VERSION_NAME, + faqItems = faqItems, + showFAQBeforeMail = true + ) } private fun searchQueryChanged(text: String) { @@ -1231,7 +1376,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { binding.searchResultsList.adapter = null } - val placeholderTextId = if (config.displayEventTypes.isEmpty()) { + val placeholderTextId = if (config.displayCalendars.isEmpty()) { R.string.everything_filtered_out } else { org.fossify.commons.R.string.no_items_found @@ -1245,7 +1390,11 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { maxFetchedSearchTS = DateTime().plusYears(2).seconds() } - eventsHelper.getEvents(minFetchedSearchTS, maxFetchedSearchTS, searchQuery = text) { events -> + eventsHelper.getEvents( + fromTS = minFetchedSearchTS, + toTS = maxFetchedSearchTS, + searchQuery = text + ) { events -> if (text == mLatestSearchQuery) { // if we have less than MIN_EVENTS_THRESHOLD events, search again by extending the time span showSearchResultEvents(events, INITIAL_EVENTS) @@ -1254,7 +1403,11 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { minFetchedSearchTS = 0L maxFetchedSearchTS = MAX_SEARCH_YEAR - eventsHelper.getEvents(minFetchedSearchTS, maxFetchedSearchTS, searchQuery = text) { events -> + eventsHelper.getEvents( + fromTS = minFetchedSearchTS, + toTS = maxFetchedSearchTS, + searchQuery = text + ) { events -> events.forEach { event -> try { if (searchResultEvents.firstOrNull { it.id == event.id && it.startTS == event.startTS } == null) { @@ -1279,10 +1432,9 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { val currentSearchQuery = binding.mainMenu.getCurrentQuery() val filtered = try { events.filter { - it.title.contains(currentSearchQuery, true) || it.location.contains(currentSearchQuery, true) || it.description.contains( - currentSearchQuery, - true - ) + it.title.contains(currentSearchQuery, true) + || it.location.contains(currentSearchQuery, true) + || it.description.contains(currentSearchQuery, true) } } catch (e: ConcurrentModificationException) { return @@ -1295,28 +1447,36 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { val listItems = getEventListItems(filtered) val currAdapter = binding.searchResultsList.adapter if (currAdapter == null) { - val eventsAdapter = EventListAdapter(this, listItems, true, this, binding.searchResultsList) { - hideKeyboard() - if (it is ListEvent) { - Intent(applicationContext, getActivityToOpen(it.isTask)).apply { - putExtra(EVENT_ID, it.id) - putExtra(EVENT_OCCURRENCE_TS, it.startTS) - startActivity(this) + val eventsAdapter = + EventListAdapter( + activity = this, + listItems = listItems, + allowLongClick = true, + listener = this, + recyclerView = binding.searchResultsList + ) { + hideKeyboard() + if (it is ListEvent) { + Intent(applicationContext, getActivityToOpen(it.isTask)).apply { + putExtra(EVENT_ID, it.id) + putExtra(EVENT_OCCURRENCE_TS, it.startTS) + startActivity(this) + } } } - } binding.searchResultsList.adapter = eventsAdapter - binding.searchResultsList.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener { - override fun updateTop() { - fetchPreviousPeriod() - } + binding.searchResultsList.endlessScrollListener = + object : MyRecyclerView.EndlessScrollListener { + override fun updateTop() { + fetchPreviousPeriod() + } - override fun updateBottom() { - fetchNextPeriod() + override fun updateBottom() { + fetchNextPeriod() + } } - } } else { (currAdapter as EventListAdapter).updateListItems(listItems) if (updateStatus == UPDATE_TOP) { @@ -1325,9 +1485,13 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { binding.searchResultsList.scrollToPosition(item) } } else if (updateStatus == UPDATE_BOTTOM) { - binding.searchResultsList.smoothScrollBy(0, resources.getDimension(R.dimen.endless_scroll_move_height).toInt()) + binding.searchResultsList.smoothScrollBy( + 0, + resources.getDimension(R.dimen.endless_scroll_move_height).toInt() + ) } else { - val firstNonPastSectionIndex = listItems.indexOfFirst { it is ListSectionDay && !it.isPastSection } + val firstNonPastSectionIndex = + listItems.indexOfFirst { it is ListSectionDay && !it.isPastSection } if (firstNonPastSectionIndex != -1) { binding.searchResultsList.scrollToPosition(firstNonPastSectionIndex) } @@ -1341,12 +1505,18 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { return } - val lastPosition = (binding.searchResultsList.layoutManager as MyLinearLayoutManager).findLastVisibleItemPosition() - bottomItemAtRefresh = (binding.searchResultsList.adapter as EventListAdapter).listItems[lastPosition] + val lastPosition = + (binding.searchResultsList.layoutManager as MyLinearLayoutManager).findLastVisibleItemPosition() + bottomItemAtRefresh = + (binding.searchResultsList.adapter as EventListAdapter).listItems[lastPosition] val oldMinFetchedTS = minFetchedSearchTS - 1 minFetchedSearchTS -= FETCH_INTERVAL - eventsHelper.getEvents(minFetchedSearchTS, oldMinFetchedTS, searchQuery = mLatestSearchQuery) { events -> + eventsHelper.getEvents( + fromTS = minFetchedSearchTS, + toTS = oldMinFetchedTS, + searchQuery = mLatestSearchQuery + ) { events -> events.forEach { event -> try { if (searchResultEvents.firstOrNull { it.id == event.id && it.startTS == event.startTS } == null) { @@ -1367,7 +1537,11 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { val oldMaxFetchedTS = maxFetchedSearchTS + 1 maxFetchedSearchTS += FETCH_INTERVAL - eventsHelper.getEvents(oldMaxFetchedTS, maxFetchedSearchTS, searchQuery = mLatestSearchQuery) { events -> + eventsHelper.getEvents( + fromTS = oldMaxFetchedTS, + toTS = maxFetchedSearchTS, + searchQuery = mLatestSearchQuery + ) { events -> events.forEach { event -> try { if (searchResultEvents.firstOrNull { it.id == event.id && it.startTS == event.startTS } == null) { @@ -1382,7 +1556,8 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { } private fun checkSwipeRefreshAvailability() { - binding.swipeRefreshLayout.isEnabled = config.caldavSync && config.pullToRefresh && config.storedView != WEEKLY_VIEW + binding.swipeRefreshLayout.isEnabled = + config.caldavSync && config.pullToRefresh && config.storedView != WEEKLY_VIEW if (!binding.swipeRefreshLayout.isEnabled) { binding.swipeRefreshLayout.isRefreshing = false } diff --git a/app/src/main/kotlin/org/fossify/calendar/activities/ManageCalendarsActivity.kt b/app/src/main/kotlin/org/fossify/calendar/activities/ManageCalendarsActivity.kt new file mode 100644 index 000000000..2af9c1a14 --- /dev/null +++ b/app/src/main/kotlin/org/fossify/calendar/activities/ManageCalendarsActivity.kt @@ -0,0 +1,80 @@ +package org.fossify.calendar.activities + +import android.os.Bundle +import org.fossify.calendar.R +import org.fossify.calendar.adapters.ManageCalendarsAdapter +import org.fossify.calendar.databinding.ActivityManageCalendarsBinding +import org.fossify.calendar.dialogs.EditCalendarDialog +import org.fossify.calendar.extensions.eventsHelper +import org.fossify.calendar.interfaces.DeleteCalendarsListener +import org.fossify.calendar.models.CalendarEntity +import org.fossify.commons.extensions.toast +import org.fossify.commons.extensions.updateTextColors +import org.fossify.commons.extensions.viewBinding +import org.fossify.commons.helpers.NavigationIcon +import org.fossify.commons.helpers.ensureBackgroundThread + +class ManageCalendarsActivity : SimpleActivity(), DeleteCalendarsListener { + + private val binding by viewBinding(ActivityManageCalendarsBinding::inflate) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(binding.root) + setupOptionsMenu() + + setupEdgeToEdge(padBottomSystem = listOf(binding.manageCalendarsList)) + setupMaterialScrollListener(binding.manageCalendarsList, binding.manageCalendarsAppbar) + + getCalendars() + updateTextColors(binding.manageCalendarsList) + } + + override fun onResume() { + super.onResume() + setupTopAppBar(binding.manageCalendarsAppbar, NavigationIcon.Arrow) + } + + private fun showEditCalendarDialog(calendar: CalendarEntity? = null) { + EditCalendarDialog(this, calendar?.copy()) { + getCalendars() + } + } + + private fun getCalendars() { + eventsHelper.getCalendars(this, false) { + val adapter = ManageCalendarsAdapter(this, it, this, binding.manageCalendarsList) { + showEditCalendarDialog(it as CalendarEntity) + } + binding.manageCalendarsList.adapter = adapter + } + } + + private fun setupOptionsMenu() { + binding.manageCalendarsToolbar.setOnMenuItemClickListener { menuItem -> + when (menuItem.itemId) { + R.id.add_calendar -> showEditCalendarDialog() + else -> return@setOnMenuItemClickListener false + } + return@setOnMenuItemClickListener true + } + } + + override fun deleteCalendars( + calendars: ArrayList, + deleteEvents: Boolean + ): Boolean { + if (calendars.any { it.caldavCalendarId != 0 }) { + toast(R.string.unsync_caldav_calendar) + if (calendars.size == 1) { + return false + } + } + + ensureBackgroundThread { + eventsHelper.deleteCalendars(calendars, deleteEvents) + } + + return true + } +} diff --git a/app/src/main/kotlin/org/fossify/calendar/activities/ManageEventTypesActivity.kt b/app/src/main/kotlin/org/fossify/calendar/activities/ManageEventTypesActivity.kt deleted file mode 100644 index f8eb651ff..000000000 --- a/app/src/main/kotlin/org/fossify/calendar/activities/ManageEventTypesActivity.kt +++ /dev/null @@ -1,77 +0,0 @@ -package org.fossify.calendar.activities - -import android.os.Bundle -import org.fossify.calendar.R -import org.fossify.calendar.adapters.ManageEventTypesAdapter -import org.fossify.calendar.databinding.ActivityManageEventTypesBinding -import org.fossify.calendar.dialogs.EditEventTypeDialog -import org.fossify.calendar.extensions.eventsHelper -import org.fossify.calendar.interfaces.DeleteEventTypesListener -import org.fossify.calendar.models.EventType -import org.fossify.commons.extensions.toast -import org.fossify.commons.extensions.updateTextColors -import org.fossify.commons.extensions.viewBinding -import org.fossify.commons.helpers.NavigationIcon -import org.fossify.commons.helpers.ensureBackgroundThread - -class ManageEventTypesActivity : SimpleActivity(), DeleteEventTypesListener { - - private val binding by viewBinding(ActivityManageEventTypesBinding::inflate) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(binding.root) - setupOptionsMenu() - - setupEdgeToEdge(padBottomSystem = listOf(binding.manageEventTypesList)) - setupMaterialScrollListener(binding.manageEventTypesList, binding.manageEventTypesAppbar) - - getEventTypes() - updateTextColors(binding.manageEventTypesList) - } - - override fun onResume() { - super.onResume() - setupTopAppBar(binding.manageEventTypesAppbar, NavigationIcon.Arrow) - } - - private fun showEventTypeDialog(eventType: EventType? = null) { - EditEventTypeDialog(this, eventType?.copy()) { - getEventTypes() - } - } - - private fun getEventTypes() { - eventsHelper.getEventTypes(this, false) { - val adapter = ManageEventTypesAdapter(this, it, this, binding.manageEventTypesList) { - showEventTypeDialog(it as EventType) - } - binding.manageEventTypesList.adapter = adapter - } - } - - private fun setupOptionsMenu() { - binding.manageEventTypesToolbar.setOnMenuItemClickListener { menuItem -> - when (menuItem.itemId) { - R.id.add_event_type -> showEventTypeDialog() - else -> return@setOnMenuItemClickListener false - } - return@setOnMenuItemClickListener true - } - } - - override fun deleteEventTypes(eventTypes: ArrayList, deleteEvents: Boolean): Boolean { - if (eventTypes.any { it.caldavCalendarId != 0 }) { - toast(R.string.unsync_caldav_calendar) - if (eventTypes.size == 1) { - return false - } - } - - ensureBackgroundThread { - eventsHelper.deleteEventTypes(eventTypes, deleteEvents) - } - - return true - } -} diff --git a/app/src/main/kotlin/org/fossify/calendar/activities/SettingsActivity.kt b/app/src/main/kotlin/org/fossify/calendar/activities/SettingsActivity.kt index b90e85858..ebb569eb0 100644 --- a/app/src/main/kotlin/org/fossify/calendar/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/org/fossify/calendar/activities/SettingsActivity.kt @@ -1,6 +1,5 @@ package org.fossify.calendar.activities -import android.app.Activity import android.app.TimePickerDialog import android.content.ActivityNotFoundException import android.content.Intent @@ -12,13 +11,128 @@ import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.TimeFormat import org.fossify.calendar.R import org.fossify.calendar.databinding.ActivitySettingsBinding -import org.fossify.calendar.dialogs.* -import org.fossify.calendar.extensions.* -import org.fossify.calendar.helpers.* -import org.fossify.calendar.models.EventType -import org.fossify.commons.dialogs.* -import org.fossify.commons.extensions.* -import org.fossify.commons.helpers.* +import org.fossify.calendar.dialogs.ExportEventsDialog +import org.fossify.calendar.dialogs.ManageAutomaticBackupsDialog +import org.fossify.calendar.dialogs.ManageSyncedCalendarsDialog +import org.fossify.calendar.dialogs.SelectCalendarDialog +import org.fossify.calendar.dialogs.SelectCalendarsDialog +import org.fossify.calendar.extensions.calDAVHelper +import org.fossify.calendar.extensions.calendarsDB +import org.fossify.calendar.extensions.cancelScheduledAutomaticBackup +import org.fossify.calendar.extensions.config +import org.fossify.calendar.extensions.eventsHelper +import org.fossify.calendar.extensions.getSyncedCalDAVCalendars +import org.fossify.calendar.extensions.scheduleNextAutomaticBackup +import org.fossify.calendar.extensions.showImportEventsDialog +import org.fossify.calendar.extensions.tryImportEventsFromFile +import org.fossify.calendar.extensions.updateWidgets +import org.fossify.calendar.helpers.ALLOW_CHANGING_TIME_ZONES +import org.fossify.calendar.helpers.ALLOW_CREATING_TASKS +import org.fossify.calendar.helpers.ALLOW_CUSTOMIZE_DAY_COUNT +import org.fossify.calendar.helpers.DAILY_VIEW +import org.fossify.calendar.helpers.DEFAULT_DURATION +import org.fossify.calendar.helpers.DEFAULT_REMINDER_1 +import org.fossify.calendar.helpers.DEFAULT_REMINDER_2 +import org.fossify.calendar.helpers.DEFAULT_REMINDER_3 +import org.fossify.calendar.helpers.DEFAULT_START_TIME +import org.fossify.calendar.helpers.DEFAULT_START_TIME_CURRENT_TIME +import org.fossify.calendar.helpers.DEFAULT_START_TIME_NEXT_FULL_HOUR +import org.fossify.calendar.helpers.DIM_COMPLETED_TASKS +import org.fossify.calendar.helpers.DIM_PAST_EVENTS +import org.fossify.calendar.helpers.DISPLAY_DESCRIPTION +import org.fossify.calendar.helpers.DISPLAY_PAST_EVENTS +import org.fossify.calendar.helpers.EVENTS_LIST_VIEW +import org.fossify.calendar.helpers.Formatter +import org.fossify.calendar.helpers.HIGHLIGHT_WEEKENDS +import org.fossify.calendar.helpers.HIGHLIGHT_WEEKENDS_COLOR +import org.fossify.calendar.helpers.IcsExporter +import org.fossify.calendar.helpers.LAST_EVENT_REMINDER_MINUTES +import org.fossify.calendar.helpers.LAST_EVENT_REMINDER_MINUTES_2 +import org.fossify.calendar.helpers.LAST_EVENT_REMINDER_MINUTES_3 +import org.fossify.calendar.helpers.LAST_VIEW +import org.fossify.calendar.helpers.LIST_WIDGET_VIEW_TO_OPEN +import org.fossify.calendar.helpers.LOOP_REMINDERS +import org.fossify.calendar.helpers.MONTHLY_DAILY_VIEW +import org.fossify.calendar.helpers.MONTHLY_VIEW +import org.fossify.calendar.helpers.PULL_TO_REFRESH +import org.fossify.calendar.helpers.REMINDER_AUDIO_STREAM +import org.fossify.calendar.helpers.REMINDER_OFF +import org.fossify.calendar.helpers.REPLACE_DESCRIPTION +import org.fossify.calendar.helpers.SHOW_GRID +import org.fossify.calendar.helpers.SHOW_MIDNIGHT_SPANNING_EVENTS_AT_TOP +import org.fossify.calendar.helpers.START_WEEKLY_AT +import org.fossify.calendar.helpers.START_WEEK_WITH_CURRENT_DAY +import org.fossify.calendar.helpers.USE_PREVIOUS_EVENT_REMINDERS +import org.fossify.calendar.helpers.VIBRATE +import org.fossify.calendar.helpers.WEEKLY_VIEW +import org.fossify.calendar.helpers.WEEK_NUMBERS +import org.fossify.calendar.helpers.YEARLY_VIEW +import org.fossify.calendar.models.CalendarEntity +import org.fossify.commons.dialogs.ColorPickerDialog +import org.fossify.commons.dialogs.ConfirmationDialog +import org.fossify.commons.dialogs.CustomIntervalPickerDialog +import org.fossify.commons.dialogs.FilePickerDialog +import org.fossify.commons.dialogs.PermissionRequiredDialog +import org.fossify.commons.dialogs.RadioGroupDialog +import org.fossify.commons.dialogs.SelectAlarmSoundDialog +import org.fossify.commons.extensions.beGone +import org.fossify.commons.extensions.beGoneIf +import org.fossify.commons.extensions.beVisibleIf +import org.fossify.commons.extensions.checkAppIconColor +import org.fossify.commons.extensions.formatMinutesToTimeString +import org.fossify.commons.extensions.getAppIconColors +import org.fossify.commons.extensions.getDayOfWeekString +import org.fossify.commons.extensions.getDefaultAlarmSound +import org.fossify.commons.extensions.getFileOutputStream +import org.fossify.commons.extensions.getFontSizeText +import org.fossify.commons.extensions.getFormattedMinutes +import org.fossify.commons.extensions.getProperBackgroundColor +import org.fossify.commons.extensions.getProperPrimaryColor +import org.fossify.commons.extensions.getTimePickerDialogTheme +import org.fossify.commons.extensions.hideKeyboard +import org.fossify.commons.extensions.isDynamicTheme +import org.fossify.commons.extensions.openNotificationSettings +import org.fossify.commons.extensions.setFillWithStroke +import org.fossify.commons.extensions.showErrorToast +import org.fossify.commons.extensions.showPickSecondsDialogHelper +import org.fossify.commons.extensions.storeNewYourAlarmSound +import org.fossify.commons.extensions.toBoolean +import org.fossify.commons.extensions.toFileDirItem +import org.fossify.commons.extensions.toInt +import org.fossify.commons.extensions.toast +import org.fossify.commons.extensions.updateTextColors +import org.fossify.commons.extensions.viewBinding +import org.fossify.commons.helpers.ACCENT_COLOR +import org.fossify.commons.helpers.APP_ICON_COLOR +import org.fossify.commons.helpers.BACKGROUND_COLOR +import org.fossify.commons.helpers.FIRST_DAY_OF_WEEK +import org.fossify.commons.helpers.FONT_SIZE +import org.fossify.commons.helpers.FONT_SIZE_EXTRA_LARGE +import org.fossify.commons.helpers.FONT_SIZE_LARGE +import org.fossify.commons.helpers.FONT_SIZE_MEDIUM +import org.fossify.commons.helpers.FONT_SIZE_SMALL +import org.fossify.commons.helpers.IS_CUSTOMIZING_COLORS +import org.fossify.commons.helpers.IS_GLOBAL_THEME_ENABLED +import org.fossify.commons.helpers.NavigationIcon +import org.fossify.commons.helpers.PERMISSION_READ_CALENDAR +import org.fossify.commons.helpers.PERMISSION_READ_STORAGE +import org.fossify.commons.helpers.PERMISSION_WRITE_CALENDAR +import org.fossify.commons.helpers.PERMISSION_WRITE_STORAGE +import org.fossify.commons.helpers.PRIMARY_COLOR +import org.fossify.commons.helpers.SNOOZE_TIME +import org.fossify.commons.helpers.SUNDAY_FIRST +import org.fossify.commons.helpers.TEXT_COLOR +import org.fossify.commons.helpers.USE_24_HOUR_FORMAT +import org.fossify.commons.helpers.USE_ENGLISH +import org.fossify.commons.helpers.USE_SAME_SNOOZE +import org.fossify.commons.helpers.WAS_USE_ENGLISH_TOGGLED +import org.fossify.commons.helpers.WIDGET_BG_COLOR +import org.fossify.commons.helpers.WIDGET_TEXT_COLOR +import org.fossify.commons.helpers.ensureBackgroundThread +import org.fossify.commons.helpers.isOreoPlus +import org.fossify.commons.helpers.isQPlus +import org.fossify.commons.helpers.isRPlus +import org.fossify.commons.helpers.isTiramisuPlus import org.fossify.commons.models.AlarmSound import org.fossify.commons.models.RadioItem import org.joda.time.DateTime @@ -32,14 +146,16 @@ import java.util.Locale import kotlin.system.exitProcess class SettingsActivity : SimpleActivity() { - private val GET_RINGTONE_URI = 1 - private val PICK_SETTINGS_IMPORT_SOURCE_INTENT = 2 - private val PICK_EVENTS_IMPORT_SOURCE_INTENT = 3 - private val PICK_EVENTS_EXPORT_FILE_INTENT = 4 + companion object { + private const val GET_RINGTONE_URI = 1 + private const val PICK_SETTINGS_IMPORT_SOURCE_INTENT = 2 + private const val PICK_EVENTS_IMPORT_SOURCE_INTENT = 3 + private const val PICK_EVENTS_EXPORT_FILE_INTENT = 4 + } private var mStoredPrimaryColor = 0 - private var eventTypesToExport = listOf() + private var calendarsToExport = listOf() private val binding by viewBinding(ActivitySettingsBinding::inflate) @@ -49,12 +165,15 @@ class SettingsActivity : SimpleActivity() { mStoredPrimaryColor = getProperPrimaryColor() setupEdgeToEdge(padBottomSystem = listOf(binding.settingsNestedScrollview)) - setupMaterialScrollListener(binding.settingsNestedScrollview, binding.settingsAppbar) + setupMaterialScrollListener( + scrollingView = binding.settingsNestedScrollview, + topAppBar = binding.settingsAppbar + ) } override fun onResume() { super.onResume() - setupTopAppBar(binding.settingsAppbar, NavigationIcon.Arrow) + setupTopAppBar(topAppBar = binding.settingsAppbar, navigationIcon = NavigationIcon.Arrow) setupSettingItems() } @@ -63,8 +182,8 @@ class SettingsActivity : SimpleActivity() { setupCustomizeNotifications() setupUseEnglish() setupLanguage() - setupManageEventTypes() - setupManageQuickFilterEventTypes() + setupManageCalendars() + setupManageQuickFilterCalendars() setupHourFormat() setupAllowCreatingTasks() setupStartWeekOn() @@ -89,7 +208,7 @@ class SettingsActivity : SimpleActivity() { setupManageSyncedCalendars() setupDefaultStartTime() setupDefaultDuration() - setupDefaultEventType() + setupDefaultCalendar() setupPullToRefresh() setupDefaultReminder() setupDefaultReminder1() @@ -137,7 +256,11 @@ class SettingsActivity : SimpleActivity() { override fun onStop() { super.onStop() - val reminders = sortedSetOf(config.defaultReminder1, config.defaultReminder2, config.defaultReminder3).filter { it != REMINDER_OFF } + val reminders = sortedSetOf( + config.defaultReminder1, + config.defaultReminder2, + config.defaultReminder3 + ).filter { it != REMINDER_OFF } config.defaultReminder1 = reminders.getOrElse(0) { REMINDER_OFF } config.defaultReminder2 = reminders.getOrElse(1) { REMINDER_OFF } config.defaultReminder3 = reminders.getOrElse(2) { REMINDER_OFF } @@ -148,25 +271,25 @@ class SettingsActivity : SimpleActivity() { if (requestCode == GET_RINGTONE_URI && resultCode == RESULT_OK && resultData != null) { val newAlarmSound = storeNewYourAlarmSound(resultData) updateReminderSound(newAlarmSound) - } else if (requestCode == PICK_SETTINGS_IMPORT_SOURCE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) { + } else if (requestCode == PICK_SETTINGS_IMPORT_SOURCE_INTENT && resultCode == RESULT_OK && resultData != null && resultData.data != null) { val inputStream = contentResolver.openInputStream(resultData.data!!) parseFile(inputStream) - } else if (requestCode == PICK_EVENTS_IMPORT_SOURCE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) { + } else if (requestCode == PICK_EVENTS_IMPORT_SOURCE_INTENT && resultCode == RESULT_OK && resultData != null && resultData.data != null) { tryImportEventsFromFile(resultData.data!!) - } else if (requestCode == PICK_EVENTS_EXPORT_FILE_INTENT && resultCode == Activity.RESULT_OK && resultData != null && resultData.data != null) { + } else if (requestCode == PICK_EVENTS_EXPORT_FILE_INTENT && resultCode == RESULT_OK && resultData != null && resultData.data != null) { val outputStream = contentResolver.openOutputStream(resultData.data!!) - exportEventsTo(eventTypesToExport, outputStream) + exportEventsTo(calendarsToExport, outputStream) } } private fun checkPrimaryColor() { if (getProperPrimaryColor() != mStoredPrimaryColor) { ensureBackgroundThread { - val eventTypes = eventsHelper.getEventTypesSync() - if (eventTypes.filter { it.caldavCalendarId == 0 }.size == 1) { - val eventType = eventTypes.first { it.caldavCalendarId == 0 } - eventType.color = getProperPrimaryColor() - eventsHelper.insertOrUpdateEventTypeSync(eventType) + val calendars = eventsHelper.getCalendarsSync() + if (calendars.filter { it.caldavCalendarId == 0 }.size == 1) { + val calendar = calendars.first { it.caldavCalendarId == 0 } + calendar.color = getProperPrimaryColor() + eventsHelper.insertOrUpdateCalendarSync(calendar) } } } @@ -203,19 +326,19 @@ class SettingsActivity : SimpleActivity() { } } - private fun setupManageEventTypes() { - binding.settingsManageEventTypesHolder.setOnClickListener { - startActivity(Intent(this, ManageEventTypesActivity::class.java)) + private fun setupManageCalendars() { + binding.settingsManageCalendarsHolder.setOnClickListener { + startActivity(Intent(this, ManageCalendarsActivity::class.java)) } } - private fun setupManageQuickFilterEventTypes() = binding.apply { - settingsManageQuickFilterEventTypesHolder.setOnClickListener { + private fun setupManageQuickFilterCalendars() = binding.apply { + settingsManageQuickFilterCalendarsHolder.setOnClickListener { showQuickFilterPicker() } - eventsHelper.getEventTypes(this@SettingsActivity, false) { - settingsManageQuickFilterEventTypesHolder.beGoneIf(it.size < 2) + eventsHelper.getCalendars(this@SettingsActivity, false) { + settingsManageQuickFilterCalendarsHolder.beGoneIf(it.size < 2) } } @@ -287,8 +410,8 @@ class SettingsActivity : SimpleActivity() { config.getSyncedCalendarIdsAsList().forEach { calDAVHelper.deleteCalDAVCalendarEvents(it.toLong()) } - eventTypesDB.deleteEventTypesWithCalendarId(config.getSyncedCalendarIdsAsList()) - updateDefaultEventTypeText() + calendarsDB.deleteCalendarsWithCalendarIds(config.getSyncedCalendarIdsAsList()) + updateDefaultCalendarText() } } } @@ -296,10 +419,10 @@ class SettingsActivity : SimpleActivity() { private fun showCalendarPicker() = binding.apply { val oldCalendarIds = config.getSyncedCalendarIdsAsList() - SelectCalendarsDialog(this@SettingsActivity) { + ManageSyncedCalendarsDialog(this@SettingsActivity) { val newCalendarIds = config.getSyncedCalendarIdsAsList() if (newCalendarIds.isEmpty() && !config.caldavSync) { - return@SelectCalendarsDialog + return@ManageSyncedCalendarsDialog } settingsManageSyncedCalendarsHolder.beVisibleIf(newCalendarIds.isNotEmpty()) @@ -312,16 +435,23 @@ class SettingsActivity : SimpleActivity() { ensureBackgroundThread { if (newCalendarIds.isNotEmpty()) { - val existingEventTypeNames = eventsHelper.getEventTypesSync().map { + val existingCalendarNames = eventsHelper.getCalendarsSync().map { it.getDisplayTitle().lowercase(Locale.getDefault()) } as ArrayList getSyncedCalDAVCalendars().forEach { val calendarTitle = it.getFullTitle() - if (!existingEventTypeNames.contains(calendarTitle.lowercase(Locale.getDefault()))) { - val eventType = EventType(null, it.displayName, it.color, it.id, it.displayName, it.accountName) - existingEventTypeNames.add(calendarTitle.lowercase(Locale.getDefault())) - eventsHelper.insertOrUpdateEventType(this@SettingsActivity, eventType) + if (!existingCalendarNames.contains(calendarTitle.lowercase(Locale.getDefault()))) { + val calendar = CalendarEntity( + id = null, + title = it.displayName, + color = it.color, + caldavCalendarId = it.id, + caldavDisplayName = it.displayName, + caldavEmail = it.accountName + ) + existingCalendarNames.add(calendarTitle.lowercase(Locale.getDefault())) + eventsHelper.insertOrUpdateCalendar(this@SettingsActivity, calendar) } } @@ -337,20 +467,20 @@ class SettingsActivity : SimpleActivity() { val removedCalendarIds = oldCalendarIds.filter { !newCalendarIds.contains(it) } removedCalendarIds.forEach { calDAVHelper.deleteCalDAVCalendarEvents(it.toLong()) - eventsHelper.getEventTypeWithCalDAVCalendarId(it)?.apply { - eventsHelper.deleteEventTypes(arrayListOf(this), true) + eventsHelper.getCalendarWithCalDAVCalendarId(it)?.apply { + eventsHelper.deleteCalendars(arrayListOf(this), true) } } - eventTypesDB.deleteEventTypesWithCalendarId(removedCalendarIds) - updateDefaultEventTypeText() + calendarsDB.deleteCalendarsWithCalendarIds(removedCalendarIds) + updateDefaultCalendarText() } } } private fun showQuickFilterPicker() { - SelectEventTypesDialog(this, config.quickFilterEventTypes) { - config.quickFilterEventTypes = it + SelectCalendarsDialog(this, config.quickFilterCalendars) { + config.quickFilterCalendars = it } } @@ -359,7 +489,10 @@ class SettingsActivity : SimpleActivity() { RadioItem(DateTimeConstants.SUNDAY, getString(org.fossify.commons.R.string.sunday)), RadioItem(DateTimeConstants.MONDAY, getString(org.fossify.commons.R.string.monday)), RadioItem(DateTimeConstants.TUESDAY, getString(org.fossify.commons.R.string.tuesday)), - RadioItem(DateTimeConstants.WEDNESDAY, getString(org.fossify.commons.R.string.wednesday)), + RadioItem( + DateTimeConstants.WEDNESDAY, + getString(org.fossify.commons.R.string.wednesday) + ), RadioItem(DateTimeConstants.THURSDAY, getString(org.fossify.commons.R.string.thursday)), RadioItem(DateTimeConstants.FRIDAY, getString(org.fossify.commons.R.string.friday)), RadioItem(DateTimeConstants.SATURDAY, getString(org.fossify.commons.R.string.saturday)), @@ -386,12 +519,21 @@ class SettingsActivity : SimpleActivity() { } private fun setupHighlightWeekendsColor() = binding.apply { - settingsHighlightWeekendsColor.setFillWithStroke(config.highlightWeekendsColor, getProperBackgroundColor()) + settingsHighlightWeekendsColor.setFillWithStroke( + config.highlightWeekendsColor, + getProperBackgroundColor() + ) settingsHighlightWeekendsColorHolder.setOnClickListener { - ColorPickerDialog(this@SettingsActivity, config.highlightWeekendsColor) { wasPositivePressed, color -> + ColorPickerDialog( + activity = this@SettingsActivity, + color = config.highlightWeekendsColor + ) { wasPositivePressed, color -> if (wasPositivePressed) { config.highlightWeekendsColor = color - settingsHighlightWeekendsColor.setFillWithStroke(color, getProperBackgroundColor()) + settingsHighlightWeekendsColor.setFillWithStroke( + color, + getProperBackgroundColor() + ) } } } @@ -399,7 +541,10 @@ class SettingsActivity : SimpleActivity() { private fun setupDeleteAllEvents() = binding.apply { settingsDeleteAllEventsHolder.setOnClickListener { - ConfirmationDialog(this@SettingsActivity, messageId = R.string.delete_all_events_confirmation) { + ConfirmationDialog( + activity = this@SettingsActivity, + messageId = R.string.delete_all_events_confirmation + ) { eventsHelper.deleteAllEvents() } } @@ -429,7 +574,11 @@ class SettingsActivity : SimpleActivity() { val items = ArrayList() (0..16).mapTo(items) { RadioItem(it, getHoursString(it)) } - RadioGroupDialog(this@SettingsActivity, items, config.startWeeklyAt) { + RadioGroupDialog( + activity = this@SettingsActivity, + items = items, + checkedItemId = config.startWeeklyAt + ) { config.startWeeklyAt = it as Int settingsStartWeeklyAt.text = getHoursString(it) } @@ -483,12 +632,12 @@ class SettingsActivity : SimpleActivity() { settingsReminderSoundHolder.setOnClickListener { SelectAlarmSoundDialog( - this@SettingsActivity, - config.reminderSoundUri, - config.reminderAudioStream, - GET_RINGTONE_URI, - RingtoneManager.TYPE_NOTIFICATION, - false, + activity = this@SettingsActivity, + currentUri = config.reminderSoundUri, + audioStream = config.reminderAudioStream, + pickAudioIntentId = GET_RINGTONE_URI, + type = RingtoneManager.TYPE_NOTIFICATION, + loopAudio = false, onAlarmPicked = { if (it != null) { updateReminderSound(it) @@ -516,11 +665,18 @@ class SettingsActivity : SimpleActivity() { val items = arrayListOf( RadioItem(AudioManager.STREAM_ALARM, getString(R.string.alarm_stream)), RadioItem(AudioManager.STREAM_SYSTEM, getString(R.string.system_stream)), - RadioItem(AudioManager.STREAM_NOTIFICATION, getString(R.string.notification_stream)), + RadioItem( + AudioManager.STREAM_NOTIFICATION, + getString(R.string.notification_stream) + ), RadioItem(AudioManager.STREAM_RING, getString(R.string.ring_stream)) ) - RadioGroupDialog(this@SettingsActivity, items, config.reminderAudioStream) { + RadioGroupDialog( + activity = this@SettingsActivity, + items = items, + checkedItemId = config.reminderAudioStream + ) { config.reminderAudioStream = it as Int settingsReminderAudioStream.text = getAudioStreamText() } @@ -617,7 +773,11 @@ class SettingsActivity : SimpleActivity() { } private fun toggleDefaultRemindersVisibility(show: Boolean) = binding.apply { - arrayOf(settingsDefaultReminder1Holder, settingsDefaultReminder2Holder, settingsDefaultReminder3Holder).forEach { + arrayOf( + settingsDefaultReminder1Holder, + settingsDefaultReminder2Holder, + settingsDefaultReminder3Holder + ).forEach { it.beVisibleIf(show) } } @@ -666,7 +826,10 @@ class SettingsActivity : SimpleActivity() { RadioItem(FONT_SIZE_SMALL, getString(org.fossify.commons.R.string.small)), RadioItem(FONT_SIZE_MEDIUM, getString(org.fossify.commons.R.string.medium)), RadioItem(FONT_SIZE_LARGE, getString(org.fossify.commons.R.string.large)), - RadioItem(FONT_SIZE_EXTRA_LARGE, getString(org.fossify.commons.R.string.extra_large)) + RadioItem( + FONT_SIZE_EXTRA_LARGE, + getString(org.fossify.commons.R.string.extra_large) + ) ) RadioGroupDialog(this@SettingsActivity, items, config.fontSize) { @@ -699,7 +862,11 @@ class SettingsActivity : SimpleActivity() { RadioItem(LAST_VIEW, getString(R.string.last_view)) ) - RadioGroupDialog(this@SettingsActivity, items, config.listWidgetViewToOpen) { + RadioGroupDialog( + activity = this@SettingsActivity, + items = items, + checkedItemId = config.listWidgetViewToOpen + ) { config.listWidgetViewToOpen = it as Int settingsListWidgetViewToOpen.text = getDefaultViewText() updateWidgets() @@ -754,18 +921,28 @@ class SettingsActivity : SimpleActivity() { val items = ArrayList() items.add(RadioItem(DEFAULT_START_TIME_CURRENT_TIME, getString(R.string.current_time))) - items.add(RadioItem(DEFAULT_START_TIME_NEXT_FULL_HOUR, getString(R.string.next_full_hour))) + items.add( + RadioItem( + DEFAULT_START_TIME_NEXT_FULL_HOUR, + getString(R.string.next_full_hour) + ) + ) items.add(RadioItem(0, getString(R.string.other_time))) - RadioGroupDialog(this@SettingsActivity, items, currentDefaultTime) { + RadioGroupDialog( + activity = this@SettingsActivity, + items = items, + checkedItemId = currentDefaultTime + ) { if (it as Int == DEFAULT_START_TIME_NEXT_FULL_HOUR || it == DEFAULT_START_TIME_CURRENT_TIME) { config.defaultStartTime = it updateDefaultStartTimeText() } else { - val timeListener = TimePickerDialog.OnTimeSetListener { view, hourOfDay, minute -> - config.defaultStartTime = hourOfDay * 60 + minute - updateDefaultStartTimeText() - } + val timeListener = + TimePickerDialog.OnTimeSetListener { view, hourOfDay, minute -> + config.defaultStartTime = hourOfDay * 60 + minute + updateDefaultStartTimeText() + } val currentDateTime = DateTime.now() @@ -837,33 +1014,41 @@ class SettingsActivity : SimpleActivity() { } } - private fun setupDefaultEventType() = binding.apply { - updateDefaultEventTypeText() - settingsDefaultEventType.text = getString(R.string.last_used_one) - settingsDefaultEventTypeHolder.setOnClickListener { - SelectEventTypeDialog(this@SettingsActivity, config.defaultEventTypeId, true, false, true, true, false) { - config.defaultEventTypeId = it.id!! - updateDefaultEventTypeText() + private fun setupDefaultCalendar() = binding.apply { + updateDefaultCalendarText() + settingsDefaultCalendar.text = getString(R.string.last_used_one) + settingsDefaultCalendarHolder.setOnClickListener { + SelectCalendarDialog( + activity = this@SettingsActivity, + currCalendar = config.defaultCalendarId, + showCalDAVCalendars = true, + showNewCalendarOption = false, + addLastUsedOneAsFirstOption = true, + showOnlyWritable = true, + showManageCalendars = false + ) { + config.defaultCalendarId = it.id!! + updateDefaultCalendarText() } } } - private fun updateDefaultEventTypeText() { - if (config.defaultEventTypeId == -1L) { + private fun updateDefaultCalendarText() { + if (config.defaultCalendarId == -1L) { runOnUiThread { - binding.settingsDefaultEventType.text = getString(R.string.last_used_one) + binding.settingsDefaultCalendar.text = getString(R.string.last_used_one) } } else { ensureBackgroundThread { - val eventType = eventTypesDB.getEventTypeWithId(config.defaultEventTypeId) - if (eventType != null) { - config.lastUsedCaldavCalendarId = eventType.caldavCalendarId + val calendar = calendarsDB.getCalendarWithId(config.defaultCalendarId) + if (calendar != null) { + config.lastUsedCaldavCalendarId = calendar.caldavCalendarId runOnUiThread { - binding.settingsDefaultEventType.text = eventType.title + binding.settingsDefaultCalendar.text = calendar.title } } else { - config.defaultEventTypeId = -1 - updateDefaultEventTypeText() + config.defaultCalendarId = -1 + updateDefaultCalendarText() } } } @@ -988,7 +1173,10 @@ class SettingsActivity : SimpleActivity() { try { startActivityForResult(this, PICK_SETTINGS_IMPORT_SOURCE_INTENT) } catch (e: ActivityNotFoundException) { - toast(org.fossify.commons.R.string.system_service_disabled, Toast.LENGTH_LONG) + toast( + org.fossify.commons.R.string.system_service_disabled, + Toast.LENGTH_LONG + ) } catch (e: Exception) { showErrorToast(e) } @@ -1050,7 +1238,9 @@ class SettingsActivity : SimpleActivity() { WIDGET_TEXT_COLOR -> config.widgetTextColor = value.toInt() WEEK_NUMBERS -> config.showWeekNumbers = value.toBoolean() START_WEEKLY_AT -> config.startWeeklyAt = value.toInt() - SHOW_MIDNIGHT_SPANNING_EVENTS_AT_TOP -> config.showMidnightSpanningEventsAtTop = value.toBoolean() + SHOW_MIDNIGHT_SPANNING_EVENTS_AT_TOP -> config.showMidnightSpanningEventsAtTop = + value.toBoolean() + ALLOW_CUSTOMIZE_DAY_COUNT -> config.allowCustomizeDayCount = value.toBoolean() START_WEEK_WITH_CURRENT_DAY -> config.startWeekWithCurrentDay = value.toBoolean() VIBRATE -> config.vibrateOnReminder = value.toBoolean() @@ -1087,7 +1277,7 @@ class SettingsActivity : SimpleActivity() { } runOnUiThread { - val msg = if (configValues.size > 0) { + val msg = if (configValues.isNotEmpty()) { org.fossify.commons.R.string.settings_imported_successfully } else { org.fossify.commons.R.string.no_entries_for_importing @@ -1112,13 +1302,20 @@ class SettingsActivity : SimpleActivity() { try { startActivityForResult(this, PICK_EVENTS_IMPORT_SOURCE_INTENT) } catch (e: ActivityNotFoundException) { - toast(org.fossify.commons.R.string.system_service_disabled, Toast.LENGTH_LONG) + toast( + org.fossify.commons.R.string.system_service_disabled, + Toast.LENGTH_LONG + ) } catch (e: Exception) { showErrorToast(e) } } } else { - PermissionRequiredDialog(this, org.fossify.commons.R.string.allow_notifications_reminders, { openNotificationSettings() }) + PermissionRequiredDialog( + activity = this, + textId = org.fossify.commons.R.string.allow_notifications_reminders, + positiveActionCallback = { openNotificationSettings() } + ) } } } else { @@ -1139,8 +1336,12 @@ class SettingsActivity : SimpleActivity() { private fun tryExportEvents() { if (isQPlus()) { - ExportEventsDialog(this, config.lastExportPath, true) { file, eventTypes -> - eventTypesToExport = eventTypes + ExportEventsDialog( + activity = this, + path = config.lastExportPath, + hidePath = true + ) { file, calendars -> + calendarsToExport = calendars hideKeyboard() Intent(Intent.ACTION_CREATE_DOCUMENT).apply { @@ -1151,7 +1352,10 @@ class SettingsActivity : SimpleActivity() { try { startActivityForResult(this, PICK_EVENTS_EXPORT_FILE_INTENT) } catch (e: ActivityNotFoundException) { - toast(org.fossify.commons.R.string.system_service_disabled, Toast.LENGTH_LONG) + toast( + org.fossify.commons.R.string.system_service_disabled, + Toast.LENGTH_LONG + ) } catch (e: Exception) { showErrorToast(e) } @@ -1160,9 +1364,13 @@ class SettingsActivity : SimpleActivity() { } else { handlePermission(PERMISSION_WRITE_STORAGE) { granted -> if (granted) { - ExportEventsDialog(this, config.lastExportPath, false) { file, eventTypes -> + ExportEventsDialog( + activity = this, + path = config.lastExportPath, + hidePath = false + ) { file, calendars -> getFileOutputStream(file.toFileDirItem(this), true) { - exportEventsTo(eventTypes, it) + exportEventsTo(calendars, it) } } } @@ -1170,9 +1378,14 @@ class SettingsActivity : SimpleActivity() { } } - private fun exportEventsTo(eventTypes: List, outputStream: OutputStream?) { + private fun exportEventsTo(calendars: List, outputStream: OutputStream?) { ensureBackgroundThread { - val events = eventsHelper.getEventsToExport(eventTypes, config.exportEvents, config.exportTasks, config.exportPastEntries) + val events = eventsHelper.getEventsToExport( + calendars = calendars, + exportEvents = config.exportEvents, + exportTasks = config.exportTasks, + exportPastEntries = config.exportPastEntries + ) if (events.isEmpty()) { toast(org.fossify.commons.R.string.no_entries_for_exporting) } else { diff --git a/app/src/main/kotlin/org/fossify/calendar/activities/TaskActivity.kt b/app/src/main/kotlin/org/fossify/calendar/activities/TaskActivity.kt index 94dfa560a..f2970c91f 100644 --- a/app/src/main/kotlin/org/fossify/calendar/activities/TaskActivity.kt +++ b/app/src/main/kotlin/org/fossify/calendar/activities/TaskActivity.kt @@ -10,23 +10,110 @@ import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.TimeFormat import org.fossify.calendar.R import org.fossify.calendar.databinding.ActivityTaskBinding -import org.fossify.calendar.dialogs.* -import org.fossify.calendar.extensions.* -import org.fossify.calendar.helpers.* +import org.fossify.calendar.dialogs.DeleteEventDialog +import org.fossify.calendar.dialogs.EditRepeatingEventDialog +import org.fossify.calendar.dialogs.ReminderWarningDialog +import org.fossify.calendar.dialogs.RepeatLimitTypePickerDialog +import org.fossify.calendar.dialogs.RepeatRuleWeeklyDialog +import org.fossify.calendar.dialogs.SelectCalendarDialog +import org.fossify.calendar.extensions.calendarsDB +import org.fossify.calendar.extensions.config +import org.fossify.calendar.extensions.eventsDB +import org.fossify.calendar.extensions.eventsHelper +import org.fossify.calendar.extensions.getNewEventTimestampFromCode +import org.fossify.calendar.extensions.getRepetitionText +import org.fossify.calendar.extensions.getShortDaysFromBitmask +import org.fossify.calendar.extensions.isTaskCompleted +import org.fossify.calendar.extensions.isXMonthlyRepetition +import org.fossify.calendar.extensions.isXWeeklyRepetition +import org.fossify.calendar.extensions.isXYearlyRepetition +import org.fossify.calendar.extensions.notifyEvent +import org.fossify.calendar.extensions.seconds +import org.fossify.calendar.extensions.shareEvents +import org.fossify.calendar.extensions.showEventRepeatIntervalDialog +import org.fossify.calendar.extensions.updateTaskCompletion +import org.fossify.calendar.helpers.CALENDAR_ID +import org.fossify.calendar.helpers.DELETE_ALL_OCCURRENCES +import org.fossify.calendar.helpers.DELETE_FUTURE_OCCURRENCES +import org.fossify.calendar.helpers.DELETE_SELECTED_OCCURRENCE +import org.fossify.calendar.helpers.EDIT_ALL_OCCURRENCES +import org.fossify.calendar.helpers.EDIT_FUTURE_OCCURRENCES +import org.fossify.calendar.helpers.EDIT_SELECTED_OCCURRENCE +import org.fossify.calendar.helpers.EVENT_COLOR +import org.fossify.calendar.helpers.EVENT_ID +import org.fossify.calendar.helpers.EVENT_OCCURRENCE_TS +import org.fossify.calendar.helpers.FLAG_ALL_DAY +import org.fossify.calendar.helpers.FLAG_TASK_COMPLETED +import org.fossify.calendar.helpers.Formatter +import org.fossify.calendar.helpers.IS_DUPLICATE_INTENT +import org.fossify.calendar.helpers.IS_NEW_EVENT +import org.fossify.calendar.helpers.IS_TASK_COMPLETED +import org.fossify.calendar.helpers.LOCAL_CALENDAR_ID +import org.fossify.calendar.helpers.NEW_EVENT_START_TS +import org.fossify.calendar.helpers.ORIGINAL_START_TS +import org.fossify.calendar.helpers.REMINDER_1_MINUTES +import org.fossify.calendar.helpers.REMINDER_2_MINUTES +import org.fossify.calendar.helpers.REMINDER_3_MINUTES +import org.fossify.calendar.helpers.REMINDER_NOTIFICATION +import org.fossify.calendar.helpers.REMINDER_OFF +import org.fossify.calendar.helpers.REPEAT_INTERVAL +import org.fossify.calendar.helpers.REPEAT_LAST_DAY +import org.fossify.calendar.helpers.REPEAT_LIMIT +import org.fossify.calendar.helpers.REPEAT_ORDER_WEEKDAY +import org.fossify.calendar.helpers.REPEAT_ORDER_WEEKDAY_USE_LAST +import org.fossify.calendar.helpers.REPEAT_RULE +import org.fossify.calendar.helpers.REPEAT_SAME_DAY +import org.fossify.calendar.helpers.START_TS +import org.fossify.calendar.helpers.TASK +import org.fossify.calendar.helpers.TYPE_TASK +import org.fossify.calendar.helpers.generateImportId +import org.fossify.calendar.models.CalendarEntity import org.fossify.calendar.models.Event -import org.fossify.calendar.models.EventType import org.fossify.calendar.models.Reminder import org.fossify.commons.dialogs.ColorPickerDialog import org.fossify.commons.dialogs.ConfirmationAdvancedDialog import org.fossify.commons.dialogs.PermissionRequiredDialog import org.fossify.commons.dialogs.RadioGroupDialog -import org.fossify.commons.extensions.* -import org.fossify.commons.helpers.* +import org.fossify.commons.extensions.addBitIf +import org.fossify.commons.extensions.applyColorFilter +import org.fossify.commons.extensions.beGoneIf +import org.fossify.commons.extensions.beVisibleIf +import org.fossify.commons.extensions.checkAppSideloading +import org.fossify.commons.extensions.getContrastColor +import org.fossify.commons.extensions.getDatePickerDialogTheme +import org.fossify.commons.extensions.getFormattedMinutes +import org.fossify.commons.extensions.getProperBackgroundColor +import org.fossify.commons.extensions.getProperPrimaryColor +import org.fossify.commons.extensions.getProperTextColor +import org.fossify.commons.extensions.getTimePickerDialogTheme +import org.fossify.commons.extensions.hideKeyboard +import org.fossify.commons.extensions.isDynamicTheme +import org.fossify.commons.extensions.isGone +import org.fossify.commons.extensions.openNotificationSettings +import org.fossify.commons.extensions.removeBit +import org.fossify.commons.extensions.setFillWithStroke +import org.fossify.commons.extensions.showPickSecondsDialogHelper +import org.fossify.commons.extensions.toast +import org.fossify.commons.extensions.updateTextColors +import org.fossify.commons.extensions.value +import org.fossify.commons.extensions.viewBinding +import org.fossify.commons.helpers.EVERY_DAY_BIT +import org.fossify.commons.helpers.FRIDAY_BIT +import org.fossify.commons.helpers.MONDAY_BIT +import org.fossify.commons.helpers.NavigationIcon +import org.fossify.commons.helpers.SATURDAY_BIT +import org.fossify.commons.helpers.SAVE_DISCARD_PROMPT_INTERVAL +import org.fossify.commons.helpers.SUNDAY_BIT +import org.fossify.commons.helpers.THURSDAY_BIT +import org.fossify.commons.helpers.TUESDAY_BIT +import org.fossify.commons.helpers.WEDNESDAY_BIT +import org.fossify.commons.helpers.ensureBackgroundThread +import org.fossify.commons.helpers.getJavaDayOfWeekFromISO import org.fossify.commons.models.RadioItem import org.joda.time.DateTime class TaskActivity : SimpleActivity() { - private var mEventTypeId = LOCAL_CALENDAR_ID + private var mCalendarId = LOCAL_CALENDAR_ID private lateinit var mTaskDateTime: DateTime private lateinit var mTask: Event @@ -74,11 +161,13 @@ class TaskActivity : SimpleActivity() { return@ensureBackgroundThread } - val storedEventTypes = eventTypesDB.getEventTypes().toMutableList() as ArrayList - val localEventType = storedEventTypes.firstOrNull { it.id == config.lastUsedLocalEventTypeId } + val storedCalendars = + calendarsDB.getCalendars().toMutableList() as ArrayList + val localCalendar = + storedCalendars.firstOrNull { it.id == config.lastUsedLocalCalendarId } runOnUiThread { if (!isDestroyed && !isFinishing) { - gotTask(savedInstanceState, localEventType, task) + gotTask(savedInstanceState, localCalendar, task) } } } @@ -137,14 +226,14 @@ class TaskActivity : SimpleActivity() { val reminders = getReminders() val originalReminders = mTask.getReminders() return binding.taskTitle.text.toString() != mTask.title || - binding.taskDescription.text.toString() != mTask.description || - reminders != originalReminders || - mRepeatInterval != mTask.repeatInterval || - mRepeatRule != mTask.repeatRule || - mRepeatLimit != mTask.repeatLimit || - mEventTypeId != mTask.eventType || - mEventColor != mTask.color || - hasTimeChanged + binding.taskDescription.text.toString() != mTask.description || + reminders != originalReminders || + mRepeatInterval != mTask.repeatInterval || + mRepeatRule != mTask.repeatRule || + mRepeatLimit != mTask.repeatLimit || + mCalendarId != mTask.calendarId || + mEventColor != mTask.color || + hasTimeChanged } override fun onBackPressedCompat(): Boolean { @@ -184,7 +273,7 @@ class TaskActivity : SimpleActivity() { outState.apply { putSerializable(TASK, mTask) putLong(START_TS, mTaskDateTime.seconds()) - putLong(EVENT_TYPE_ID, mEventTypeId) + putLong(CALENDAR_ID, mCalendarId) putInt(REMINDER_1_MINUTES, mReminder1Minutes) putInt(REMINDER_2_MINUTES, mReminder2Minutes) @@ -194,7 +283,7 @@ class TaskActivity : SimpleActivity() { putInt(REPEAT_RULE, mRepeatRule) putLong(REPEAT_LIMIT, mRepeatLimit) - putLong(EVENT_TYPE_ID, mEventTypeId) + putLong(CALENDAR_ID, mCalendarId) putBoolean(IS_NEW_EVENT, mIsNewTask) putLong(ORIGINAL_START_TS, mOriginalStartTS) putInt(EVENT_COLOR, mEventColor) @@ -212,7 +301,7 @@ class TaskActivity : SimpleActivity() { savedInstanceState.apply { mTask = getSerializable(TASK) as Event mTaskDateTime = Formatter.getDateTimeFromTS(getLong(START_TS)) - mEventTypeId = getLong(EVENT_TYPE_ID) + mCalendarId = getLong(CALENDAR_ID) mReminder1Minutes = getInt(REMINDER_1_MINUTES) mReminder2Minutes = getInt(REMINDER_2_MINUTES) @@ -221,13 +310,13 @@ class TaskActivity : SimpleActivity() { mRepeatInterval = getInt(REPEAT_INTERVAL) mRepeatRule = getInt(REPEAT_RULE) mRepeatLimit = getLong(REPEAT_LIMIT) - mEventTypeId = getLong(EVENT_TYPE_ID) + mCalendarId = getLong(CALENDAR_ID) mIsNewTask = getBoolean(IS_NEW_EVENT) mOriginalStartTS = getLong(ORIGINAL_START_TS) mEventColor = getInt(EVENT_COLOR) } - updateEventType() + updateCalendar() updateTexts() setupMarkCompleteButton() checkRepeatTexts(mRepeatInterval) @@ -235,12 +324,13 @@ class TaskActivity : SimpleActivity() { updateActionBarTitle() } - private fun gotTask(savedInstanceState: Bundle?, localEventType: EventType?, task: Event?) { - if (localEventType == null) { - config.lastUsedLocalEventTypeId = LOCAL_CALENDAR_ID + private fun gotTask(savedInstanceState: Bundle?, localCalendar: CalendarEntity?, task: Event?) { + if (localCalendar == null) { + config.lastUsedLocalCalendarId = LOCAL_CALENDAR_ID } - mEventTypeId = if (config.defaultEventTypeId == -1L) config.lastUsedLocalEventTypeId else config.defaultEventTypeId + mCalendarId = + if (config.defaultCalendarId == -1L) config.lastUsedLocalCalendarId else config.defaultCalendarId if (task != null) { mTask = task @@ -257,9 +347,12 @@ class TaskActivity : SimpleActivity() { } else { mTask = Event(null) config.apply { - mReminder1Minutes = if (usePreviousEventReminders && lastEventReminderMinutes1 >= -1) lastEventReminderMinutes1 else defaultReminder1 - mReminder2Minutes = if (usePreviousEventReminders && lastEventReminderMinutes2 >= -1) lastEventReminderMinutes2 else defaultReminder2 - mReminder3Minutes = if (usePreviousEventReminders && lastEventReminderMinutes3 >= -1) lastEventReminderMinutes3 else defaultReminder3 + mReminder1Minutes = + if (usePreviousEventReminders && lastEventReminderMinutes1 >= -1) lastEventReminderMinutes1 else defaultReminder1 + mReminder2Minutes = + if (usePreviousEventReminders && lastEventReminderMinutes2 >= -1) lastEventReminderMinutes2 else defaultReminder2 + mReminder3Minutes = + if (usePreviousEventReminders && lastEventReminderMinutes3 >= -1) lastEventReminderMinutes3 else defaultReminder3 } if (savedInstanceState == null) { @@ -275,7 +368,7 @@ class TaskActivity : SimpleActivity() { taskDate.setOnClickListener { setupDate() } taskTime.setOnClickListener { setupTime() } - taskTypeHolder.setOnClickListener { showEventTypeDialog() } + taskTypeHolder.setOnClickListener { showCalendarDialog() } taskRepetition.setOnClickListener { showRepeatIntervalDialog() } taskRepetitionRuleHolder.setOnClickListener { showRepetitionRuleDialog() } taskRepetitionLimitHolder.setOnClickListener { showRepetitionTypePicker() } @@ -302,7 +395,7 @@ class TaskActivity : SimpleActivity() { setupMarkCompleteButton() if (savedInstanceState == null) { - updateEventType() + updateCalendar() updateTexts() } } @@ -315,7 +408,7 @@ class TaskActivity : SimpleActivity() { window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN) binding.taskToolbar.title = getString(R.string.edit_task) - mEventTypeId = mTask.eventType + mCalendarId = mTask.calendarId mReminder1Minutes = mTask.reminder1Minutes mReminder2Minutes = mTask.reminder2Minutes mReminder3Minutes = mTask.reminder3Minutes @@ -352,7 +445,7 @@ class TaskActivity : SimpleActivity() { reminder2Type = mReminder2Type reminder3Minutes = mReminder3Minutes reminder3Type = mReminder3Type - eventType = mEventTypeId + calendarId = mCalendarId } } @@ -415,7 +508,7 @@ class TaskActivity : SimpleActivity() { } } - config.lastUsedLocalEventTypeId = mEventTypeId + config.lastUsedLocalCalendarId = mCalendarId mTask.apply { startTS = mTaskDateTime.withSecondOfMinute(0).withMillisOfSecond(0).seconds() endTS = startTS @@ -432,7 +525,7 @@ class TaskActivity : SimpleActivity() { importId = newImportId flags = mTask.flags.addBitIf(binding.taskAllDay.isChecked, FLAG_ALL_DAY) lastUpdated = System.currentTimeMillis() - eventType = mEventTypeId + calendarId = mCalendarId type = TYPE_TASK reminder1Minutes = reminder1.minutes @@ -455,7 +548,11 @@ class TaskActivity : SimpleActivity() { storeTask(wasRepeatable) } } else { - PermissionRequiredDialog(this, org.fossify.commons.R.string.allow_notifications_reminders, { openNotificationSettings() }) + PermissionRequiredDialog( + activity = this, + textId = org.fossify.commons.R.string.allow_notifications_reminders, + positiveActionCallback = { openNotificationSettings() } + ) } } } else { @@ -469,7 +566,9 @@ class TaskActivity : SimpleActivity() { hideKeyboard() if (DateTime.now().isAfter(mTaskDateTime.millis)) { - if (mTask.repeatInterval == 0 && mTask.getReminders().any { it.type == REMINDER_NOTIFICATION }) { + if (mTask.repeatInterval == 0 && mTask.getReminders() + .any { it.type == REMINDER_NOTIFICATION } + ) { notifyEvent(mTask) } } @@ -530,9 +629,21 @@ class TaskActivity : SimpleActivity() { DeleteEventDialog(this, arrayListOf(mTask.id!!), mTask.repeatInterval > 0, isTask = true) { ensureBackgroundThread { when (it) { - DELETE_SELECTED_OCCURRENCE -> eventsHelper.deleteRepeatingEventOccurrence(mTask.id!!, mTaskOccurrenceTS, false) - DELETE_FUTURE_OCCURRENCES -> eventsHelper.addEventRepeatLimit(mTask.id!!, mTaskOccurrenceTS) - DELETE_ALL_OCCURRENCES -> eventsHelper.deleteEvent(mTask.id!!, false) + DELETE_SELECTED_OCCURRENCE -> eventsHelper.deleteRepeatingEventOccurrence( + parentEventId = mTask.id!!, + occurrenceTS = mTaskOccurrenceTS, + addToCalDAV = false + ) + + DELETE_FUTURE_OCCURRENCES -> eventsHelper.addEventRepeatLimit( + eventId = mTask.id!!, + occurrenceTS = mTaskOccurrenceTS + ) + + DELETE_ALL_OCCURRENCES -> eventsHelper.deleteEvent( + id = mTask.id!!, + deleteFromCalDAV = false + ) } runOnUiThread { @@ -557,7 +668,12 @@ class TaskActivity : SimpleActivity() { private fun setupDate() { hideKeyboard() val datePicker = DatePickerDialog( - this, getDatePickerDialogTheme(), dateSetListener, mTaskDateTime.year, mTaskDateTime.monthOfYear - 1, mTaskDateTime.dayOfMonth + this, + getDatePickerDialogTheme(), + dateSetListener, + mTaskDateTime.year, + mTaskDateTime.monthOfYear - 1, + mTaskDateTime.dayOfMonth ) datePicker.datePicker.firstDayOfWeek = getJavaDayOfWeekFromISO(config.firstDayOfWeek) @@ -597,9 +713,10 @@ class TaskActivity : SimpleActivity() { } } - private val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth -> - dateSet(year, monthOfYear, dayOfMonth) - } + private val dateSetListener = + DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth -> + dateSet(year, monthOfYear, dayOfMonth) + } private val timeSetListener = TimePickerDialog.OnTimeSetListener { _, hourOfDay, minute -> timeSet(hourOfDay, minute) @@ -651,7 +768,8 @@ class TaskActivity : SimpleActivity() { // One-time migration: when converting from all-day to timed for the first time, // set default start time to avoid unexpected time values if (!isChecked && mTask.getIsAllDay() && !mConvertedFromOriginalAllDay) { - val defaultStartTS = getNewEventTimestampFromCode(Formatter.getDayCodeFromDateTime(mTaskDateTime)) + val defaultStartTS = + getNewEventTimestampFromCode(Formatter.getDayCodeFromDateTime(mTaskDateTime)) val defaultStartTime = Formatter.getDateTimeFromTS(defaultStartTS) mTaskDateTime = mTaskDateTime.withTime( @@ -769,57 +887,62 @@ class TaskActivity : SimpleActivity() { Reminder(mReminder2Minutes, mReminder2Type), Reminder(mReminder3Minutes, mReminder3Type) ) - reminders = reminders.filter { it.minutes != REMINDER_OFF }.sortedBy { it.minutes }.toMutableList() as ArrayList + reminders = reminders.filter { it.minutes != REMINDER_OFF }.sortedBy { it.minutes } + .toMutableList() as ArrayList return reminders } - private fun showEventTypeDialog() { + private fun showCalendarDialog() { hideKeyboard() - SelectEventTypeDialog( + SelectCalendarDialog( activity = this, - currEventType = mEventTypeId, + currCalendar = mCalendarId, showCalDAVCalendars = false, - showNewEventTypeOption = true, + showNewCalendarOption = true, addLastUsedOneAsFirstOption = false, showOnlyWritable = true, - showManageEventTypes = true + showManageCalendars = true ) { - mEventTypeId = it.id!! - updateEventType() + mCalendarId = it.id!! + updateCalendar() } } - private fun updateEventType() { + private fun updateCalendar() { ensureBackgroundThread { - val eventType = eventTypesDB.getEventTypeWithId(mEventTypeId) - if (eventType != null) { + val calendar = calendarsDB.getCalendarWithId(mCalendarId) + if (calendar != null) { runOnUiThread { - binding.taskType.text = eventType.title - updateTaskColorInfo(eventType.color) + binding.taskType.text = calendar.title + updateTaskColorInfo(calendar.color) } } - binding.taskColorImage.beVisibleIf(eventType != null) - binding.taskColorHolder.beVisibleIf(eventType != null) - binding.taskColorDivider.beVisibleIf(eventType != null) + binding.taskColorImage.beVisibleIf(calendar != null) + binding.taskColorHolder.beVisibleIf(calendar != null) + binding.taskColorDivider.beVisibleIf(calendar != null) } } private fun showTaskColorDialog() { hideKeyboard() ensureBackgroundThread { - val eventType = eventTypesDB.getEventTypeWithId(mEventTypeId)!! + val calendar = calendarsDB.getCalendarWithId(mCalendarId)!! val currentColor = if (mEventColor == 0) { - eventType.color + calendar.color } else { mEventColor } runOnUiThread { - ColorPickerDialog(activity = this, color = currentColor, addDefaultColorButton = true) { wasPositivePressed, newColor -> + ColorPickerDialog( + activity = this, + color = currentColor, + addDefaultColorButton = true + ) { wasPositivePressed, newColor -> if (wasPositivePressed) { if (newColor != currentColor) { mEventColor = newColor - updateTaskColorInfo(defaultColor = eventType.color) + updateTaskColorInfo(defaultColor = calendar.color) } } } @@ -931,33 +1054,70 @@ class TaskActivity : SimpleActivity() { } private fun getAvailableMonthlyRepetitionRules(): ArrayList { - val items = arrayListOf(RadioItem(REPEAT_SAME_DAY, getString(R.string.repeat_on_the_same_day_monthly))) + val items = arrayListOf( + RadioItem( + REPEAT_SAME_DAY, + getString(R.string.repeat_on_the_same_day_monthly) + ) + ) - items.add(RadioItem(REPEAT_ORDER_WEEKDAY, getRepeatXthDayString(true, REPEAT_ORDER_WEEKDAY))) + items.add( + RadioItem( + REPEAT_ORDER_WEEKDAY, + getRepeatXthDayString(true, REPEAT_ORDER_WEEKDAY) + ) + ) if (isLastWeekDayOfMonth()) { - items.add(RadioItem(REPEAT_ORDER_WEEKDAY_USE_LAST, getRepeatXthDayString(true, REPEAT_ORDER_WEEKDAY_USE_LAST))) + items.add( + RadioItem( + REPEAT_ORDER_WEEKDAY_USE_LAST, + getRepeatXthDayString(true, REPEAT_ORDER_WEEKDAY_USE_LAST) + ) + ) } if (isLastDayOfTheMonth()) { - items.add(RadioItem(REPEAT_LAST_DAY, getString(R.string.repeat_on_the_last_day_monthly))) + items.add( + RadioItem( + REPEAT_LAST_DAY, + getString(R.string.repeat_on_the_last_day_monthly) + ) + ) } return items } private fun getAvailableYearlyRepetitionRules(): ArrayList { - val items = arrayListOf(RadioItem(REPEAT_SAME_DAY, getString(R.string.repeat_on_the_same_day_yearly))) + val items = arrayListOf( + RadioItem( + REPEAT_SAME_DAY, + getString(R.string.repeat_on_the_same_day_yearly) + ) + ) - items.add(RadioItem(REPEAT_ORDER_WEEKDAY, getRepeatXthDayInMonthString(true, REPEAT_ORDER_WEEKDAY))) + items.add( + RadioItem( + REPEAT_ORDER_WEEKDAY, + getRepeatXthDayInMonthString(true, REPEAT_ORDER_WEEKDAY) + ) + ) if (isLastWeekDayOfMonth()) { - items.add(RadioItem(REPEAT_ORDER_WEEKDAY_USE_LAST, getRepeatXthDayInMonthString(true, REPEAT_ORDER_WEEKDAY_USE_LAST))) + items.add( + RadioItem( + REPEAT_ORDER_WEEKDAY_USE_LAST, + getRepeatXthDayInMonthString(true, REPEAT_ORDER_WEEKDAY_USE_LAST) + ) + ) } return items } - private fun isLastDayOfTheMonth() = mTaskDateTime.dayOfMonth == mTaskDateTime.dayOfMonth().withMaximumValue().dayOfMonth + private fun isLastDayOfTheMonth() = + mTaskDateTime.dayOfMonth == mTaskDateTime.dayOfMonth().withMaximumValue().dayOfMonth - private fun isLastWeekDayOfMonth() = mTaskDateTime.monthOfYear != mTaskDateTime.plusDays(7).monthOfYear + private fun isLastWeekDayOfMonth() = + mTaskDateTime.monthOfYear != mTaskDateTime.plusDays(7).monthOfYear private fun getRepeatXthDayString(includeBase: Boolean, repeatRule: Int): String { val dayOfWeek = mTaskDateTime.dayOfWeek @@ -967,7 +1127,8 @@ class TaskActivity : SimpleActivity() { return if (includeBase) { "$base $order $dayString" } else { - val everyString = getString(if (isMaleGender(mTaskDateTime.dayOfWeek)) R.string.every_m else R.string.every_f) + val everyString = + getString(if (isMaleGender(mTaskDateTime.dayOfWeek)) R.string.every_m else R.string.every_f) "$everyString $order $dayString" } } @@ -1020,7 +1181,8 @@ class TaskActivity : SimpleActivity() { private fun getRepeatXthDayInMonthString(includeBase: Boolean, repeatRule: Int): String { val weekDayString = getRepeatXthDayString(includeBase, repeatRule) - val monthString = resources.getStringArray(org.fossify.commons.R.array.in_months)[mTaskDateTime.monthOfYear - 1] + val monthString = + resources.getStringArray(org.fossify.commons.R.array.in_months)[mTaskDateTime.monthOfYear - 1] return "$weekDayString $monthString" } @@ -1043,16 +1205,18 @@ class TaskActivity : SimpleActivity() { } mRepeatInterval.isXMonthlyRepetition() -> { - val repeatString = if (mRepeatRule == REPEAT_ORDER_WEEKDAY_USE_LAST || mRepeatRule == REPEAT_ORDER_WEEKDAY) - R.string.repeat else R.string.repeat_on + val repeatString = + if (mRepeatRule == REPEAT_ORDER_WEEKDAY_USE_LAST || mRepeatRule == REPEAT_ORDER_WEEKDAY) + R.string.repeat else R.string.repeat_on binding.taskRepetitionRuleLabel.text = getString(repeatString) binding.taskRepetitionRule.text = getMonthlyRepetitionRuleText() } mRepeatInterval.isXYearlyRepetition() -> { - val repeatString = if (mRepeatRule == REPEAT_ORDER_WEEKDAY_USE_LAST || mRepeatRule == REPEAT_ORDER_WEEKDAY) - R.string.repeat else R.string.repeat_on + val repeatString = + if (mRepeatRule == REPEAT_ORDER_WEEKDAY_USE_LAST || mRepeatRule == REPEAT_ORDER_WEEKDAY) + R.string.repeat else R.string.repeat_on binding.taskRepetitionRuleLabel.text = getString(repeatString) binding.taskRepetitionRule.text = getYearlyRepetitionRuleText() diff --git a/app/src/main/kotlin/org/fossify/calendar/adapters/FilterCalendarAdapter.kt b/app/src/main/kotlin/org/fossify/calendar/adapters/FilterCalendarAdapter.kt new file mode 100644 index 000000000..a13c45304 --- /dev/null +++ b/app/src/main/kotlin/org/fossify/calendar/adapters/FilterCalendarAdapter.kt @@ -0,0 +1,79 @@ +package org.fossify.calendar.adapters + +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import org.fossify.calendar.activities.SimpleActivity +import org.fossify.calendar.databinding.FilterCalendarViewBinding +import org.fossify.calendar.models.CalendarEntity +import org.fossify.commons.extensions.getProperBackgroundColor +import org.fossify.commons.extensions.getProperPrimaryColor +import org.fossify.commons.extensions.getProperTextColor +import org.fossify.commons.extensions.setFillWithStroke + +class FilterCalendarAdapter( + val activity: SimpleActivity, + val calendars: List, + val displayCalendars: Set +) : + RecyclerView.Adapter() { + private val selectedKeys = HashSet() + + init { + calendars.forEach { calendar -> + if (displayCalendars.contains(calendar.id.toString())) { + selectedKeys.add(calendar.id!!) + } + } + } + + private fun toggleItemSelection(select: Boolean, calendar: CalendarEntity, pos: Int) { + if (select) { + selectedKeys.add(calendar.id!!) + } else { + selectedKeys.remove(calendar.id) + } + + notifyItemChanged(pos) + } + + fun getSelectedItemsList() = + selectedKeys.asSequence().map { it }.toMutableList() as ArrayList + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CalendarViewHolder { + return CalendarViewHolder( + binding = FilterCalendarViewBinding.inflate(activity.layoutInflater, parent, false) + ) + } + + override fun onBindViewHolder(holder: CalendarViewHolder, position: Int) = + holder.bindView(calendar = calendars[position]) + + override fun getItemCount() = calendars.size + + inner class CalendarViewHolder(val binding: FilterCalendarViewBinding) : + RecyclerView.ViewHolder(binding.root) { + fun bindView(calendar: CalendarEntity) { + val isSelected = selectedKeys.contains(calendar.id) + binding.apply { + filterCalendarCheckbox.isChecked = isSelected + filterCalendarCheckbox.setColors( + activity.getProperTextColor(), + activity.getProperPrimaryColor(), + activity.getProperBackgroundColor() + ) + filterCalendarCheckbox.text = calendar.getDisplayTitle() + filterCalendarColor.setFillWithStroke( + calendar.color, + activity.getProperBackgroundColor() + ) + filterCalendarHolder.setOnClickListener { + viewClicked(!isSelected, calendar) + } + } + } + + private fun viewClicked(select: Boolean, calendar: CalendarEntity) { + toggleItemSelection(select, calendar, adapterPosition) + } + } +} diff --git a/app/src/main/kotlin/org/fossify/calendar/adapters/FilterEventTypeAdapter.kt b/app/src/main/kotlin/org/fossify/calendar/adapters/FilterEventTypeAdapter.kt deleted file mode 100644 index 693b8a045..000000000 --- a/app/src/main/kotlin/org/fossify/calendar/adapters/FilterEventTypeAdapter.kt +++ /dev/null @@ -1,65 +0,0 @@ -package org.fossify.calendar.adapters - -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import org.fossify.calendar.activities.SimpleActivity -import org.fossify.calendar.databinding.FilterEventTypeViewBinding -import org.fossify.calendar.models.EventType -import org.fossify.commons.extensions.getProperBackgroundColor -import org.fossify.commons.extensions.getProperPrimaryColor -import org.fossify.commons.extensions.getProperTextColor -import org.fossify.commons.extensions.setFillWithStroke - -class FilterEventTypeAdapter(val activity: SimpleActivity, val eventTypes: List, val displayEventTypes: Set) : - RecyclerView.Adapter() { - private val selectedKeys = HashSet() - - init { - eventTypes.forEach { eventType -> - if (displayEventTypes.contains(eventType.id.toString())) { - selectedKeys.add(eventType.id!!) - } - } - } - - private fun toggleItemSelection(select: Boolean, eventType: EventType, pos: Int) { - if (select) { - selectedKeys.add(eventType.id!!) - } else { - selectedKeys.remove(eventType.id) - } - - notifyItemChanged(pos) - } - - fun getSelectedItemsList() = selectedKeys.asSequence().map { it }.toMutableList() as ArrayList - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EventTypeViewHolder { - return EventTypeViewHolder( - binding = FilterEventTypeViewBinding.inflate(activity.layoutInflater, parent, false) - ) - } - - override fun onBindViewHolder(holder: EventTypeViewHolder, position: Int) = holder.bindView(eventType = eventTypes[position]) - - override fun getItemCount() = eventTypes.size - - inner class EventTypeViewHolder(val binding: FilterEventTypeViewBinding) : RecyclerView.ViewHolder(binding.root) { - fun bindView(eventType: EventType) { - val isSelected = selectedKeys.contains(eventType.id) - binding.apply { - filterEventTypeCheckbox.isChecked = isSelected - filterEventTypeCheckbox.setColors(activity.getProperTextColor(), activity.getProperPrimaryColor(), activity.getProperBackgroundColor()) - filterEventTypeCheckbox.text = eventType.getDisplayTitle() - filterEventTypeColor.setFillWithStroke(eventType.color, activity.getProperBackgroundColor()) - filterEventTypeHolder.setOnClickListener { - viewClicked(!isSelected, eventType) - } - } - } - - private fun viewClicked(select: Boolean, eventType: EventType) { - toggleItemSelection(select, eventType, adapterPosition) - } - } -} diff --git a/app/src/main/kotlin/org/fossify/calendar/adapters/ManageCalendarsAdapter.kt b/app/src/main/kotlin/org/fossify/calendar/adapters/ManageCalendarsAdapter.kt new file mode 100644 index 000000000..432b41233 --- /dev/null +++ b/app/src/main/kotlin/org/fossify/calendar/adapters/ManageCalendarsAdapter.kt @@ -0,0 +1,204 @@ +package org.fossify.calendar.adapters + +import android.view.ContextThemeWrapper +import android.view.Gravity +import android.view.Menu +import android.view.View +import android.view.ViewGroup +import android.widget.PopupMenu +import org.fossify.calendar.R +import org.fossify.calendar.activities.SimpleActivity +import org.fossify.calendar.databinding.ItemCalendarBinding +import org.fossify.calendar.extensions.eventsHelper +import org.fossify.calendar.helpers.LOCAL_CALENDAR_ID +import org.fossify.calendar.interfaces.DeleteCalendarsListener +import org.fossify.calendar.models.CalendarEntity +import org.fossify.commons.adapters.MyRecyclerViewAdapter +import org.fossify.commons.dialogs.ConfirmationDialog +import org.fossify.commons.dialogs.RadioGroupDialog +import org.fossify.commons.extensions.getPopupMenuTheme +import org.fossify.commons.extensions.getProperBackgroundColor +import org.fossify.commons.extensions.getProperTextColor +import org.fossify.commons.extensions.setFillWithStroke +import org.fossify.commons.extensions.toast +import org.fossify.commons.models.RadioItem +import org.fossify.commons.views.MyRecyclerView + +class ManageCalendarsAdapter( + activity: SimpleActivity, + val calendars: ArrayList, + val listener: DeleteCalendarsListener?, + recyclerView: MyRecyclerView, + itemClick: (Any) -> Unit +) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) { + private val MOVE_EVENTS = 0 + private val DELETE_EVENTS = 1 + + init { + setupDragListener(true) + } + + override fun getActionMenuId() = R.menu.cab_calendar + + override fun prepareActionMode(menu: Menu) { + menu.apply { + findItem(R.id.cab_edit).isVisible = isOneItemSelected() + } + } + + override fun actionItemPressed(id: Int) { + if (selectedKeys.isEmpty()) { + return + } + + when (id) { + R.id.cab_edit -> editCalendar() + R.id.cab_delete -> askConfirmDelete() + } + } + + override fun getSelectableItemCount() = calendars.size + + override fun getIsItemSelectable(position: Int) = true + + override fun getItemSelectionKey(position: Int) = calendars.getOrNull(position)?.id?.toInt() + + override fun getItemKeyPosition(key: Int) = calendars.indexOfFirst { it.id?.toInt() == key } + + override fun onActionModeCreated() {} + + override fun onActionModeDestroyed() {} + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return createViewHolder( + view = ItemCalendarBinding.inflate(activity.layoutInflater, parent, false).root + ) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val calendar = calendars[position] + holder.bindView(calendar, allowSingleClick = true, allowLongClick = true) { itemView, _ -> + setupView(itemView, calendar) + } + bindViewHolder(holder) + } + + override fun getItemCount() = calendars.size + + private fun getItemWithKey(key: Int): CalendarEntity? = + calendars.firstOrNull { it.id?.toInt() == key } + + private fun getSelectedItems() = + calendars.filter { selectedKeys.contains(it.id?.toInt()) } as ArrayList + + private fun setupView(view: View, calendar: CalendarEntity) { + ItemCalendarBinding.bind(view).apply { + eventItemFrame.isSelected = selectedKeys.contains(calendar.id?.toInt()) + calendarTitle.text = calendar.getDisplayTitle() + calendarColor.setFillWithStroke(calendar.color, activity.getProperBackgroundColor()) + calendarTitle.setTextColor(textColor) + + overflowMenuIcon.drawable.apply { + mutate() + setTint(activity.getProperTextColor()) + } + + overflowMenuIcon.setOnClickListener { + showPopupMenu(overflowMenuAnchor, calendar) + } + } + } + + private fun showPopupMenu(view: View, calendar: CalendarEntity) { + finishActMode() + val theme = activity.getPopupMenuTheme() + val contextTheme = ContextThemeWrapper(activity, theme) + + PopupMenu(contextTheme, view, Gravity.END).apply { + inflate(getActionMenuId()) + setOnMenuItemClickListener { item -> + val calendarId = calendar.id!!.toInt() + when (item.itemId) { + R.id.cab_edit -> { + executeItemMenuOperation(calendarId) { + itemClick(calendar) + } + } + + R.id.cab_delete -> { + executeItemMenuOperation(calendarId) { + askConfirmDelete() + } + } + } + true + } + show() + } + } + + private fun executeItemMenuOperation(calendarId: Int, callback: () -> Unit) { + selectedKeys.clear() + selectedKeys.add(calendarId) + callback() + } + + private fun editCalendar() { + itemClick.invoke(getSelectedItems().first()) + finishActMode() + } + + private fun askConfirmDelete() { + val calendarIds = calendars.filter { selectedKeys.contains(it.id?.toInt()) } + .map { it.id } as ArrayList + + activity.eventsHelper.doCalendarsContainEventsOrTasks(calendarIds) { + activity.runOnUiThread { + if (it) { + val res = activity.resources + val items = ArrayList().apply { + add( + RadioItem( + MOVE_EVENTS, + res.getString(R.string.move_events_into_default) + ) + ) + add( + RadioItem( + DELETE_EVENTS, + res.getString(R.string.remove_affected_events) + ) + ) + } + RadioGroupDialog(activity, items) { + deleteCalendars(it == DELETE_EVENTS) + } + } else { + ConfirmationDialog(activity) { + deleteCalendars(true) + } + } + } + } + } + + private fun deleteCalendars(deleteEvents: Boolean) { + val calendarsToDelete = getSelectedItems() + + for (key in selectedKeys) { + val type = getItemWithKey(key) ?: continue + if (type.id == LOCAL_CALENDAR_ID) { + activity.toast(R.string.cannot_delete_default_type) + calendarsToDelete.remove(type) + toggleItemSelection(false, getItemKeyPosition(type.id!!.toInt())) + break + } + } + + if (listener?.deleteCalendars(calendarsToDelete, deleteEvents) == true) { + val positions = getSelectedItemPositions() + calendars.removeAll(calendarsToDelete) + removeSelectedItems(positions) + } + } +} diff --git a/app/src/main/kotlin/org/fossify/calendar/adapters/ManageEventTypesAdapter.kt b/app/src/main/kotlin/org/fossify/calendar/adapters/ManageEventTypesAdapter.kt deleted file mode 100644 index ef50383b6..000000000 --- a/app/src/main/kotlin/org/fossify/calendar/adapters/ManageEventTypesAdapter.kt +++ /dev/null @@ -1,180 +0,0 @@ -package org.fossify.calendar.adapters - -import android.view.* -import android.widget.PopupMenu -import org.fossify.calendar.R -import org.fossify.calendar.activities.SimpleActivity -import org.fossify.calendar.databinding.ItemEventTypeBinding -import org.fossify.calendar.extensions.eventsHelper -import org.fossify.calendar.helpers.LOCAL_CALENDAR_ID -import org.fossify.calendar.interfaces.DeleteEventTypesListener -import org.fossify.calendar.models.EventType -import org.fossify.commons.adapters.MyRecyclerViewAdapter -import org.fossify.commons.dialogs.ConfirmationDialog -import org.fossify.commons.dialogs.RadioGroupDialog -import org.fossify.commons.extensions.* -import org.fossify.commons.models.RadioItem -import org.fossify.commons.views.MyRecyclerView - -class ManageEventTypesAdapter( - activity: SimpleActivity, val eventTypes: ArrayList, val listener: DeleteEventTypesListener?, recyclerView: MyRecyclerView, - itemClick: (Any) -> Unit -) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) { - private val MOVE_EVENTS = 0 - private val DELETE_EVENTS = 1 - - init { - setupDragListener(true) - } - - override fun getActionMenuId() = R.menu.cab_event_type - - override fun prepareActionMode(menu: Menu) { - menu.apply { - findItem(R.id.cab_edit).isVisible = isOneItemSelected() - } - } - - override fun actionItemPressed(id: Int) { - if (selectedKeys.isEmpty()) { - return - } - - when (id) { - R.id.cab_edit -> editEventType() - R.id.cab_delete -> askConfirmDelete() - } - } - - override fun getSelectableItemCount() = eventTypes.size - - override fun getIsItemSelectable(position: Int) = true - - override fun getItemSelectionKey(position: Int) = eventTypes.getOrNull(position)?.id?.toInt() - - override fun getItemKeyPosition(key: Int) = eventTypes.indexOfFirst { it.id?.toInt() == key } - - override fun onActionModeCreated() {} - - override fun onActionModeDestroyed() {} - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { - return createViewHolder( - view = ItemEventTypeBinding.inflate(activity.layoutInflater, parent, false).root - ) - } - - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val eventType = eventTypes[position] - holder.bindView(eventType, allowSingleClick = true, allowLongClick = true) { itemView, _ -> - setupView(itemView, eventType) - } - bindViewHolder(holder) - } - - override fun getItemCount() = eventTypes.size - - private fun getItemWithKey(key: Int): EventType? = eventTypes.firstOrNull { it.id?.toInt() == key } - - private fun getSelectedItems() = eventTypes.filter { selectedKeys.contains(it.id?.toInt()) } as ArrayList - - private fun setupView(view: View, eventType: EventType) { - ItemEventTypeBinding.bind(view).apply { - eventItemFrame.isSelected = selectedKeys.contains(eventType.id?.toInt()) - eventTypeTitle.text = eventType.getDisplayTitle() - eventTypeColor.setFillWithStroke(eventType.color, activity.getProperBackgroundColor()) - eventTypeTitle.setTextColor(textColor) - - overflowMenuIcon.drawable.apply { - mutate() - setTint(activity.getProperTextColor()) - } - - overflowMenuIcon.setOnClickListener { - showPopupMenu(overflowMenuAnchor, eventType) - } - } - } - - private fun showPopupMenu(view: View, eventType: EventType) { - finishActMode() - val theme = activity.getPopupMenuTheme() - val contextTheme = ContextThemeWrapper(activity, theme) - - PopupMenu(contextTheme, view, Gravity.END).apply { - inflate(getActionMenuId()) - setOnMenuItemClickListener { item -> - val eventTypeId = eventType.id!!.toInt() - when (item.itemId) { - R.id.cab_edit -> { - executeItemMenuOperation(eventTypeId) { - itemClick(eventType) - } - } - - R.id.cab_delete -> { - executeItemMenuOperation(eventTypeId) { - askConfirmDelete() - } - } - } - true - } - show() - } - } - - private fun executeItemMenuOperation(eventTypeId: Int, callback: () -> Unit) { - selectedKeys.clear() - selectedKeys.add(eventTypeId) - callback() - } - - private fun editEventType() { - itemClick.invoke(getSelectedItems().first()) - finishActMode() - } - - private fun askConfirmDelete() { - val eventTypes = eventTypes.filter { selectedKeys.contains(it.id?.toInt()) }.map { it.id } as ArrayList - - activity.eventsHelper.doEventTypesContainEventsOrTasks(eventTypes) { - activity.runOnUiThread { - if (it) { - val res = activity.resources - val items = ArrayList().apply { - add(RadioItem(MOVE_EVENTS, res.getString(R.string.move_events_into_default))) - add(RadioItem(DELETE_EVENTS, res.getString(R.string.remove_affected_events))) - } - RadioGroupDialog(activity, items) { - deleteEventTypes(it == DELETE_EVENTS) - } - } else { - ConfirmationDialog(activity) { - deleteEventTypes(true) - } - } - } - } - } - - private fun deleteEventTypes(deleteEvents: Boolean) { - val eventTypesToDelete = getSelectedItems() - - for (key in selectedKeys) { - val type = getItemWithKey(key) ?: continue - if (type.id == LOCAL_CALENDAR_ID) { - activity.toast(R.string.cannot_delete_default_type) - eventTypesToDelete.remove(type) - toggleItemSelection(false, getItemKeyPosition(type.id!!.toInt())) - break - } - } - - if (listener?.deleteEventTypes(eventTypesToDelete, deleteEvents) == true) { - val positions = getSelectedItemPositions() - eventTypes.removeAll(eventTypesToDelete) - removeSelectedItems(positions) - } - } -} diff --git a/app/src/main/kotlin/org/fossify/calendar/adapters/QuickFilterEventTypeAdapter.kt b/app/src/main/kotlin/org/fossify/calendar/adapters/QuickFilterCalendarAdapter.kt similarity index 53% rename from app/src/main/kotlin/org/fossify/calendar/adapters/QuickFilterEventTypeAdapter.kt rename to app/src/main/kotlin/org/fossify/calendar/adapters/QuickFilterCalendarAdapter.kt index 8b0a838df..1ea6a43ca 100644 --- a/app/src/main/kotlin/org/fossify/calendar/adapters/QuickFilterEventTypeAdapter.kt +++ b/app/src/main/kotlin/org/fossify/calendar/adapters/QuickFilterCalendarAdapter.kt @@ -5,22 +5,22 @@ import androidx.core.view.updateLayoutParams import androidx.recyclerview.widget.RecyclerView import org.fossify.calendar.R import org.fossify.calendar.activities.SimpleActivity -import org.fossify.calendar.databinding.QuickFilterEventTypeViewBinding +import org.fossify.calendar.databinding.QuickFilterCalendarViewBinding import org.fossify.calendar.extensions.config -import org.fossify.calendar.models.EventType +import org.fossify.calendar.models.CalendarEntity import org.fossify.commons.extensions.adjustAlpha import org.fossify.commons.extensions.getProperTextColor import org.fossify.commons.helpers.LOWER_ALPHA -class QuickFilterEventTypeAdapter( +class QuickFilterCalendarAdapter( val activity: SimpleActivity, - private val allEventTypes: List, - private val quickFilterEventTypeIds: Set, + private val allCalendars: List, + private val quickFilterCalendarIds: Set, val callback: () -> Unit -) : RecyclerView.Adapter() { +) : RecyclerView.Adapter() { private val activeKeys = HashSet() - private val quickFilterEventTypes = ArrayList() - private val displayEventTypes = activity.config.displayEventTypes + private val quickFilterCalendars = ArrayList() + private val displayCalendars = activity.config.displayCalendars private val textColorActive = activity.getProperTextColor() private val textColorInactive = textColorActive.adjustAlpha(LOWER_ALPHA) @@ -29,31 +29,31 @@ class QuickFilterEventTypeAdapter( activity.resources.getDimensionPixelSize(R.dimen.quick_filter_min_width) private var lastClickTS = 0L - private var lastLongClickedType: EventType? = null + private var lastLongClickedType: CalendarEntity? = null private var lastActiveKeys = HashSet() init { - quickFilterEventTypeIds.forEach { quickFilterEventType -> - val eventType = allEventTypes - .firstOrNull { eventType -> eventType.id.toString() == quickFilterEventType } + quickFilterCalendarIds.forEach { quickFilterCalendar -> + val calendar = allCalendars + .firstOrNull { calendar -> calendar.id.toString() == quickFilterCalendar } ?: return@forEach - quickFilterEventTypes.add(eventType) + quickFilterCalendars.add(calendar) } - allEventTypes.forEach { - if (displayEventTypes.contains(it.id.toString())) { + allCalendars.forEach { + if (displayCalendars.contains(it.id.toString())) { activeKeys.add(it.id!!) } } - quickFilterEventTypes.sortBy { it.title.lowercase() } + quickFilterCalendars.sortBy { it.title.lowercase() } } - private fun toggleItemSelection(select: Boolean, eventType: EventType, pos: Int) { + private fun toggleItemSelection(select: Boolean, calendar: CalendarEntity, pos: Int) { if (select) { - activeKeys.add(eventType.id!!) + activeKeys.add(calendar.id!!) } else { - activeKeys.remove(eventType.id) + activeKeys.remove(calendar.id) } notifyItemChanged(pos) @@ -61,8 +61,8 @@ class QuickFilterEventTypeAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuickFilterViewHolder { val parentWidth = parent.measuredWidth - val numberOfItems = quickFilterEventTypes.size - val binding = QuickFilterEventTypeViewBinding.inflate( + val numberOfItems = quickFilterCalendars.size + val binding = QuickFilterCalendarViewBinding.inflate( activity.layoutInflater, parent, false ) @@ -78,70 +78,70 @@ class QuickFilterEventTypeAdapter( } override fun onBindViewHolder(holder: QuickFilterViewHolder, position: Int) { - val eventType = quickFilterEventTypes[position] - holder.bindView(eventType) + val calendar = quickFilterCalendars[position] + holder.bindView(calendar) } - override fun getItemCount() = quickFilterEventTypes.size + override fun getItemCount() = quickFilterCalendars.size - inner class QuickFilterViewHolder(val binding: QuickFilterEventTypeViewBinding) : + inner class QuickFilterViewHolder(val binding: QuickFilterCalendarViewBinding) : RecyclerView.ViewHolder(binding.root) { - fun bindView(eventType: EventType) { - val isSelected = activeKeys.contains(eventType.id) + fun bindView(calendar: CalendarEntity) { + val isSelected = activeKeys.contains(calendar.id) binding.apply { - quickFilterEventType.text = eventType.title + quickFilterCalendar.text = calendar.title val textColor = if (isSelected) textColorActive else textColorInactive - quickFilterEventType.setTextColor(textColor) + quickFilterCalendar.setTextColor(textColor) val indicatorHeightRes = if (isSelected) R.dimen.quick_filter_active_line_size else R.dimen.quick_filter_inactive_line_size - quickFilterEventTypeColor.layoutParams.height = + quickFilterCalendarColor.layoutParams.height = root.resources.getDimensionPixelSize(indicatorHeightRes) - quickFilterEventTypeColor.setBackgroundColor(eventType.color) + quickFilterCalendarColor.setBackgroundColor(calendar.color) // avoid too quick clicks, could cause glitches - quickFilterEventType.setOnClickListener { + quickFilterCalendar.setOnClickListener { if (System.currentTimeMillis() - lastClickTS > 300) { lastClickTS = System.currentTimeMillis() - viewClicked(!isSelected, eventType) + viewClicked(!isSelected, calendar) callback() lastLongClickedType = null } } - quickFilterEventType.setOnLongClickListener { - if (lastLongClickedType != eventType) { + quickFilterCalendar.setOnLongClickListener { + if (lastLongClickedType != calendar) { lastActiveKeys.clear() } val activeKeysCopy = HashSet(activeKeys) - allEventTypes.forEach { - viewClicked(select = lastActiveKeys.contains(it.id!!), eventType = it) + allCalendars.forEach { + viewClicked(select = lastActiveKeys.contains(it.id!!), calendar = it) } - val shouldSelectCurrent = if (lastLongClickedType != eventType) { + val shouldSelectCurrent = if (lastLongClickedType != calendar) { true } else { - lastActiveKeys.contains(eventType.id!!) + lastActiveKeys.contains(calendar.id!!) } - viewClicked(shouldSelectCurrent, eventType) + viewClicked(shouldSelectCurrent, calendar) notifyItemRangeChanged(0, itemCount) callback() - lastLongClickedType = eventType + lastLongClickedType = calendar lastActiveKeys = activeKeysCopy true } } } - private fun viewClicked(select: Boolean, eventType: EventType) { - activity.config.displayEventTypes = if (select) { - activity.config.displayEventTypes.plus(eventType.id.toString()) + private fun viewClicked(select: Boolean, calendar: CalendarEntity) { + activity.config.displayCalendars = if (select) { + activity.config.displayCalendars.plus(calendar.id.toString()) } else { - activity.config.displayEventTypes.minus(eventType.id.toString()) + activity.config.displayCalendars.minus(calendar.id.toString()) } - toggleItemSelection(select, eventType, adapterPosition) + toggleItemSelection(select, calendar, adapterPosition) } } } diff --git a/app/src/main/kotlin/org/fossify/calendar/databases/EventsDatabase.kt b/app/src/main/kotlin/org/fossify/calendar/databases/EventsDatabase.kt index 08f286c61..04011454a 100644 --- a/app/src/main/kotlin/org/fossify/calendar/databases/EventsDatabase.kt +++ b/app/src/main/kotlin/org/fossify/calendar/databases/EventsDatabase.kt @@ -11,24 +11,27 @@ import org.fossify.calendar.R import org.fossify.calendar.extensions.config import org.fossify.calendar.helpers.Converters import org.fossify.calendar.helpers.LOCAL_CALENDAR_ID -import org.fossify.calendar.interfaces.EventTypesDao +import org.fossify.calendar.interfaces.CalendarsDao import org.fossify.calendar.interfaces.EventsDao import org.fossify.calendar.interfaces.TasksDao import org.fossify.calendar.interfaces.WidgetsDao +import org.fossify.calendar.models.CalendarEntity import org.fossify.calendar.models.Event -import org.fossify.calendar.models.EventType import org.fossify.calendar.models.Task import org.fossify.calendar.models.Widget import org.fossify.commons.extensions.getProperPrimaryColor import java.util.concurrent.Executors -@Database(entities = [Event::class, EventType::class, Widget::class, Task::class], version = 11) +@Database( + entities = [Event::class, CalendarEntity::class, Widget::class, Task::class], + version = 11 +) @TypeConverters(Converters::class) abstract class EventsDatabase : RoomDatabase() { abstract fun EventsDao(): EventsDao - abstract fun EventTypesDao(): EventTypesDao + abstract fun CalendarsDao(): CalendarsDao abstract fun WidgetsDao(): WidgetsDao @@ -41,7 +44,11 @@ abstract class EventsDatabase : RoomDatabase() { if (db == null) { synchronized(EventsDatabase::class) { if (db == null) { - db = Room.databaseBuilder(context.applicationContext, EventsDatabase::class.java, "events.db") + db = Room.databaseBuilder( + context = context.applicationContext, + klass = EventsDatabase::class.java, + name = "events.db" + ) .addCallback(object : Callback() { override fun onCreate(db: SupportSQLiteDatabase) { super.onCreate(db) @@ -72,13 +79,13 @@ abstract class EventsDatabase : RoomDatabase() { private fun insertLocalCalendar(context: Context) { Executors.newSingleThreadScheduledExecutor().execute { - val eventType = EventType( + val calendar = CalendarEntity( id = LOCAL_CALENDAR_ID, title = context.resources.getString(R.string.regular_event), color = context.getProperPrimaryColor() ) - db!!.EventTypesDao().insertOrUpdate(eventType) - context.config.addDisplayEventType(LOCAL_CALENDAR_ID.toString()) + db!!.CalendarsDao().insertOrUpdate(calendar) + context.config.addDisplayCalendar(LOCAL_CALENDAR_ID.toString()) } } diff --git a/app/src/main/kotlin/org/fossify/calendar/dialogs/EditCalendarDialog.kt b/app/src/main/kotlin/org/fossify/calendar/dialogs/EditCalendarDialog.kt new file mode 100644 index 000000000..6d2cb1202 --- /dev/null +++ b/app/src/main/kotlin/org/fossify/calendar/dialogs/EditCalendarDialog.kt @@ -0,0 +1,127 @@ +package org.fossify.calendar.dialogs + +import android.app.Activity +import android.widget.ImageView +import androidx.appcompat.app.AlertDialog +import org.fossify.calendar.R +import org.fossify.calendar.databinding.DialogCalendarBinding +import org.fossify.calendar.extensions.calDAVHelper +import org.fossify.calendar.extensions.eventsHelper +import org.fossify.calendar.helpers.OTHER_EVENT +import org.fossify.calendar.models.CalendarEntity +import org.fossify.commons.dialogs.ColorPickerDialog +import org.fossify.commons.extensions.getAlertDialogBuilder +import org.fossify.commons.extensions.getProperBackgroundColor +import org.fossify.commons.extensions.getProperPrimaryColor +import org.fossify.commons.extensions.setFillWithStroke +import org.fossify.commons.extensions.setupDialogStuff +import org.fossify.commons.extensions.showKeyboard +import org.fossify.commons.extensions.toast +import org.fossify.commons.extensions.value +import org.fossify.commons.extensions.viewBinding +import org.fossify.commons.helpers.ensureBackgroundThread + +class EditCalendarDialog( + val activity: Activity, + var calendar: CalendarEntity? = null, + val callback: (calendar: CalendarEntity) -> Unit +) { + private var isNewEvent = calendar == null + private val binding by activity.viewBinding(DialogCalendarBinding::inflate) + + init { + if (calendar == null) { + calendar = CalendarEntity(null, "", activity.getProperPrimaryColor()) + } + + binding.apply { + setupColor(typeColor) + typeTitle.setText(calendar!!.title) + typeColor.setOnClickListener { + if (calendar?.caldavCalendarId == 0) { + ColorPickerDialog( + activity = activity, + color = calendar!!.color + ) { wasPositivePressed, color -> + if (wasPositivePressed) { + calendar!!.color = color + setupColor(typeColor) + } + } + } else { + val currentColor = calendar!!.color + val colors = + activity.calDAVHelper.getAvailableCalDAVCalendarColors(calendar!!).keys.toIntArray() + SelectCalendarColorDialog( + activity = activity, + colors = colors, + currentColor = currentColor + ) { + calendar!!.color = it + setupColor(typeColor) + } + } + } + } + + activity.getAlertDialogBuilder() + .setPositiveButton(org.fossify.commons.R.string.ok, null) + .setNegativeButton(org.fossify.commons.R.string.cancel, null) + .apply { + activity.setupDialogStuff( + view = binding.root, + dialog = this, + titleId = if (isNewEvent) R.string.add_new_type else R.string.edit_type + ) { alertDialog -> + alertDialog.showKeyboard(binding.typeTitle) + alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { + ensureBackgroundThread { + calendarConfirmed(binding.typeTitle.value, alertDialog) + } + } + } + } + } + + private fun setupColor(view: ImageView) { + view.setFillWithStroke(calendar!!.color, activity.getProperBackgroundColor()) + } + + private fun calendarConfirmed(title: String, dialog: AlertDialog) { + val calendarClass = calendar?.type ?: OTHER_EVENT + val calendarId = if (calendarClass == OTHER_EVENT) { + activity.eventsHelper.getCalendarIdWithTitle(title) + } else { + activity.eventsHelper.getCalendarIdWithClass(calendarClass) + } + + var isCalendarTitleTaken = isNewEvent && calendarId != -1L + if (!isCalendarTitleTaken) { + isCalendarTitleTaken = !isNewEvent && calendar!!.id != calendarId && calendarId != -1L + } + + if (title.isEmpty()) { + activity.toast(R.string.title_empty) + return + } else if (isCalendarTitleTaken) { + activity.toast(R.string.type_already_exists) + return + } + + calendar!!.title = title + if (calendar!!.caldavCalendarId != 0) { + calendar!!.caldavDisplayName = title + } + + calendar!!.id = activity.eventsHelper.insertOrUpdateCalendarSync(calendar!!) + + if (calendar!!.id != -1L) { + activity.runOnUiThread { + dialog.dismiss() + callback(calendar!!) + } + } else { + activity.toast(R.string.editing_calendar_failed) + } + } +} diff --git a/app/src/main/kotlin/org/fossify/calendar/dialogs/EditEventTypeDialog.kt b/app/src/main/kotlin/org/fossify/calendar/dialogs/EditEventTypeDialog.kt deleted file mode 100644 index 26f6c84e7..000000000 --- a/app/src/main/kotlin/org/fossify/calendar/dialogs/EditEventTypeDialog.kt +++ /dev/null @@ -1,103 +0,0 @@ -package org.fossify.calendar.dialogs - -import android.app.Activity -import android.widget.ImageView -import androidx.appcompat.app.AlertDialog -import org.fossify.calendar.R -import org.fossify.calendar.databinding.DialogEventTypeBinding -import org.fossify.calendar.extensions.calDAVHelper -import org.fossify.calendar.extensions.eventsHelper -import org.fossify.calendar.helpers.OTHER_EVENT -import org.fossify.calendar.models.EventType -import org.fossify.commons.dialogs.ColorPickerDialog -import org.fossify.commons.extensions.* -import org.fossify.commons.helpers.ensureBackgroundThread - -class EditEventTypeDialog(val activity: Activity, var eventType: EventType? = null, val callback: (eventType: EventType) -> Unit) { - private var isNewEvent = eventType == null - private val binding by activity.viewBinding(DialogEventTypeBinding::inflate) - - init { - if (eventType == null) { - eventType = EventType(null, "", activity.getProperPrimaryColor()) - } - - binding.apply { - setupColor(typeColor) - typeTitle.setText(eventType!!.title) - typeColor.setOnClickListener { - if (eventType?.caldavCalendarId == 0) { - ColorPickerDialog(activity, eventType!!.color) { wasPositivePressed, color -> - if (wasPositivePressed) { - eventType!!.color = color - setupColor(typeColor) - } - } - } else { - val currentColor = eventType!!.color - val colors = activity.calDAVHelper.getAvailableCalDAVCalendarColors(eventType!!).keys.toIntArray() - SelectEventTypeColorDialog(activity, colors = colors, currentColor = currentColor) { - eventType!!.color = it - setupColor(typeColor) - } - } - } - } - - activity.getAlertDialogBuilder() - .setPositiveButton(org.fossify.commons.R.string.ok, null) - .setNegativeButton(org.fossify.commons.R.string.cancel, null) - .apply { - activity.setupDialogStuff(binding.root, this, if (isNewEvent) R.string.add_new_type else R.string.edit_type) { alertDialog -> - alertDialog.showKeyboard(binding.typeTitle) - alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { - ensureBackgroundThread { - eventTypeConfirmed(binding.typeTitle.value, alertDialog) - } - } - } - } - } - - private fun setupColor(view: ImageView) { - view.setFillWithStroke(eventType!!.color, activity.getProperBackgroundColor()) - } - - private fun eventTypeConfirmed(title: String, dialog: AlertDialog) { - val eventTypeClass = eventType?.type ?: OTHER_EVENT - val eventTypeId = if (eventTypeClass == OTHER_EVENT) { - activity.eventsHelper.getEventTypeIdWithTitle(title) - } else { - activity.eventsHelper.getEventTypeIdWithClass(eventTypeClass) - } - - var isEventTypeTitleTaken = isNewEvent && eventTypeId != -1L - if (!isEventTypeTitleTaken) { - isEventTypeTitleTaken = !isNewEvent && eventType!!.id != eventTypeId && eventTypeId != -1L - } - - if (title.isEmpty()) { - activity.toast(R.string.title_empty) - return - } else if (isEventTypeTitleTaken) { - activity.toast(R.string.type_already_exists) - return - } - - eventType!!.title = title - if (eventType!!.caldavCalendarId != 0) { - eventType!!.caldavDisplayName = title - } - - eventType!!.id = activity.eventsHelper.insertOrUpdateEventTypeSync(eventType!!) - - if (eventType!!.id != -1L) { - activity.runOnUiThread { - dialog.dismiss() - callback(eventType!!) - } - } else { - activity.toast(R.string.editing_calendar_failed) - } - } -} diff --git a/app/src/main/kotlin/org/fossify/calendar/dialogs/ExportEventsDialog.kt b/app/src/main/kotlin/org/fossify/calendar/dialogs/ExportEventsDialog.kt index 6812fab95..fd83293e6 100644 --- a/app/src/main/kotlin/org/fossify/calendar/dialogs/ExportEventsDialog.kt +++ b/app/src/main/kotlin/org/fossify/calendar/dialogs/ExportEventsDialog.kt @@ -3,18 +3,32 @@ package org.fossify.calendar.dialogs import androidx.appcompat.app.AlertDialog import org.fossify.calendar.R import org.fossify.calendar.activities.SimpleActivity -import org.fossify.calendar.adapters.FilterEventTypeAdapter +import org.fossify.calendar.adapters.FilterCalendarAdapter import org.fossify.calendar.databinding.DialogExportEventsBinding import org.fossify.calendar.extensions.config import org.fossify.calendar.extensions.eventsHelper import org.fossify.commons.dialogs.FilePickerDialog -import org.fossify.commons.extensions.* +import org.fossify.commons.extensions.beGone +import org.fossify.commons.extensions.beVisible +import org.fossify.commons.extensions.getAlertDialogBuilder +import org.fossify.commons.extensions.getCurrentFormattedDateTime +import org.fossify.commons.extensions.getParentPath +import org.fossify.commons.extensions.hideKeyboard +import org.fossify.commons.extensions.humanizePath +import org.fossify.commons.extensions.internalStoragePath +import org.fossify.commons.extensions.isAValidFilename +import org.fossify.commons.extensions.setupDialogStuff +import org.fossify.commons.extensions.toast +import org.fossify.commons.extensions.value +import org.fossify.commons.extensions.viewBinding import org.fossify.commons.helpers.ensureBackgroundThread import java.io.File class ExportEventsDialog( - val activity: SimpleActivity, val path: String, val hidePath: Boolean, - val callback: (file: File, eventTypes: ArrayList) -> Unit + val activity: SimpleActivity, + val path: String, + val hidePath: Boolean, + val callback: (file: File, calendars: ArrayList) -> Unit ) { private var realPath = path.ifEmpty { activity.internalStoragePath } private val config = activity.config @@ -51,11 +65,11 @@ class ExportEventsDialog( } } - activity.eventsHelper.getEventTypes(activity, false) { - val eventTypes = HashSet() - it.mapTo(eventTypes) { it.id.toString() } + activity.eventsHelper.getCalendars(activity, false) { + val calendars = HashSet() + it.mapTo(calendars) { it.id.toString() } - exportEventsTypesList.adapter = FilterEventTypeAdapter(activity, it, eventTypes) + exportEventsTypesList.adapter = FilterCalendarAdapter(activity, it, calendars) if (it.size > 1) { exportEventsPickTypes.beVisible() } @@ -66,7 +80,11 @@ class ExportEventsDialog( .setPositiveButton(org.fossify.commons.R.string.ok, null) .setNegativeButton(org.fossify.commons.R.string.cancel, null) .apply { - activity.setupDialogStuff(binding.root, this, R.string.export_events) { alertDialog -> + activity.setupDialogStuff( + view = binding.root, + dialog = this, + titleId = R.string.export_events + ) { alertDialog -> alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { val filename = binding.exportEventsFilename.value when { @@ -90,11 +108,13 @@ class ExportEventsDialog( lastExportPath = file.absolutePath.getParentPath() exportEvents = exportEventsChecked exportTasks = exportTasksChecked - exportPastEntries = binding.exportPastEventsCheckbox.isChecked + exportPastEntries = + binding.exportPastEventsCheckbox.isChecked } - val eventTypes = (binding.exportEventsTypesList.adapter as FilterEventTypeAdapter).getSelectedItemsList() - callback(file, eventTypes) + val calendars = + (binding.exportEventsTypesList.adapter as FilterCalendarAdapter).getSelectedItemsList() + callback(file, calendars) alertDialog.dismiss() } } diff --git a/app/src/main/kotlin/org/fossify/calendar/dialogs/ImportEventsDialog.kt b/app/src/main/kotlin/org/fossify/calendar/dialogs/ImportEventsDialog.kt index 65aa1b9da..8e7d9d488 100644 --- a/app/src/main/kotlin/org/fossify/calendar/dialogs/ImportEventsDialog.kt +++ b/app/src/main/kotlin/org/fossify/calendar/dialogs/ImportEventsDialog.kt @@ -4,8 +4,8 @@ import androidx.appcompat.app.AlertDialog import org.fossify.calendar.R import org.fossify.calendar.activities.SimpleActivity import org.fossify.calendar.databinding.DialogImportEventsBinding +import org.fossify.calendar.extensions.calendarsDB import org.fossify.calendar.extensions.config -import org.fossify.calendar.extensions.eventTypesDB import org.fossify.calendar.extensions.eventsHelper import org.fossify.calendar.helpers.IcsImporter import org.fossify.calendar.helpers.IcsImporter.ImportResult.IMPORT_FAIL @@ -13,34 +13,45 @@ import org.fossify.calendar.helpers.IcsImporter.ImportResult.IMPORT_NOTHING_NEW import org.fossify.calendar.helpers.IcsImporter.ImportResult.IMPORT_OK import org.fossify.calendar.helpers.IcsImporter.ImportResult.IMPORT_PARTIAL import org.fossify.calendar.helpers.LOCAL_CALENDAR_ID -import org.fossify.commons.extensions.* +import org.fossify.commons.extensions.getAlertDialogBuilder +import org.fossify.commons.extensions.getProperBackgroundColor +import org.fossify.commons.extensions.setFillWithStroke +import org.fossify.commons.extensions.setupDialogStuff +import org.fossify.commons.extensions.toast +import org.fossify.commons.extensions.viewBinding import org.fossify.commons.helpers.ensureBackgroundThread -class ImportEventsDialog(val activity: SimpleActivity, val path: String, val callback: (refreshView: Boolean) -> Unit) { - private var currEventTypeId = LOCAL_CALENDAR_ID - private var currEventTypeCalDAVCalendarId = 0 +class ImportEventsDialog( + val activity: SimpleActivity, + val path: String, + val callback: (refreshView: Boolean) -> Unit +) { + private var currCalendarId = LOCAL_CALENDAR_ID + private var currCalendarCalDAVCalendarId = 0 private val config = activity.config private val binding by activity.viewBinding(DialogImportEventsBinding::inflate) init { ensureBackgroundThread { - if (activity.eventTypesDB.getEventTypeWithId(config.lastUsedLocalEventTypeId) == null) { - config.lastUsedLocalEventTypeId = LOCAL_CALENDAR_ID + if (activity.calendarsDB.getCalendarWithId(config.lastUsedLocalCalendarId) == null) { + config.lastUsedLocalCalendarId = LOCAL_CALENDAR_ID } - val isLastCaldavCalendarOK = config.caldavSync && config.getSyncedCalendarIdsAsList().contains(config.lastUsedCaldavCalendarId) - currEventTypeId = if (isLastCaldavCalendarOK) { - val lastUsedCalDAVCalendar = activity.eventsHelper.getEventTypeWithCalDAVCalendarId(config.lastUsedCaldavCalendarId) + val isLastCaldavCalendarOK = config.caldavSync && config.getSyncedCalendarIdsAsList() + .contains(config.lastUsedCaldavCalendarId) + currCalendarId = if (isLastCaldavCalendarOK) { + val lastUsedCalDAVCalendar = + activity.eventsHelper.getCalendarWithCalDAVCalendarId(config.lastUsedCaldavCalendarId) if (lastUsedCalDAVCalendar != null) { - currEventTypeCalDAVCalendarId = config.lastUsedCaldavCalendarId + currCalendarCalDAVCalendarId = config.lastUsedCaldavCalendarId lastUsedCalDAVCalendar.id!! } else { LOCAL_CALENDAR_ID } } else { - config.lastUsedLocalEventTypeId + config.lastUsedLocalCalendarId } - binding.importEventsCheckbox.isChecked = config.lastUsedIgnoreEventTypesState + binding.importEventsCheckbox.isChecked = config.lastUsedIgnoreCalendarsState activity.runOnUiThread { initDialog() @@ -50,24 +61,24 @@ class ImportEventsDialog(val activity: SimpleActivity, val path: String, val cal private fun initDialog() { binding.apply { - updateEventType(this) - importEventTypeTitle.setOnClickListener { - SelectEventTypeDialog( + updateCalendar(this) + importCalendarTitle.setOnClickListener { + SelectCalendarDialog( activity = activity, - currEventType = currEventTypeId, + currCalendar = currCalendarId, showCalDAVCalendars = true, - showNewEventTypeOption = true, + showNewCalendarOption = true, addLastUsedOneAsFirstOption = false, showOnlyWritable = true, - showManageEventTypes = false + showManageCalendars = false ) { - currEventTypeId = it.id!! - currEventTypeCalDAVCalendarId = it.caldavCalendarId + currCalendarId = it.id!! + currCalendarCalDAVCalendarId = it.caldavCalendarId - config.lastUsedLocalEventTypeId = it.id!! + config.lastUsedLocalCalendarId = it.id!! config.lastUsedCaldavCalendarId = it.caldavCalendarId - updateEventType(this) + updateCalendar(this) } } @@ -80,14 +91,23 @@ class ImportEventsDialog(val activity: SimpleActivity, val path: String, val cal .setPositiveButton(org.fossify.commons.R.string.ok, null) .setNegativeButton(org.fossify.commons.R.string.cancel, null) .apply { - activity.setupDialogStuff(binding.root, this, R.string.import_events) { alertDialog -> + activity.setupDialogStuff( + view = binding.root, + dialog = this, + titleId = R.string.import_events + ) { alertDialog -> alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { alertDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(null) activity.toast(org.fossify.commons.R.string.importing) ensureBackgroundThread { - val overrideFileEventTypes = binding.importEventsCheckbox.isChecked - config.lastUsedIgnoreEventTypesState = overrideFileEventTypes - val result = IcsImporter(activity).importEvents(path, currEventTypeId, currEventTypeCalDAVCalendarId, overrideFileEventTypes) + val overrideFileCalendars = binding.importEventsCheckbox.isChecked + config.lastUsedIgnoreCalendarsState = overrideFileCalendars + val result = IcsImporter(activity).importEvents( + path = path, + defaultCalendarId = currCalendarId, + calDAVCalendarId = currCalendarCalDAVCalendarId, + overrideFileCalendars = overrideFileCalendars + ) handleParseResult(result) alertDialog.dismiss() } @@ -96,12 +116,15 @@ class ImportEventsDialog(val activity: SimpleActivity, val path: String, val cal } } - private fun updateEventType(binding: DialogImportEventsBinding) { + private fun updateCalendar(binding: DialogImportEventsBinding) { ensureBackgroundThread { - val eventType = activity.eventTypesDB.getEventTypeWithId(currEventTypeId) + val calendar = activity.calendarsDB.getCalendarWithId(currCalendarId) activity.runOnUiThread { - binding.importEventTypeTitle.setText(eventType!!.getDisplayTitle()) - binding.importEventTypeColor.setFillWithStroke(eventType.color, activity.getProperBackgroundColor()) + binding.importCalendarTitle.setText(calendar!!.getDisplayTitle()) + binding.importCalendarColor.setFillWithStroke( + calendar.color, + activity.getProperBackgroundColor() + ) } } } diff --git a/app/src/main/kotlin/org/fossify/calendar/dialogs/ManageAutomaticBackupsDialog.kt b/app/src/main/kotlin/org/fossify/calendar/dialogs/ManageAutomaticBackupsDialog.kt index b09935c50..bd69650e5 100644 --- a/app/src/main/kotlin/org/fossify/calendar/dialogs/ManageAutomaticBackupsDialog.kt +++ b/app/src/main/kotlin/org/fossify/calendar/dialogs/ManageAutomaticBackupsDialog.kt @@ -6,7 +6,14 @@ import org.fossify.calendar.activities.SimpleActivity import org.fossify.calendar.databinding.DialogManageAutomaticBackupsBinding import org.fossify.calendar.extensions.config import org.fossify.commons.dialogs.FilePickerDialog -import org.fossify.commons.extensions.* +import org.fossify.commons.extensions.getAlertDialogBuilder +import org.fossify.commons.extensions.hideKeyboard +import org.fossify.commons.extensions.humanizePath +import org.fossify.commons.extensions.isAValidFilename +import org.fossify.commons.extensions.setupDialogStuff +import org.fossify.commons.extensions.toast +import org.fossify.commons.extensions.value +import org.fossify.commons.extensions.viewBinding import org.fossify.commons.helpers.ensureBackgroundThread import java.io.File @@ -14,7 +21,7 @@ class ManageAutomaticBackupsDialog(private val activity: SimpleActivity, onSucce private val binding by activity.viewBinding(DialogManageAutomaticBackupsBinding::inflate) private val config = activity.config private var backupFolder = config.autoBackupFolder - private var selectedEventTypes = config.autoBackupEventTypes.ifEmpty { config.displayEventTypes } + private var selectedCalendars = config.autoBackupCalendars.ifEmpty { config.displayCalendars } init { binding.apply { @@ -52,9 +59,9 @@ class ManageAutomaticBackupsDialog(private val activity: SimpleActivity, onSucce selectBackupFolder() } - manageEventTypesHolder.setOnClickListener { - SelectEventTypesDialog(activity, selectedEventTypes) { - selectedEventTypes = it + manageCalendarsHolder.setOnClickListener { + SelectCalendarsDialog(activity, selectedCalendars) { + selectedCalendars = it } } } @@ -62,7 +69,11 @@ class ManageAutomaticBackupsDialog(private val activity: SimpleActivity, onSucce .setPositiveButton(org.fossify.commons.R.string.ok, null) .setNegativeButton(org.fossify.commons.R.string.cancel, null) .apply { - activity.setupDialogStuff(binding.root, this, org.fossify.commons.R.string.manage_automatic_backups) { dialog -> + activity.setupDialogStuff( + view = binding.root, + dialog = this, + titleId = org.fossify.commons.R.string.manage_automatic_backups + ) { dialog -> dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { val filename = binding.backupEventsFilename.value when { @@ -76,7 +87,7 @@ class ManageAutomaticBackupsDialog(private val activity: SimpleActivity, onSucce val backupEventsChecked = binding.backupEventsCheckbox.isChecked val backupTasksChecked = binding.backupTasksCheckbox.isChecked - if (!backupEventsChecked && !backupTasksChecked || selectedEventTypes.isEmpty()) { + if (!backupEventsChecked && !backupTasksChecked || selectedCalendars.isEmpty()) { activity.toast(org.fossify.commons.R.string.no_entries_for_exporting) return@setOnClickListener } @@ -87,9 +98,10 @@ class ManageAutomaticBackupsDialog(private val activity: SimpleActivity, onSucce autoBackupFilename = filename autoBackupEvents = backupEventsChecked autoBackupTasks = backupTasksChecked - autoBackupPastEntries = binding.backupPastEventsCheckbox.isChecked - if (autoBackupEventTypes != selectedEventTypes) { - autoBackupEventTypes = selectedEventTypes + autoBackupPastEntries = + binding.backupPastEventsCheckbox.isChecked + if (autoBackupCalendars != selectedCalendars) { + autoBackupCalendars = selectedCalendars } } diff --git a/app/src/main/kotlin/org/fossify/calendar/dialogs/ManageSyncedCalendarsDialog.kt b/app/src/main/kotlin/org/fossify/calendar/dialogs/ManageSyncedCalendarsDialog.kt new file mode 100644 index 000000000..19ee6d2bb --- /dev/null +++ b/app/src/main/kotlin/org/fossify/calendar/dialogs/ManageSyncedCalendarsDialog.kt @@ -0,0 +1,96 @@ +package org.fossify.calendar.dialogs + +import android.text.TextUtils +import android.widget.RelativeLayout +import org.fossify.calendar.R +import org.fossify.calendar.activities.SimpleActivity +import org.fossify.calendar.databinding.CalendarItemAccountBinding +import org.fossify.calendar.databinding.CalendarItemCalendarBinding +import org.fossify.calendar.databinding.DialogSelectCalendarsBinding +import org.fossify.calendar.extensions.calDAVHelper +import org.fossify.calendar.extensions.config +import org.fossify.commons.extensions.beVisibleIf +import org.fossify.commons.extensions.getAlertDialogBuilder +import org.fossify.commons.extensions.setupDialogStuff +import org.fossify.commons.extensions.viewBinding +import org.fossify.commons.views.MyAppCompatCheckbox + +class ManageSyncedCalendarsDialog(val activity: SimpleActivity, val callback: () -> Unit) { + private var prevAccount = "" + private val binding by activity.viewBinding(DialogSelectCalendarsBinding::inflate) + + init { + val ids = activity.config.getSyncedCalendarIdsAsList() + val calendars = activity.calDAVHelper.getCalDAVCalendars("", true) + binding.apply { + dialogSelectCalendarsPlaceholder.beVisibleIf(calendars.isEmpty()) + dialogSelectCalendarsHolder.beVisibleIf(calendars.isNotEmpty()) + } + + val sorted = calendars.sortedWith(compareBy({ it.accountName }, { it.displayName })) + sorted.forEach { + if (prevAccount != it.accountName) { + prevAccount = it.accountName + addCalendarItem(false, it.accountName) + } + + addCalendarItem(true, it.displayName, it.id, ids.contains(it.id)) + } + + activity.getAlertDialogBuilder() + .setPositiveButton(org.fossify.commons.R.string.ok) { _, _ -> confirmSelection() } + .setNegativeButton(org.fossify.commons.R.string.cancel, null) + .apply { + activity.setupDialogStuff(binding.root, this, R.string.select_caldav_calendars) + } + } + + private fun addCalendarItem( + isEvent: Boolean, + text: String, + tag: Int = 0, + shouldCheck: Boolean = false + ) { + val itemBinding = if (isEvent) { + CalendarItemCalendarBinding.inflate( + activity.layoutInflater, + binding.dialogSelectCalendarsHolder, + false + ).apply { + calendarItemCalendarSwitch.tag = tag + calendarItemCalendarSwitch.text = text + calendarItemCalendarSwitch.isChecked = shouldCheck + root.setOnClickListener { + calendarItemCalendarSwitch.toggle() + } + } + } else { + CalendarItemAccountBinding.inflate( + activity.layoutInflater, + binding.dialogSelectCalendarsHolder, + false + ).apply { + calendarItemAccount.text = text + } + } + + binding.dialogSelectCalendarsHolder.addView(itemBinding.root) + } + + private fun confirmSelection() { + val calendarIds = ArrayList() + val childCnt = binding.dialogSelectCalendarsHolder.childCount + for (i in 0..childCnt) { + val child = binding.dialogSelectCalendarsHolder.getChildAt(i) + if (child is RelativeLayout) { + val check = child.getChildAt(0) + if (check is MyAppCompatCheckbox && check.isChecked) { + calendarIds.add(check.tag as Int) + } + } + } + + activity.config.caldavSyncedCalendarIds = TextUtils.join(",", calendarIds) + callback() + } +} diff --git a/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectEventTypeColorDialog.kt b/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectCalendarColorDialog.kt similarity index 85% rename from app/src/main/kotlin/org/fossify/calendar/dialogs/SelectEventTypeColorDialog.kt rename to app/src/main/kotlin/org/fossify/calendar/dialogs/SelectCalendarColorDialog.kt index ee0ff5057..0257e2603 100644 --- a/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectEventTypeColorDialog.kt +++ b/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectCalendarColorDialog.kt @@ -11,7 +11,12 @@ import org.fossify.commons.extensions.getAlertDialogBuilder import org.fossify.commons.extensions.setupDialogStuff import org.fossify.commons.extensions.viewBinding -class SelectEventTypeColorDialog(val activity: Activity, val colors: IntArray, var currentColor: Int, val callback: (color: Int) -> Unit) { +class SelectCalendarColorDialog( + val activity: Activity, + val colors: IntArray, + var currentColor: Int, + val callback: (color: Int) -> Unit +) { private var dialog: AlertDialog? = null private val binding by activity.viewBinding(DialogSelectColorBinding::inflate) @@ -23,7 +28,8 @@ class SelectEventTypeColorDialog(val activity: Activity, val colors: IntArray, v binding.colorGrid.apply { val width = activity.resources.getDimensionPixelSize(R.dimen.smaller_icon_size) - val spacing = activity.resources.getDimensionPixelSize(org.fossify.commons.R.dimen.small_margin) * 2 + val spacing = + activity.resources.getDimensionPixelSize(org.fossify.commons.R.dimen.small_margin) * 2 layoutManager = AutoGridLayoutManager(context = activity, itemWidth = width + spacing) adapter = colorAdapter } diff --git a/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectCalendarDialog.kt b/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectCalendarDialog.kt new file mode 100644 index 000000000..79b9f11bb --- /dev/null +++ b/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectCalendarDialog.kt @@ -0,0 +1,136 @@ +package org.fossify.calendar.dialogs + +import android.app.Activity +import android.content.Intent +import android.graphics.Color +import android.view.ViewGroup +import android.widget.RadioGroup +import androidx.appcompat.app.AlertDialog +import org.fossify.calendar.R +import org.fossify.calendar.activities.ManageCalendarsActivity +import org.fossify.calendar.databinding.DialogSelectCalendarBinding +import org.fossify.calendar.databinding.RadioButtonWithColorBinding +import org.fossify.calendar.extensions.eventsHelper +import org.fossify.calendar.models.CalendarEntity +import org.fossify.commons.extensions.beVisibleIf +import org.fossify.commons.extensions.getAlertDialogBuilder +import org.fossify.commons.extensions.getProperBackgroundColor +import org.fossify.commons.extensions.hideKeyboard +import org.fossify.commons.extensions.setFillWithStroke +import org.fossify.commons.extensions.setupDialogStuff +import org.fossify.commons.extensions.updateTextColors +import org.fossify.commons.extensions.viewBinding + +class SelectCalendarDialog( + val activity: Activity, + val currCalendar: Long, + val showCalDAVCalendars: Boolean, + val showNewCalendarOption: Boolean, + val addLastUsedOneAsFirstOption: Boolean, + val showOnlyWritable: Boolean, + var showManageCalendars: Boolean, + val callback: (calendar: CalendarEntity) -> Unit +) { + companion object { + private const val NEW_CALENDAR_ID = -2L + private const val LAST_USED_CALENDAR_ID = -1L + } + + private var dialog: AlertDialog? = null + private val radioGroup: RadioGroup + private var wasInit = false + private var calendars = ArrayList() + + private val binding by activity.viewBinding(DialogSelectCalendarBinding::inflate) + + init { + radioGroup = binding.dialogRadioGroup + binding.dialogManageCalendars.apply { + beVisibleIf(showManageCalendars) + setOnClickListener { + activity.startActivity(Intent(activity, ManageCalendarsActivity::class.java)) + dialog?.dismiss() + } + } + + binding.dialogRadioDivider.beVisibleIf(showManageCalendars) + + activity.eventsHelper.getCalendars(activity, showOnlyWritable) { calendars -> + this.calendars = calendars + activity.runOnUiThread { + if (addLastUsedOneAsFirstOption) { + val lastUsedCalendar = CalendarEntity( + LAST_USED_CALENDAR_ID, + activity.getString(R.string.last_used_one), + Color.TRANSPARENT, + 0 + ) + addRadioButton(lastUsedCalendar) + } + this.calendars.filter { showCalDAVCalendars || it.caldavCalendarId == 0 }.forEach { + addRadioButton(it) + } + if (showNewCalendarOption) { + val newCalendar = CalendarEntity( + id = NEW_CALENDAR_ID, + title = activity.getString(R.string.add_new_type), + color = Color.TRANSPARENT, + caldavCalendarId = 0 + ) + addRadioButton(newCalendar) + } + wasInit = true + activity.updateTextColors(binding.dialogRadioHolder) + } + } + + activity.getAlertDialogBuilder() + .apply { + activity.setupDialogStuff(binding.root, this) { alertDialog -> + dialog = alertDialog + } + } + } + + private fun addRadioButton(calendar: CalendarEntity) { + val radioBinding = RadioButtonWithColorBinding.inflate(activity.layoutInflater) + (radioBinding.dialogRadioButton).apply { + text = calendar.getDisplayTitle() + isChecked = calendar.id == currCalendar + id = calendar.id!!.toInt() + } + + if (calendar.color != Color.TRANSPARENT) { + radioBinding.dialogRadioColor.setFillWithStroke( + fillColor = calendar.color, + backgroundColor = activity.getProperBackgroundColor() + ) + } + + radioBinding.root.setOnClickListener { viewClicked(calendar) } + radioGroup.addView( + radioBinding.root, + RadioGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) + ) + } + + private fun viewClicked(calendar: CalendarEntity) { + if (!wasInit) { + return + } + + if (calendar.id == NEW_CALENDAR_ID) { + EditCalendarDialog(activity) { + callback(it) + activity.hideKeyboard() + dialog?.dismiss() + } + } else { + callback(calendar) + dialog?.dismiss() + } + } +} diff --git a/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectCalendarsDialog.kt b/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectCalendarsDialog.kt index 3e51ab703..c2620d6b3 100644 --- a/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectCalendarsDialog.kt +++ b/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectCalendarsDialog.kt @@ -1,83 +1,44 @@ package org.fossify.calendar.dialogs -import android.text.TextUtils -import android.widget.RelativeLayout -import org.fossify.calendar.R +import androidx.appcompat.app.AlertDialog import org.fossify.calendar.activities.SimpleActivity -import org.fossify.calendar.databinding.CalendarItemAccountBinding -import org.fossify.calendar.databinding.CalendarItemCalendarBinding -import org.fossify.calendar.databinding.DialogSelectCalendarsBinding -import org.fossify.calendar.extensions.calDAVHelper -import org.fossify.calendar.extensions.config -import org.fossify.commons.extensions.beVisibleIf +import org.fossify.calendar.adapters.FilterCalendarAdapter +import org.fossify.calendar.databinding.DialogFilterCalendarsBinding +import org.fossify.calendar.extensions.eventsHelper import org.fossify.commons.extensions.getAlertDialogBuilder import org.fossify.commons.extensions.setupDialogStuff import org.fossify.commons.extensions.viewBinding -import org.fossify.commons.views.MyAppCompatCheckbox -class SelectCalendarsDialog(val activity: SimpleActivity, val callback: () -> Unit) { - private var prevAccount = "" - private val binding by activity.viewBinding(DialogSelectCalendarsBinding::inflate) +class SelectCalendarsDialog( + val activity: SimpleActivity, + selectedCalendars: Set, + val callback: (HashSet) -> Unit +) { + private var dialog: AlertDialog? = null + private val binding by activity.viewBinding(DialogFilterCalendarsBinding::inflate) init { - val ids = activity.config.getSyncedCalendarIdsAsList() - val calendars = activity.calDAVHelper.getCalDAVCalendars("", true) - binding.apply { - dialogSelectCalendarsPlaceholder.beVisibleIf(calendars.isEmpty()) - dialogSelectCalendarsHolder.beVisibleIf(calendars.isNotEmpty()) + activity.eventsHelper.getCalendars(activity, false) { + binding.filterCalendarsList.adapter = + FilterCalendarAdapter(activity, it, selectedCalendars) + + activity.getAlertDialogBuilder() + .setPositiveButton(org.fossify.commons.R.string.ok) { _, _ -> confirmCalendars() } + .setNegativeButton(org.fossify.commons.R.string.cancel, null) + .apply { + activity.setupDialogStuff(binding.root, this) { alertDialog -> + dialog = alertDialog + } + } } - - val sorted = calendars.sortedWith(compareBy({ it.accountName }, { it.displayName })) - sorted.forEach { - if (prevAccount != it.accountName) { - prevAccount = it.accountName - addCalendarItem(false, it.accountName) - } - - addCalendarItem(true, it.displayName, it.id, ids.contains(it.id)) - } - - activity.getAlertDialogBuilder() - .setPositiveButton(org.fossify.commons.R.string.ok) { _, _ -> confirmSelection() } - .setNegativeButton(org.fossify.commons.R.string.cancel, null) - .apply { - activity.setupDialogStuff(binding.root, this, R.string.select_caldav_calendars) - } } - private fun addCalendarItem(isEvent: Boolean, text: String, tag: Int = 0, shouldCheck: Boolean = false) { - val itemBinding = if (isEvent) { - CalendarItemCalendarBinding.inflate(activity.layoutInflater, binding.dialogSelectCalendarsHolder, false).apply { - calendarItemCalendarSwitch.tag = tag - calendarItemCalendarSwitch.text = text - calendarItemCalendarSwitch.isChecked = shouldCheck - root.setOnClickListener { - calendarItemCalendarSwitch.toggle() - } - } - } else { - CalendarItemAccountBinding.inflate(activity.layoutInflater, binding.dialogSelectCalendarsHolder, false).apply { - calendarItemAccount.text = text - } - } - - binding.dialogSelectCalendarsHolder.addView(itemBinding.root) - } - - private fun confirmSelection() { - val calendarIds = ArrayList() - val childCnt = binding.dialogSelectCalendarsHolder.childCount - for (i in 0..childCnt) { - val child = binding.dialogSelectCalendarsHolder.getChildAt(i) - if (child is RelativeLayout) { - val check = child.getChildAt(0) - if (check is MyAppCompatCheckbox && check.isChecked) { - calendarIds.add(check.tag as Int) - } - } - } - - activity.config.caldavSyncedCalendarIds = TextUtils.join(",", calendarIds) - callback() + private fun confirmCalendars() { + val adapter = binding.filterCalendarsList.adapter as FilterCalendarAdapter + val selectedItems = adapter.getSelectedItemsList() + .map { it.toString() } + .toHashSet() + callback(selectedItems) + dialog?.dismiss() } } diff --git a/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectEventCalendarDialog.kt b/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectEventCalendarDialog.kt index 3d3ce12c1..b1a1b1044 100644 --- a/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectEventCalendarDialog.kt +++ b/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectEventCalendarDialog.kt @@ -11,10 +11,20 @@ import org.fossify.calendar.databinding.RadioButtonWithColorBinding import org.fossify.calendar.extensions.eventsHelper import org.fossify.calendar.helpers.STORED_LOCALLY_ONLY import org.fossify.calendar.models.CalDAVCalendar -import org.fossify.commons.extensions.* +import org.fossify.commons.extensions.getAlertDialogBuilder +import org.fossify.commons.extensions.getProperBackgroundColor +import org.fossify.commons.extensions.setFillWithStroke +import org.fossify.commons.extensions.setupDialogStuff +import org.fossify.commons.extensions.updateTextColors +import org.fossify.commons.extensions.viewBinding import org.fossify.commons.helpers.ensureBackgroundThread -class SelectEventCalendarDialog(val activity: Activity, val calendars: List, val currCalendarId: Int, val callback: (id: Int) -> Unit) { +class SelectEventCalendarDialog( + val activity: Activity, + val calendars: List, + val currCalendarId: Int, + val callback: (id: Int) -> Unit +) { private var dialog: AlertDialog? = null private val radioGroup: RadioGroup private var wasInit = false @@ -25,9 +35,9 @@ class SelectEventCalendarDialog(val activity: Activity, val calendars: List Unit -) { - private val NEW_EVENT_TYPE_ID = -2L - private val LAST_USED_EVENT_TYPE_ID = -1L - - private var dialog: AlertDialog? = null - private val radioGroup: RadioGroup - private var wasInit = false - private var eventTypes = ArrayList() - - private val binding by activity.viewBinding(DialogSelectEventTypeBinding::inflate) - - init { - radioGroup = binding.dialogRadioGroup - binding.dialogManageEventTypes.apply { - beVisibleIf(showManageEventTypes) - setOnClickListener { - activity.startActivity(Intent(activity, ManageEventTypesActivity::class.java)) - dialog?.dismiss() - } - } - - binding.dialogRadioDivider.beVisibleIf(showManageEventTypes) - - activity.eventsHelper.getEventTypes(activity, showOnlyWritable) { eventTypes -> - this.eventTypes = eventTypes - activity.runOnUiThread { - if (addLastUsedOneAsFirstOption) { - val lastUsedEventType = EventType(LAST_USED_EVENT_TYPE_ID, activity.getString(R.string.last_used_one), Color.TRANSPARENT, 0) - addRadioButton(lastUsedEventType) - } - this.eventTypes.filter { showCalDAVCalendars || it.caldavCalendarId == 0 }.forEach { - addRadioButton(it) - } - if (showNewEventTypeOption) { - val newEventType = EventType(NEW_EVENT_TYPE_ID, activity.getString(R.string.add_new_type), Color.TRANSPARENT, 0) - addRadioButton(newEventType) - } - wasInit = true - activity.updateTextColors(binding.dialogRadioHolder) - } - } - - activity.getAlertDialogBuilder() - .apply { - activity.setupDialogStuff(binding.root, this) { alertDialog -> - dialog = alertDialog - } - } - } - - private fun addRadioButton(eventType: EventType) { - val radioBinding = RadioButtonWithColorBinding.inflate(activity.layoutInflater) - (radioBinding.dialogRadioButton).apply { - text = eventType.getDisplayTitle() - isChecked = eventType.id == currEventType - id = eventType.id!!.toInt() - } - - if (eventType.color != Color.TRANSPARENT) { - radioBinding.dialogRadioColor.setFillWithStroke(eventType.color, activity.getProperBackgroundColor()) - } - - radioBinding.root.setOnClickListener { viewClicked(eventType) } - radioGroup.addView(radioBinding.root, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)) - } - - private fun viewClicked(eventType: EventType) { - if (!wasInit) { - return - } - - if (eventType.id == NEW_EVENT_TYPE_ID) { - EditEventTypeDialog(activity) { - callback(it) - activity.hideKeyboard() - dialog?.dismiss() - } - } else { - callback(eventType) - dialog?.dismiss() - } - } -} diff --git a/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectEventTypesDialog.kt b/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectEventTypesDialog.kt deleted file mode 100644 index ff3db4daf..000000000 --- a/app/src/main/kotlin/org/fossify/calendar/dialogs/SelectEventTypesDialog.kt +++ /dev/null @@ -1,39 +0,0 @@ -package org.fossify.calendar.dialogs - -import androidx.appcompat.app.AlertDialog -import org.fossify.calendar.activities.SimpleActivity -import org.fossify.calendar.adapters.FilterEventTypeAdapter -import org.fossify.calendar.databinding.DialogFilterEventTypesBinding -import org.fossify.calendar.extensions.eventsHelper -import org.fossify.commons.extensions.getAlertDialogBuilder -import org.fossify.commons.extensions.setupDialogStuff -import org.fossify.commons.extensions.viewBinding - -class SelectEventTypesDialog(val activity: SimpleActivity, selectedEventTypes: Set, val callback: (HashSet) -> Unit) { - private var dialog: AlertDialog? = null - private val binding by activity.viewBinding(DialogFilterEventTypesBinding::inflate) - - init { - activity.eventsHelper.getEventTypes(activity, false) { - binding.filterEventTypesList.adapter = FilterEventTypeAdapter(activity, it, selectedEventTypes) - - activity.getAlertDialogBuilder() - .setPositiveButton(org.fossify.commons.R.string.ok) { _, _ -> confirmEventTypes() } - .setNegativeButton(org.fossify.commons.R.string.cancel, null) - .apply { - activity.setupDialogStuff(binding.root, this) { alertDialog -> - dialog = alertDialog - } - } - } - } - - private fun confirmEventTypes() { - val adapter = binding.filterEventTypesList.adapter as FilterEventTypeAdapter - val selectedItems = adapter.getSelectedItemsList() - .map { it.toString() } - .toHashSet() - callback(selectedItems) - dialog?.dismiss() - } -} diff --git a/app/src/main/kotlin/org/fossify/calendar/dialogs/SetRemindersDialog.kt b/app/src/main/kotlin/org/fossify/calendar/dialogs/SetRemindersDialog.kt index 64f46b88f..ee8f4ea3c 100644 --- a/app/src/main/kotlin/org/fossify/calendar/dialogs/SetRemindersDialog.kt +++ b/app/src/main/kotlin/org/fossify/calendar/dialogs/SetRemindersDialog.kt @@ -10,9 +10,21 @@ import org.fossify.calendar.helpers.BIRTHDAY_EVENT import org.fossify.calendar.helpers.OTHER_EVENT import org.fossify.calendar.helpers.REMINDER_OFF import org.fossify.commons.dialogs.PermissionRequiredDialog -import org.fossify.commons.extensions.* +import org.fossify.commons.extensions.applyColorFilter +import org.fossify.commons.extensions.beVisible +import org.fossify.commons.extensions.getAlertDialogBuilder +import org.fossify.commons.extensions.getFormattedMinutes +import org.fossify.commons.extensions.getProperTextColor +import org.fossify.commons.extensions.openNotificationSettings +import org.fossify.commons.extensions.setupDialogStuff +import org.fossify.commons.extensions.showPickSecondsDialogHelper +import org.fossify.commons.extensions.viewBinding -class SetRemindersDialog(val activity: SimpleActivity, val eventType: Int, val callback: (reminders: ArrayList) -> Unit) { +class SetRemindersDialog( + val activity: SimpleActivity, + val eventType: Int, + val callback: (reminders: ArrayList) -> Unit +) { private var mReminder1Minutes = REMINDER_OFF private var mReminder2Minutes = REMINDER_OFF private var mReminder3Minutes = REMINDER_OFF @@ -30,7 +42,10 @@ class SetRemindersDialog(val activity: SimpleActivity, val eventType: Int, val c setReminders1.setOnClickListener { activity.handleNotificationPermission { granted -> if (granted) { - activity.showPickSecondsDialogHelper(mReminder1Minutes, showDuringDayOption = true) { + activity.showPickSecondsDialogHelper( + mReminder1Minutes, + showDuringDayOption = true + ) { mReminder1Minutes = if (it == -1 || it == 0) it else it / 60 setReminders1.text = activity.getFormattedMinutes(mReminder1Minutes) if (mReminder1Minutes != REMINDER_OFF) { @@ -48,7 +63,10 @@ class SetRemindersDialog(val activity: SimpleActivity, val eventType: Int, val c } setReminders2.setOnClickListener { - activity.showPickSecondsDialogHelper(mReminder2Minutes, showDuringDayOption = true) { + activity.showPickSecondsDialogHelper( + mReminder2Minutes, + showDuringDayOption = true + ) { mReminder2Minutes = if (it == -1 || it == 0) it else it / 60 setReminders2.text = activity.getFormattedMinutes(mReminder2Minutes) if (mReminder2Minutes != REMINDER_OFF) { @@ -58,7 +76,10 @@ class SetRemindersDialog(val activity: SimpleActivity, val eventType: Int, val c } setReminders3.setOnClickListener { - activity.showPickSecondsDialogHelper(mReminder3Minutes, showDuringDayOption = true) { + activity.showPickSecondsDialogHelper( + mReminder3Minutes, + showDuringDayOption = true + ) { mReminder3Minutes = if (it == -1 || it == 0) it else it / 60 setReminders3.text = activity.getFormattedMinutes(mReminder3Minutes) } @@ -90,7 +111,11 @@ class SetRemindersDialog(val activity: SimpleActivity, val eventType: Int, val c } private fun dialogConfirmed() { - val tempReminders = arrayListOf(mReminder1Minutes, mReminder2Minutes, mReminder3Minutes).filter { it != REMINDER_OFF }.sorted() + val tempReminders = arrayListOf( + mReminder1Minutes, + mReminder2Minutes, + mReminder3Minutes + ).filter { it != REMINDER_OFF }.sorted() val reminders = arrayListOf( tempReminders.getOrNull(0) ?: REMINDER_OFF, tempReminders.getOrNull(1) ?: REMINDER_OFF, diff --git a/app/src/main/kotlin/org/fossify/calendar/extensions/Context.kt b/app/src/main/kotlin/org/fossify/calendar/extensions/Context.kt index 04c8c3966..f9dd6af1e 100644 --- a/app/src/main/kotlin/org/fossify/calendar/extensions/Context.kt +++ b/app/src/main/kotlin/org/fossify/calendar/extensions/Context.kt @@ -29,8 +29,8 @@ import androidx.core.app.NotificationCompat import androidx.core.net.toUri import androidx.print.PrintHelper import org.fossify.calendar.R +import org.fossify.calendar.activities.CalendarPickerActivity import org.fossify.calendar.activities.EventActivity -import org.fossify.calendar.activities.EventTypePickerActivity import org.fossify.calendar.activities.SnoozeReminderActivity import org.fossify.calendar.activities.TaskActivity import org.fossify.calendar.databases.EventsDatabase @@ -69,7 +69,7 @@ import org.fossify.calendar.helpers.getNextAutoBackupTime import org.fossify.calendar.helpers.getNowSeconds import org.fossify.calendar.helpers.getPreviousAutoBackupTime import org.fossify.calendar.helpers.isWeekend -import org.fossify.calendar.interfaces.EventTypesDao +import org.fossify.calendar.interfaces.CalendarsDao import org.fossify.calendar.interfaces.EventsDao import org.fossify.calendar.interfaces.TasksDao import org.fossify.calendar.interfaces.WidgetsDao @@ -132,14 +132,18 @@ import kotlin.math.roundToInt val Context.config: Config get() = Config.newInstance(applicationContext) val Context.eventsDB: EventsDao get() = EventsDatabase.getInstance(applicationContext).EventsDao() -val Context.eventTypesDB: EventTypesDao get() = EventsDatabase.getInstance(applicationContext).EventTypesDao() -val Context.widgetsDB: WidgetsDao get() = EventsDatabase.getInstance(applicationContext).WidgetsDao() -val Context.completedTasksDB: TasksDao get() = EventsDatabase.getInstance(applicationContext).TasksDao() +val Context.calendarsDB: CalendarsDao + get() = EventsDatabase.getInstance(applicationContext).CalendarsDao() +val Context.widgetsDB: WidgetsDao + get() = EventsDatabase.getInstance(applicationContext).WidgetsDao() +val Context.completedTasksDB: TasksDao + get() = EventsDatabase.getInstance(applicationContext).TasksDao() val Context.eventsHelper: EventsHelper get() = EventsHelper(this) val Context.calDAVHelper: CalDAVHelper get() = CalDAVHelper(this) fun Context.updateWidgets() { - val widgetIDs = AppWidgetManager.getInstance(applicationContext)?.getAppWidgetIds(ComponentName(applicationContext, MyWidgetMonthlyProvider::class.java)) + val widgetIDs = AppWidgetManager.getInstance(applicationContext) + ?.getAppWidgetIds(ComponentName(applicationContext, MyWidgetMonthlyProvider::class.java)) ?: return if (widgetIDs.isNotEmpty()) { Intent(applicationContext, MyWidgetMonthlyProvider::class.java).apply { @@ -154,7 +158,8 @@ fun Context.updateWidgets() { } fun Context.updateListWidget() { - val widgetIDs = AppWidgetManager.getInstance(applicationContext)?.getAppWidgetIds(ComponentName(applicationContext, MyWidgetListProvider::class.java)) + val widgetIDs = AppWidgetManager.getInstance(applicationContext) + ?.getAppWidgetIds(ComponentName(applicationContext, MyWidgetListProvider::class.java)) ?: return if (widgetIDs.isNotEmpty()) { @@ -164,11 +169,13 @@ fun Context.updateListWidget() { sendBroadcast(this) } } - AppWidgetManager.getInstance(applicationContext)?.notifyAppWidgetViewDataChanged(widgetIDs, R.id.widget_event_list) + AppWidgetManager.getInstance(applicationContext) + ?.notifyAppWidgetViewDataChanged(widgetIDs, R.id.widget_event_list) } fun Context.updateDateWidget() { - val widgetIDs = AppWidgetManager.getInstance(applicationContext)?.getAppWidgetIds(ComponentName(applicationContext, MyWidgetDateProvider::class.java)) + val widgetIDs = AppWidgetManager.getInstance(applicationContext) + ?.getAppWidgetIds(ComponentName(applicationContext, MyWidgetDateProvider::class.java)) ?: return if (widgetIDs.isNotEmpty()) { Intent(applicationContext, MyWidgetDateProvider::class.java).apply { @@ -208,7 +215,11 @@ fun Context.scheduleNextEventReminder(event: Event, showToasts: Boolean) { for (curReminder in reminderSeconds) { if (curEvent.getEventStartTS() - curReminder > now) { - scheduleEventIn((curEvent.getEventStartTS() - curReminder) * 1000L, curEvent, showToasts) + scheduleEventIn( + (curEvent.getEventStartTS() - curReminder) * 1000L, + curEvent, + showToasts + ) return@getEvents } } @@ -233,7 +244,10 @@ fun Context.scheduleEventIn(notifyAtMillis: Long, event: Event, showToasts: Bool val newNotifyAtMillis = notifyAtMillis + 1000 if (showToasts) { val secondsTillNotification = (newNotifyAtMillis - now) / 1000 - val msg = String.format(getString(org.fossify.commons.R.string.time_remaining), formatSecondsToTimeString(secondsTillNotification.toInt())) + val msg = String.format( + getString(org.fossify.commons.R.string.time_remaining), + formatSecondsToTimeString(secondsTillNotification.toInt()) + ) toast(msg) } @@ -250,17 +264,32 @@ fun Context.getNotificationIntent(event: Event): PendingIntent { val intent = Intent(this, NotificationReceiver::class.java) intent.putExtra(EVENT_ID, event.id) intent.putExtra(EVENT_OCCURRENCE_TS, event.startTS) - return PendingIntent.getBroadcast(this, event.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) + return PendingIntent.getBroadcast( + this, + event.id!!.toInt(), + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) } fun Context.cancelPendingIntent(id: Long) { val intent = Intent(this, NotificationReceiver::class.java) - PendingIntent.getBroadcast(this, id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE).cancel() + PendingIntent.getBroadcast( + this, + id.toInt(), + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ).cancel() } fun Context.getAutomaticBackupIntent(): PendingIntent { val intent = Intent(this, AutomaticBackupReceiver::class.java) - return PendingIntent.getBroadcast(this, AUTOMATIC_BACKUP_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) + return PendingIntent.getBroadcast( + this, + AUTOMATIC_BACKUP_REQUEST_CODE, + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) } fun Context.scheduleNextAutomaticBackup() { @@ -290,7 +319,7 @@ fun Context.backupEventsAndTasks() { ensureBackgroundThread { val config = config val events = eventsHelper.getEventsToExport( - eventTypes = config.autoBackupEventTypes.map { it.toLong() } as ArrayList, + calendars = config.autoBackupCalendars.map { it.toLong() } as ArrayList, exportEvents = config.autoBackupEvents, exportTasks = config.autoBackupTasks, exportPastEntries = config.autoBackupPastEntries @@ -330,7 +359,8 @@ fun Context.backupEventsAndTasks() { if (!getDoesFilePathExist(exportFilePath)) { createSAFFileSdk30(exportFilePath) } - applicationContext.contentResolver.openOutputStream(exportFileUri, "wt") ?: FileOutputStream(exportFile) + applicationContext.contentResolver.openOutputStream(exportFileUri, "wt") + ?: FileOutputStream(exportFile) } else { var num = 0 while (getDoesFilePathExist(exportFilePath) && !exportFile.canWrite()) { @@ -371,10 +401,29 @@ fun Context.getRepetitionText(seconds: Int) = when (seconds) { YEAR -> getString(R.string.yearly) else -> { when { - seconds % YEAR == 0 -> resources.getQuantityString(org.fossify.commons.R.plurals.years, seconds / YEAR, seconds / YEAR) - seconds % MONTH == 0 -> resources.getQuantityString(org.fossify.commons.R.plurals.months, seconds / MONTH, seconds / MONTH) - seconds % WEEK == 0 -> resources.getQuantityString(org.fossify.commons.R.plurals.weeks, seconds / WEEK, seconds / WEEK) - else -> resources.getQuantityString(org.fossify.commons.R.plurals.days, seconds / DAY, seconds / DAY) + seconds % YEAR == 0 -> resources.getQuantityString( + org.fossify.commons.R.plurals.years, + seconds / YEAR, + seconds / YEAR + ) + + seconds % MONTH == 0 -> resources.getQuantityString( + org.fossify.commons.R.plurals.months, + seconds / MONTH, + seconds / MONTH + ) + + seconds % WEEK == 0 -> resources.getQuantityString( + org.fossify.commons.R.plurals.weeks, + seconds / WEEK, + seconds / WEEK + ) + + else -> resources.getQuantityString( + org.fossify.commons.R.plurals.days, + seconds / DAY, + seconds / DAY + ) } } } @@ -392,14 +441,25 @@ fun Context.notifyEvent(originalEvent: Event) { var event = originalEvent.copy() val currentSeconds = getNowSeconds() - var eventStartTS = if (event.getIsAllDay()) Formatter.getDayStartTS(Formatter.getDayCodeFromTS(event.startTS)) else event.startTS + var eventStartTS = + if (event.getIsAllDay()) Formatter.getDayStartTS(Formatter.getDayCodeFromTS(event.startTS)) else event.startTS // make sure refer to the proper repeatable event instance with "Tomorrow", or the specific date if (event.repeatInterval != 0 && eventStartTS - event.reminder1Minutes * 60 < currentSeconds) { - val events = eventsHelper.getRepeatableEventsFor(currentSeconds - WEEK_SECONDS, currentSeconds + YEAR_SECONDS, event.id!!) + val events = eventsHelper.getRepeatableEventsFor( + currentSeconds - WEEK_SECONDS, + currentSeconds + YEAR_SECONDS, + event.id!! + ) for (currEvent in events) { - eventStartTS = if (currEvent.getIsAllDay()) Formatter.getDayStartTS(Formatter.getDayCodeFromTS(currEvent.startTS)) else currEvent.startTS + eventStartTS = if (currEvent.getIsAllDay()) Formatter.getDayStartTS( + Formatter.getDayCodeFromTS(currEvent.startTS) + ) else currEvent.startTS val firstReminderMinutes = - arrayOf(currEvent.reminder3Minutes, currEvent.reminder2Minutes, currEvent.reminder1Minutes).filter { it != REMINDER_OFF }.max() + arrayOf( + currEvent.reminder3Minutes, + currEvent.reminder2Minutes, + currEvent.reminder1Minutes + ).filter { it != REMINDER_OFF }.max() if (eventStartTS - firstReminderMinutes * 60 > currentSeconds) { break } @@ -419,13 +479,17 @@ fun Context.notifyEvent(originalEvent: Event) { else -> "${Formatter.getDateFromCode(this, Formatter.getDayCodeFromTS(event.startTS))}," } - val timeRange = if (event.getIsAllDay()) getString(R.string.all_day) else getFormattedEventTime(startTime, endTime) + val timeRange = if (event.getIsAllDay()) getString(R.string.all_day) else getFormattedEventTime( + startTime, + endTime + ) val descriptionOrLocation = if (config.replaceDescription) event.location else event.description val content = "$displayedStartDate $timeRange $descriptionOrLocation".trim() ensureBackgroundThread { if (event.isTask()) eventsHelper.updateIsTaskCompleted(event) val notification = getNotification(pendingIntent, event, content) - val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + val notificationManager = + getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager try { if (notification != null) { notificationManager.notify(event.id!!.toInt(), notification) @@ -447,7 +511,12 @@ fun Context.getUsageAttributeForStreamType(): Int { } @SuppressLint("NewApi") -fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content: String, publicVersion: Boolean = false): Notification? { +fun Context.getNotification( + pendingIntent: PendingIntent, + event: Event, + content: String, + publicVersion: Boolean = false +): Notification? { var soundUri = config.reminderSoundUri if (soundUri == SILENT) { soundUri = "" @@ -460,7 +529,8 @@ fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content: if (soundUri != config.lastSoundUri || config.lastVibrateOnReminder != config.vibrateOnReminder) { if (!publicVersion) { if (isOreoPlus()) { - val oldChannelId = "simple_calendar_${config.lastReminderChannel}_${config.reminderAudioStream}_${event.eventType}" + val oldChannelId = + "simple_calendar_${config.lastReminderChannel}_${config.reminderAudioStream}_${event.calendarId}" notificationManager.deleteNotificationChannel(oldChannelId) } } @@ -470,13 +540,14 @@ fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content: config.lastSoundUri = soundUri } - val channelId = "simple_calendar_${config.lastReminderChannel}_${config.reminderAudioStream}_${event.eventType}" + val channelId = + "simple_calendar_${config.lastReminderChannel}_${config.reminderAudioStream}_${event.calendarId}" val audioAttributes = AudioAttributes.Builder() .setUsage(getUsageAttributeForStreamType()) .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .build() - val name = eventTypesDB.getEventTypeWithId(event.eventType)?.getDisplayTitle() + val name = calendarsDB.getCalendarWithId(event.calendarId)?.getDisplayTitle() val importance = NotificationManager.IMPORTANCE_HIGH NotificationChannel(channelId, name, importance).apply { setBypassDnd(true) @@ -493,7 +564,8 @@ fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content: } val contentTitle = if (publicVersion) resources.getString(R.string.app_name) else event.title - val contentText = if (publicVersion) resources.getString(R.string.public_event_notification_text) else content + val contentText = + if (publicVersion) resources.getString(R.string.public_event_notification_text) else content val builder = NotificationCompat.Builder(this, channelId) .setContentTitle(contentTitle) @@ -508,7 +580,11 @@ fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content: .setChannelId(channelId) .apply { if (event.isTask() && !event.isTaskCompleted()) { - addAction(R.drawable.ic_task_vector, getString(R.string.mark_completed), getMarkCompletedPendingIntent(this@getNotification, event)) + addAction( + R.drawable.ic_task_vector, + getString(R.string.mark_completed), + getMarkCompletedPendingIntent(this@getNotification, event) + ) } addAction( org.fossify.commons.R.drawable.ic_snooze_vector, @@ -536,24 +612,41 @@ fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content: return notification } -private fun getFormattedEventTime(startTime: String, endTime: String) = if (startTime == endTime) startTime else "$startTime \u2013 $endTime" +private fun getFormattedEventTime(startTime: String, endTime: String) = + if (startTime == endTime) startTime else "$startTime \u2013 $endTime" private fun getPendingIntent(context: Context, event: Event): PendingIntent { val activityClass = getActivityToOpen(event.isTask()) val intent = Intent(context, activityClass) intent.putExtra(EVENT_ID, event.id) intent.putExtra(EVENT_OCCURRENCE_TS, event.startTS) - return PendingIntent.getActivity(context, event.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) + return PendingIntent.getActivity( + context, + event.id!!.toInt(), + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) } private fun getSnoozePendingIntent(context: Context, event: Event): PendingIntent { - val snoozeClass = if (context.config.useSameSnooze) SnoozeService::class.java else SnoozeReminderActivity::class.java + val snoozeClass = + if (context.config.useSameSnooze) SnoozeService::class.java else SnoozeReminderActivity::class.java val intent = Intent(context, snoozeClass).setAction("Snooze") intent.putExtra(EVENT_ID, event.id) return if (context.config.useSameSnooze) { - PendingIntent.getService(context, event.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) + PendingIntent.getService( + context, + event.id!!.toInt(), + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) } else { - PendingIntent.getActivity(context, event.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) + PendingIntent.getActivity( + context, + event.id!!.toInt(), + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) } } @@ -561,19 +654,31 @@ private fun getMarkCompletedPendingIntent(context: Context, task: Event): Pendin val intent = Intent(context, MarkCompletedService::class.java).setAction(ACTION_MARK_COMPLETED) intent.putExtra(EVENT_ID, task.id) intent.putExtra(EVENT_OCCURRENCE_TS, task.startTS) - return PendingIntent.getService(context, task.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE) + return PendingIntent.getService( + context, + task.id!!.toInt(), + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) } fun Context.rescheduleReminder(event: Event?, minutes: Int) { if (event != null) { cancelPendingIntent(event.id!!) - applicationContext.scheduleEventIn(System.currentTimeMillis() + minutes * 60000, event, false) + applicationContext.scheduleEventIn( + System.currentTimeMillis() + minutes * 60000, + event, + false + ) cancelNotification(event.id!!) } } // if the default event start time is set to "Next full hour" and the event is created before midnight, it could change the day -fun Context.launchNewEventIntent(dayCode: String = Formatter.getTodayCode(), allowChangingDay: Boolean = false) { +fun Context.launchNewEventIntent( + dayCode: String = Formatter.getTodayCode(), + allowChangingDay: Boolean = false +) { Intent(applicationContext, EventActivity::class.java).apply { putExtra(NEW_EVENT_START_TS, getNewEventTimestampFromCode(dayCode, allowChangingDay)) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) @@ -582,7 +687,10 @@ fun Context.launchNewEventIntent(dayCode: String = Formatter.getTodayCode(), all } // if the default start time is set to "Next full hour" and the task is created before midnight, it could change the day -fun Context.launchNewTaskIntent(dayCode: String = Formatter.getTodayCode(), allowChangingDay: Boolean = false) { +fun Context.launchNewTaskIntent( + dayCode: String = Formatter.getTodayCode(), + allowChangingDay: Boolean = false +) { Intent(applicationContext, TaskActivity::class.java).apply { putExtra(NEW_EVENT_START_TS, getNewEventTimestampFromCode(dayCode, allowChangingDay)) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) @@ -592,7 +700,7 @@ fun Context.launchNewTaskIntent(dayCode: String = Formatter.getTodayCode(), allo fun Context.launchNewEventOrTaskActivity() { if (config.allowCreatingTasks) { - Intent(this, EventTypePickerActivity::class.java).apply { + Intent(this, CalendarPickerActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(this) } @@ -606,7 +714,8 @@ fun Context.getNewEventTimestampFromCode(dayCode: String, allowChangingDay: Bool val defaultStartTime = config.defaultStartTime val currHour = calendar.get(Calendar.HOUR_OF_DAY) var dateTime = Formatter.getLocalDateTimeFromCode(dayCode).withHourOfDay(currHour) - var newDateTime = dateTime.plusHours(1).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0) + var newDateTime = + dateTime.plusHours(1).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0) if (!allowChangingDay && dateTime.dayOfMonth() != newDateTime.dayOfMonth()) { newDateTime = newDateTime.minusDays(1) } @@ -621,7 +730,8 @@ fun Context.getNewEventTimestampFromCode(dayCode: String, allowChangingDay: Bool else -> { val hours = defaultStartTime / 60 val minutes = defaultStartTime % 60 - dateTime = Formatter.getLocalDateTimeFromCode(dayCode).withHourOfDay(hours).withMinuteOfHour(minutes) + dateTime = Formatter.getLocalDateTimeFromCode(dayCode).withHourOfDay(hours) + .withMinuteOfHour(minutes) newDateTime = dateTime // make sure the date doesn't change @@ -630,7 +740,8 @@ fun Context.getNewEventTimestampFromCode(dayCode: String, allowChangingDay: Bool } } -fun Context.getSyncedCalDAVCalendars() = calDAVHelper.getCalDAVCalendars(config.caldavSyncedCalendarIds, false) +fun Context.getSyncedCalDAVCalendars() = + calDAVHelper.getCalDAVCalendars(config.caldavSyncedCalendarIds, false) fun Context.recheckCalDAVCalendars(scheduleNextCalDAVSync: Boolean, callback: () -> Unit) { if (config.caldavSync) { @@ -655,14 +766,27 @@ fun Context.scheduleCalDAVSync(activate: Boolean) { if (activate) { val syncCheckInterval = 2 * AlarmManager.INTERVAL_HOUR try { - alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + syncCheckInterval, syncCheckInterval, pendingIntent) + alarmManager.setRepeating( + AlarmManager.RTC_WAKEUP, + System.currentTimeMillis() + syncCheckInterval, + syncCheckInterval, + pendingIntent + ) } catch (ignored: Exception) { } } } -fun Context.addDayEvents(day: DayMonthly, linearLayout: LinearLayout, res: Resources, dividerMargin: Int) { - val eventLayoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) +fun Context.addDayEvents( + day: DayMonthly, + linearLayout: LinearLayout, + res: Resources, + dividerMargin: Int +) { + val eventLayoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ) day.dayEvents.sortedWith(compareBy { if (it.getIsAllDay()) { @@ -707,7 +831,11 @@ fun Context.addDayEvents(day: DayMonthly, linearLayout: LinearLayout, res: Resou } } -fun Context.getEventListItems(events: List, addSectionDays: Boolean = true, addSectionMonths: Boolean = true): ArrayList { +fun Context.getEventListItems( + events: List, + addSectionDays: Boolean = true, + addSectionMonths: Boolean = true +): ArrayList { val listItems = ArrayList(events.size) val replaceDescription = config.replaceDescription @@ -820,7 +948,9 @@ fun Context.getWidgetFontSize() = when (config.fontSize) { } fun Context.getWidgetSmallFontSize() = getWidgetMediumFontSize() - 3f -fun Context.getWidgetMediumFontSize() = resources.getDimension(R.dimen.day_text_size) / resources.displayMetrics.density +fun Context.getWidgetMediumFontSize() = + resources.getDimension(R.dimen.day_text_size) / resources.displayMetrics.density + fun Context.getWidgetLargeFontSize() = getWidgetMediumFontSize() + 3f fun Context.getWidgetExtraLargeFontSize() = getWidgetMediumFontSize() + 6f @@ -879,8 +1009,20 @@ fun Context.getFirstDayOfWeekDt(date: DateTime): DateTime { // format day bits to strings like "Mon, Tue, Wed" fun Context.getShortDaysFromBitmask(bitMask: Int): String { - val dayBits = withFirstDayOfWeekToFront(listOf(MONDAY_BIT, TUESDAY_BIT, WEDNESDAY_BIT, THURSDAY_BIT, FRIDAY_BIT, SATURDAY_BIT, SUNDAY_BIT)) - val weekDays = withFirstDayOfWeekToFront(resources.getStringArray(org.fossify.commons.R.array.week_days_short).toList()) + val dayBits = withFirstDayOfWeekToFront( + listOf( + MONDAY_BIT, + TUESDAY_BIT, + WEDNESDAY_BIT, + THURSDAY_BIT, + FRIDAY_BIT, + SATURDAY_BIT, + SUNDAY_BIT + ) + ) + val weekDays = withFirstDayOfWeekToFront( + resources.getStringArray(org.fossify.commons.R.array.week_days_short).toList() + ) var days = "" dayBits.forEachIndexed { index, bit -> diff --git a/app/src/main/kotlin/org/fossify/calendar/fragments/EventListFragment.kt b/app/src/main/kotlin/org/fossify/calendar/fragments/EventListFragment.kt index 7d18bf909..5ee1b7792 100644 --- a/app/src/main/kotlin/org/fossify/calendar/fragments/EventListFragment.kt +++ b/app/src/main/kotlin/org/fossify/calendar/fragments/EventListFragment.kt @@ -13,13 +13,36 @@ import org.fossify.calendar.activities.MainActivity import org.fossify.calendar.activities.SimpleActivity import org.fossify.calendar.adapters.EventListAdapter import org.fossify.calendar.databinding.FragmentEventListBinding -import org.fossify.calendar.extensions.* -import org.fossify.calendar.helpers.* +import org.fossify.calendar.extensions.config +import org.fossify.calendar.extensions.editEvent +import org.fossify.calendar.extensions.eventsHelper +import org.fossify.calendar.extensions.getEventListItems +import org.fossify.calendar.extensions.getViewBitmap +import org.fossify.calendar.extensions.launchNewEventIntent +import org.fossify.calendar.extensions.printBitmap +import org.fossify.calendar.extensions.seconds +import org.fossify.calendar.helpers.EVENTS_LIST_VIEW +import org.fossify.calendar.helpers.FETCH_INTERVAL +import org.fossify.calendar.helpers.Formatter +import org.fossify.calendar.helpers.INITIAL_EVENTS +import org.fossify.calendar.helpers.MIN_EVENTS_TRESHOLD +import org.fossify.calendar.helpers.UPDATE_BOTTOM +import org.fossify.calendar.helpers.UPDATE_TOP import org.fossify.calendar.models.Event import org.fossify.calendar.models.ListEvent import org.fossify.calendar.models.ListItem import org.fossify.calendar.models.ListSectionDay -import org.fossify.commons.extensions.* +import org.fossify.commons.extensions.areSystemAnimationsEnabled +import org.fossify.commons.extensions.beGoneIf +import org.fossify.commons.extensions.beVisibleIf +import org.fossify.commons.extensions.getProperBackgroundColor +import org.fossify.commons.extensions.getProperPrimaryColor +import org.fossify.commons.extensions.getProperTextColor +import org.fossify.commons.extensions.hideKeyboard +import org.fossify.commons.extensions.isGone +import org.fossify.commons.extensions.onGlobalLayout +import org.fossify.commons.extensions.toast +import org.fossify.commons.extensions.underlineText import org.fossify.commons.interfaces.RefreshRecyclerViewListener import org.fossify.commons.views.MyLinearLayoutManager import org.fossify.commons.views.MyRecyclerView @@ -39,7 +62,11 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener { override val viewType = EVENTS_LIST_VIEW - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { binding = FragmentEventListBinding.inflate(inflater, container, false) binding.root.background = ColorDrawable(requireContext().getProperBackgroundColor()) binding.calendarEventsListHolder.id = (System.currentTimeMillis() % 100000).toInt() @@ -62,7 +89,9 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener { val use24Hour = requireContext().config.use24HourFormat if (use24Hour != use24HourFormat) { use24HourFormat = use24Hour - (binding.calendarEventsList.adapter as? EventListAdapter)?.toggle24HourFormat(use24HourFormat) + (binding.calendarEventsList.adapter as? EventListAdapter)?.toggle24HourFormat( + use24HourFormat + ) } } @@ -73,7 +102,8 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener { private fun checkEvents() { if (!wereInitialEventsAdded) { - minFetchedTS = DateTime().minusMinutes(requireContext().config.displayPastEvents).seconds() + minFetchedTS = + DateTime().minusMinutes(requireContext().config.displayPastEvents).seconds() maxFetchedTS = DateTime().plusMonths(6).seconds() } @@ -94,7 +124,11 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener { } } - private fun receivedEvents(events: ArrayList, updateStatus: Int, forceRecreation: Boolean = false) { + private fun receivedEvents( + events: ArrayList, + updateStatus: Int, + forceRecreation: Boolean = false + ) { if (context == null || activity == null) { return } @@ -109,7 +143,13 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener { val currAdapter = binding.calendarEventsList.adapter if (currAdapter == null || forceRecreation) { - EventListAdapter(activity as SimpleActivity, listItems, true, this, binding.calendarEventsList) { + EventListAdapter( + activity as SimpleActivity, + listItems, + true, + this, + binding.calendarEventsList + ) { if (it is ListEvent) { context?.editEvent(it) } @@ -121,17 +161,19 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener { binding.calendarEventsList.scheduleLayoutAnimation() } - binding.calendarEventsList.endlessScrollListener = object : MyRecyclerView.EndlessScrollListener { - override fun updateTop() { - fetchPreviousPeriod() + binding.calendarEventsList.endlessScrollListener = + object : MyRecyclerView.EndlessScrollListener { + override fun updateTop() { + fetchPreviousPeriod() + } + + override fun updateBottom() { + fetchNextPeriod() + } } - override fun updateBottom() { - fetchNextPeriod() - } - } - - binding.calendarEventsList.addOnScrollListener(object : RecyclerView.OnScrollListener() { + binding.calendarEventsList.addOnScrollListener(object : + RecyclerView.OnScrollListener() { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { super.onScrollStateChanged(recyclerView, newState) if (!hasBeenScrolled) { @@ -149,7 +191,11 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener { binding.calendarEventsList.scrollToPosition(item) } } else if (updateStatus == UPDATE_BOTTOM) { - binding.calendarEventsList.smoothScrollBy(0, requireContext().resources.getDimension(R.dimen.endless_scroll_move_height).toInt()) + binding.calendarEventsList.smoothScrollBy( + 0, + requireContext().resources.getDimension(R.dimen.endless_scroll_move_height) + .toInt() + ) } } checkPlaceholderVisibility() @@ -163,7 +209,7 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener { if (activity != null) { binding.calendarEmptyListPlaceholder.setTextColor(requireActivity().getProperTextColor()) if (mEvents.isEmpty()) { - val placeholderTextId = if (requireActivity().config.displayEventTypes.isEmpty()) { + val placeholderTextId = if (requireActivity().config.displayCalendars.isEmpty()) { R.string.everything_filtered_out } else { R.string.no_upcoming_events @@ -175,8 +221,10 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener { } private fun fetchPreviousPeriod() { - val lastPosition = (binding.calendarEventsList.layoutManager as MyLinearLayoutManager).findLastVisibleItemPosition() - bottomItemAtRefresh = (binding.calendarEventsList.adapter as EventListAdapter).listItems[lastPosition] + val lastPosition = + (binding.calendarEventsList.layoutManager as MyLinearLayoutManager).findLastVisibleItemPosition() + bottomItemAtRefresh = + (binding.calendarEventsList.adapter as EventListAdapter).listItems[lastPosition] val oldMinFetchedTS = minFetchedTS - 1 minFetchedTS -= FETCH_INTERVAL @@ -211,9 +259,13 @@ class EventListFragment : MyFragmentHolder(), RefreshRecyclerViewListener { override fun goToToday() { val listItems = requireContext().getEventListItems(mEvents) - val firstNonPastSectionIndex = listItems.indexOfFirst { it is ListSectionDay && !it.isPastSection } + val firstNonPastSectionIndex = + listItems.indexOfFirst { it is ListSectionDay && !it.isPastSection } if (firstNonPastSectionIndex != -1) { - (binding.calendarEventsList.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(firstNonPastSectionIndex, 0) + (binding.calendarEventsList.layoutManager as LinearLayoutManager).scrollToPositionWithOffset( + firstNonPastSectionIndex, + 0 + ) binding.calendarEventsList.onGlobalLayout { hasBeenScrolled = false (activity as? MainActivity)?.refreshItems() diff --git a/app/src/main/kotlin/org/fossify/calendar/fragments/WeekFragment.kt b/app/src/main/kotlin/org/fossify/calendar/fragments/WeekFragment.kt index 9a0fe3cb0..67fe929d0 100644 --- a/app/src/main/kotlin/org/fossify/calendar/fragments/WeekFragment.kt +++ b/app/src/main/kotlin/org/fossify/calendar/fragments/WeekFragment.kt @@ -9,7 +9,13 @@ import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.os.Handler import android.util.Range -import android.view.* +import android.view.DragEvent +import android.view.GestureDetector +import android.view.LayoutInflater +import android.view.MotionEvent +import android.view.ScaleGestureDetector +import android.view.View +import android.view.ViewGroup import android.widget.ImageView import android.widget.RelativeLayout import androidx.collection.LongSparseArray @@ -17,18 +23,66 @@ import androidx.fragment.app.Fragment import org.fossify.calendar.R import org.fossify.calendar.activities.MainActivity import org.fossify.calendar.activities.SimpleActivity -import org.fossify.calendar.databinding.* +import org.fossify.calendar.databinding.AllDayEventsHolderLineBinding +import org.fossify.calendar.databinding.FragmentWeekBinding +import org.fossify.calendar.databinding.WeekAllDayEventMarkerBinding +import org.fossify.calendar.databinding.WeekEventMarkerBinding +import org.fossify.calendar.databinding.WeekGridItemBinding +import org.fossify.calendar.databinding.WeekNowMarkerBinding +import org.fossify.calendar.databinding.WeeklyViewDayColumnBinding +import org.fossify.calendar.databinding.WeeklyViewDayLetterBinding import org.fossify.calendar.dialogs.EditRepeatingEventDialog -import org.fossify.calendar.extensions.* -import org.fossify.calendar.helpers.* +import org.fossify.calendar.extensions.checkViewStrikeThrough +import org.fossify.calendar.extensions.config +import org.fossify.calendar.extensions.eventsDB +import org.fossify.calendar.extensions.eventsHelper +import org.fossify.calendar.extensions.getWeeklyViewItemHeight +import org.fossify.calendar.extensions.intersects +import org.fossify.calendar.extensions.seconds +import org.fossify.calendar.extensions.shouldStrikeThrough +import org.fossify.calendar.helpers.Config +import org.fossify.calendar.helpers.EDIT_ALL_OCCURRENCES +import org.fossify.calendar.helpers.EDIT_FUTURE_OCCURRENCES +import org.fossify.calendar.helpers.EDIT_SELECTED_OCCURRENCE +import org.fossify.calendar.helpers.EVENT_ID +import org.fossify.calendar.helpers.EVENT_OCCURRENCE_TS +import org.fossify.calendar.helpers.FLAG_ALL_DAY +import org.fossify.calendar.helpers.Formatter +import org.fossify.calendar.helpers.IS_TASK_COMPLETED +import org.fossify.calendar.helpers.NEW_EVENT_SET_HOUR_DURATION +import org.fossify.calendar.helpers.NEW_EVENT_START_TS +import org.fossify.calendar.helpers.TYPE_EVENT +import org.fossify.calendar.helpers.TYPE_TASK +import org.fossify.calendar.helpers.WEEK_START_TIMESTAMP +import org.fossify.calendar.helpers.WeeklyCalendarImpl +import org.fossify.calendar.helpers.getActivityToOpen +import org.fossify.calendar.helpers.isWeekend import org.fossify.calendar.interfaces.WeekFragmentListener import org.fossify.calendar.interfaces.WeeklyCalendar import org.fossify.calendar.models.Event import org.fossify.calendar.models.EventWeeklyView import org.fossify.calendar.views.MyScrollView import org.fossify.commons.dialogs.RadioGroupDialog -import org.fossify.commons.extensions.* -import org.fossify.commons.helpers.* +import org.fossify.commons.extensions.adjustAlpha +import org.fossify.commons.extensions.applyColorFilter +import org.fossify.commons.extensions.beGone +import org.fossify.commons.extensions.beVisible +import org.fossify.commons.extensions.beVisibleIf +import org.fossify.commons.extensions.getContrastColor +import org.fossify.commons.extensions.getProperPrimaryColor +import org.fossify.commons.extensions.getProperTextColor +import org.fossify.commons.extensions.hideKeyboard +import org.fossify.commons.extensions.onGlobalLayout +import org.fossify.commons.extensions.realScreenSize +import org.fossify.commons.extensions.removeBit +import org.fossify.commons.extensions.toInt +import org.fossify.commons.extensions.usableScreenSize +import org.fossify.commons.helpers.HIGHER_ALPHA +import org.fossify.commons.helpers.LOWER_ALPHA +import org.fossify.commons.helpers.MEDIUM_ALPHA +import org.fossify.commons.helpers.WEEK_SECONDS +import org.fossify.commons.helpers.ensureBackgroundThread +import org.fossify.commons.helpers.isNougatPlus import org.fossify.commons.models.RadioItem import org.joda.time.DateTime import org.joda.time.Days @@ -75,7 +129,7 @@ class WeekFragment : Fragment(), WeeklyCalendar { private var allDayEventToRow = LinkedHashMap() private var currEvents = ArrayList() private var dayColumns = ArrayList() - private var eventTypeColors = LongSparseArray() + private var calendarColors = LongSparseArray() private var eventTimeRanges = LinkedHashMap>() private var currentlyDraggedView: View? = null @@ -100,7 +154,11 @@ class WeekFragment : Fragment(), WeeklyCalendar { } @SuppressLint("ClickableViewAccessibility") - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { val fullHeight = requireContext().getWeeklyViewItemHeight().toInt() * 24 binding = FragmentWeekBinding.inflate(inflater, container, false).apply { scrollView = weekEventsScrollview @@ -122,14 +180,21 @@ class WeekFragment : Fragment(), WeeklyCalendar { addDayColumns() scrollView.setOnScrollviewListener(object : MyScrollView.ScrollViewListener { - override fun onScrollChanged(scrollView: MyScrollView, x: Int, y: Int, oldx: Int, oldy: Int) { + override fun onScrollChanged( + scrollView: MyScrollView, + x: Int, + y: Int, + oldx: Int, + oldy: Int + ) { checkScrollLimits(y) } }) scrollView.onGlobalLayout { if (fullHeight < scrollView.height) { - scrollView.layoutParams.height = fullHeight - res.getDimension(org.fossify.commons.R.dimen.one_dp).toInt() + scrollView.layoutParams.height = + fullHeight - res.getDimension(org.fossify.commons.R.dimen.one_dp).toInt() } val initialScrollY = (rowHeight * config.startWeeklyAt).toInt() @@ -142,9 +207,9 @@ class WeekFragment : Fragment(), WeeklyCalendar { override fun onResume() { super.onResume() - requireContext().eventsHelper.getEventTypes(requireActivity(), false) { - it.map { eventType -> - eventTypeColors.put(eventType.id!!, eventType.color) + requireContext().eventsHelper.getCalendars(requireActivity(), false) { + it.map { calendar -> + calendarColors.put(calendar.id!!, calendar.color) } } @@ -174,7 +239,8 @@ class WeekFragment : Fragment(), WeeklyCalendar { checkScrollLimits(scrollView.scrollY) // fix some glitches like at swiping from a fully scaled out fragment with all-day events to an empty one - val fullFragmentHeight = (listener?.getFullFragmentHeight() ?: 0) - binding.weekTopHolder.height + val fullFragmentHeight = + (listener?.getFullFragmentHeight() ?: 0) - binding.weekTopHolder.height if (scrollView.height < fullFragmentHeight) { config.weeklyViewItemHeightMultiplier = fullFragmentHeight / 24 / defaultRowHeight updateViewScale() @@ -193,7 +259,11 @@ class WeekFragment : Fragment(), WeeklyCalendar { private fun addDayColumns() { binding.weekEventsColumnsHolder.removeAllViews() (0 until config.weeklyViewDays).forEach { - val column = WeeklyViewDayColumnBinding.inflate(layoutInflater, binding.weekEventsColumnsHolder, false).root + val column = WeeklyViewDayColumnBinding.inflate( + layoutInflater, + binding.weekEventsColumnsHolder, + false + ).root column.tag = Formatter.getDayCodeFromDateTime(weekDateTime.plusDays(it)) binding.weekEventsColumnsHolder.addView(column) dayColumns.add(column) @@ -226,7 +296,11 @@ class WeekFragment : Fragment(), WeeklyCalendar { else -> requireContext().getProperTextColor() } - val label = WeeklyViewDayLetterBinding.inflate(layoutInflater, binding.weekLettersHolder, false).root + val label = WeeklyViewDayLetterBinding.inflate( + layoutInflater, + binding.weekLettersHolder, + false + ).root label.text = "$dayLetter\n${curDay.dayOfMonth}" label.setTextColor(textColor) if (todayCode == dayCode) { @@ -260,7 +334,10 @@ class WeekFragment : Fragment(), WeeklyCalendar { layout.setOnDragListener { _, dragEvent -> when (dragEvent.action) { - DragEvent.ACTION_DRAG_STARTED -> dragEvent.clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN) + DragEvent.ACTION_DRAG_STARTED -> dragEvent.clipDescription.hasMimeType( + ClipDescription.MIMETYPE_TEXT_PLAIN + ) + DragEvent.ACTION_DRAG_ENTERED, DragEvent.ACTION_DRAG_EXITED, DragEvent.ACTION_DRAG_LOCATION, @@ -268,12 +345,15 @@ class WeekFragment : Fragment(), WeeklyCalendar { DragEvent.ACTION_DROP -> { try { - val (eventId, originalStartTS, originalEndTS) = dragEvent.clipData.getItemAt(0).text.toString().split(";").map { it.toLong() } + val (eventId, originalStartTS, originalEndTS) = dragEvent.clipData.getItemAt( + 0 + ).text.toString().split(";").map { it.toLong() } val startHour = (dragEvent.y / rowHeight).toInt() ensureBackgroundThread { val event = context?.eventsDB?.getEventOrTaskWithId(eventId) event?.let { - val currentStartTime = Formatter.getDateTimeFromTS(event.startTS) + val currentStartTime = + Formatter.getDateTimeFromTS(event.startTS) val startTime = weekDateTime.plusDays(index) .withTime( startHour, @@ -299,20 +379,33 @@ class WeekFragment : Fragment(), WeeklyCalendar { } EDIT_SELECTED_OCCURRENCE -> { - context?.eventsHelper?.editSelectedOccurrence(newEvent, originalStartTS, false) { + context?.eventsHelper?.editSelectedOccurrence( + newEvent, + originalStartTS, + false + ) { updateCalendar() } } EDIT_FUTURE_OCCURRENCES -> { - context?.eventsHelper?.editFutureOccurrences(newEvent, originalStartTS, false) { + context?.eventsHelper?.editFutureOccurrences( + newEvent, + originalStartTS, + false + ) { // we need to refresh all fragments because they can contain future occurrences (activity as MainActivity).refreshItems() } } EDIT_ALL_OCCURRENCES -> { - context?.eventsHelper?.editAllOccurrences(newEvent, originalStartTS, originalEndTS, false) { + context?.eventsHelper?.editAllOccurrences( + newEvent, + originalStartTS, + originalEndTS, + false + ) { (activity as MainActivity).refreshItems() } } @@ -323,7 +416,11 @@ class WeekFragment : Fragment(), WeeklyCalendar { if (event.startTS == newEvent.startTS && event.endTS == newEvent.endTS) { revertDraggedEvent() } else { - context?.eventsHelper?.updateEvent(newEvent, updateAtCalDAV = true, showToasts = false) { + context?.eventsHelper?.updateEvent( + newEvent, + updateAtCalDAV = true, + showToasts = false + ) { updateCalendar() } } @@ -365,7 +462,8 @@ class WeekFragment : Fragment(), WeeklyCalendar { applyColorFilter(primaryColor.getContrastColor()) setOnClickListener { - val timestamp = weekDateTime.plusDays(index).withTime(hour, 0, 0, 0).seconds() + val timestamp = + weekDateTime.plusDays(index).withTime(hour, 0, 0, 0).seconds() if (config.allowCreatingTasks) { val items = arrayListOf( RadioItem(TYPE_EVENT, getString(R.string.event)), @@ -402,40 +500,45 @@ class WeekFragment : Fragment(), WeeklyCalendar { } private fun getViewScaleDetector(): ScaleGestureDetector { - return ScaleGestureDetector(requireContext(), object : ScaleGestureDetector.SimpleOnScaleGestureListener() { - override fun onScale(detector: ScaleGestureDetector): Boolean { - val percent = (prevScaleSpanY - detector.currentSpanY) / screenHeight - prevScaleSpanY = detector.currentSpanY + return ScaleGestureDetector( + requireContext(), + object : ScaleGestureDetector.SimpleOnScaleGestureListener() { + override fun onScale(detector: ScaleGestureDetector): Boolean { + val percent = (prevScaleSpanY - detector.currentSpanY) / screenHeight + prevScaleSpanY = detector.currentSpanY - val wantedFactor = config.weeklyViewItemHeightMultiplier - (SCALE_RANGE * percent) - var newFactor = max(min(wantedFactor, MAX_SCALE_FACTOR), MIN_SCALE_FACTOR) - if (scrollView.height > defaultRowHeight * newFactor * 24) { - newFactor = scrollView.height / 24f / defaultRowHeight + val wantedFactor = + config.weeklyViewItemHeightMultiplier - (SCALE_RANGE * percent) + var newFactor = max(min(wantedFactor, MAX_SCALE_FACTOR), MIN_SCALE_FACTOR) + if (scrollView.height > defaultRowHeight * newFactor * 24) { + newFactor = scrollView.height / 24f / defaultRowHeight + } + + if (Math.abs(newFactor - prevScaleFactor) > MIN_SCALE_DIFFERENCE) { + prevScaleFactor = newFactor + config.weeklyViewItemHeightMultiplier = newFactor + updateViewScale() + listener?.updateRowHeight(rowHeight.toInt()) + + val targetY = + rowHeightsAtScale * rowHeight - scaleCenterPercent * getVisibleHeight() + scrollView.scrollTo(0, targetY.toInt()) + } + return super.onScale(detector) } - if (Math.abs(newFactor - prevScaleFactor) > MIN_SCALE_DIFFERENCE) { - prevScaleFactor = newFactor - config.weeklyViewItemHeightMultiplier = newFactor - updateViewScale() - listener?.updateRowHeight(rowHeight.toInt()) - - val targetY = rowHeightsAtScale * rowHeight - scaleCenterPercent * getVisibleHeight() - scrollView.scrollTo(0, targetY.toInt()) + override fun onScaleBegin(detector: ScaleGestureDetector): Boolean { + scaleCenterPercent = detector.focusY / scrollView.height + rowHeightsAtScale = + (scrollView.scrollY + scaleCenterPercent * getVisibleHeight()) / rowHeight + scrollView.isScrollable = false + prevScaleSpanY = detector.currentSpanY + prevScaleFactor = config.weeklyViewItemHeightMultiplier + wasScaled = true + screenHeight = context!!.realScreenSize.y + return super.onScaleBegin(detector) } - return super.onScale(detector) - } - - override fun onScaleBegin(detector: ScaleGestureDetector): Boolean { - scaleCenterPercent = detector.focusY / scrollView.height - rowHeightsAtScale = (scrollView.scrollY + scaleCenterPercent * getVisibleHeight()) / rowHeight - scrollView.isScrollable = false - prevScaleSpanY = detector.currentSpanY - prevScaleFactor = config.weeklyViewItemHeightMultiplier - wasScaled = true - screenHeight = context!!.realScreenSize.y - return super.onScaleBegin(detector) - } - }) + }) } private fun getVisibleHeight(): Float { @@ -456,7 +559,8 @@ class WeekFragment : Fragment(), WeeklyCalendar { if (context != null && activity != null && isAdded) { val replaceDescription = config.replaceDescription val sorted = events.sortedWith( - compareBy { it.startTS }.thenBy { it.endTS }.thenBy { it.title }.thenBy { if (replaceDescription) it.location else it.description } + compareBy { it.startTS }.thenBy { it.endTS }.thenBy { it.title } + .thenBy { if (replaceDescription) it.location else it.description } ).toMutableList() as ArrayList currEvents = sorted @@ -541,12 +645,13 @@ class WeekFragment : Fragment(), WeeklyCalendar { } eventsCollisionChecked.add(eventId) - val eventWeeklyViewsToCheck = eventDayList.filterNot { eventsCollisionChecked.contains(it.key) } + val eventWeeklyViewsToCheck = + eventDayList.filterNot { eventsCollisionChecked.contains(it.key) } for ((toCheckId, eventWeeklyViewToCheck) in eventWeeklyViewsToCheck) { val areTouching = eventWeeklyView.range.intersects(eventWeeklyViewToCheck.range) val doHaveCommonMinutes = if (areTouching) { eventWeeklyView.range.upper > eventWeeklyViewToCheck.range.lower || (eventWeeklyView.range.lower == eventWeeklyView.range.upper && - eventWeeklyView.range.upper == eventWeeklyViewToCheck.range.lower) + eventWeeklyView.range.upper == eventWeeklyViewToCheck.range.lower) } else { false } @@ -623,7 +728,7 @@ class WeekFragment : Fragment(), WeeklyCalendar { val dayColumn = dayColumns[dayOfWeek] WeekEventMarkerBinding.inflate(layoutInflater).apply { var backgroundColor = if (event.color == 0) { - eventTypeColors.get(event.eventType, primaryColor) + calendarColors.get(event.calendarId, primaryColor) } else { event.color } @@ -693,7 +798,10 @@ class WeekFragment : Fragment(), WeeklyCalendar { root.setOnLongClickListener { view -> currentlyDraggedView = view val shadowBuilder = View.DragShadowBuilder(view) - val clipData = ClipData.newPlainText(WEEKLY_EVENT_ID_LABEL, "${event.id};${event.startTS};${event.endTS}") + val clipData = ClipData.newPlainText( + WEEKLY_EVENT_ID_LABEL, + "${event.id};${event.startTS};${event.endTS}" + ) if (isNougatPlus()) { view.startDragAndDrop(clipData, shadowBuilder, null, 0) } else { @@ -742,7 +850,8 @@ class WeekFragment : Fragment(), WeeklyCalendar { currentTimeView = WeekNowMarkerBinding.inflate(layoutInflater).root.apply { applyColorFilter(primaryColor) binding.weekEventsHolder.addView(this, 0) - val extraWidth = res.getDimension(org.fossify.commons.R.dimen.activity_margin).toInt() + val extraWidth = + res.getDimension(org.fossify.commons.R.dimen.activity_margin).toInt() val markerHeight = res.getDimension(R.dimen.weekly_view_now_height).toInt() val minuteHeight = rowHeight / 60 (layoutParams as RelativeLayout.LayoutParams).apply { @@ -769,7 +878,11 @@ class WeekFragment : Fragment(), WeeklyCalendar { } } - private fun shouldAddEventOnTopBar(isAllDay: Boolean, startDayCode: String, endDayCode: String): Boolean { + private fun shouldAddEventOnTopBar( + isAllDay: Boolean, + startDayCode: String, + endDayCode: String + ): Boolean { val spansMultipleDays = startDayCode != endDayCode return isAllDay || (spansMultipleDays && config.showMidnightSpanningEventsAtTop) } @@ -778,7 +891,7 @@ class WeekFragment : Fragment(), WeeklyCalendar { private fun addAllDayEvent(event: Event) { WeekAllDayEventMarkerBinding.inflate(layoutInflater).apply { var backgroundColor = if (event.color == 0) { - eventTypeColors.get(event.eventType, primaryColor) + calendarColors.get(event.calendarId, primaryColor) } else { event.color } @@ -823,15 +936,22 @@ class WeekFragment : Fragment(), WeeklyCalendar { return } - val isStartTimeDay = Formatter.getDateTimeFromTS(maxTS) == Formatter.getDateTimeFromTS(maxTS).withTimeAtStartOfDay() - val numDays = Days.daysBetween(Formatter.getDateTimeFromTS(minTS).toLocalDate(), Formatter.getDateTimeFromTS(maxTS).toLocalDate()).days + val isStartTimeDay = + Formatter.getDateTimeFromTS(maxTS) == Formatter.getDateTimeFromTS(maxTS) + .withTimeAtStartOfDay() + val numDays = Days.daysBetween( + Formatter.getDateTimeFromTS(minTS).toLocalDate(), + Formatter.getDateTimeFromTS(maxTS).toLocalDate() + ).days val daysCnt = if (numDays == 1 && isStartTimeDay) 0 else numDays val startDateTimeInWeek = Formatter.getDateTimeFromTS(minTS) - val firstDayIndex = startDateTimeInWeek.dayOfMonth // indices must be unique for the visible range (2 weeks) + val firstDayIndex = + startDateTimeInWeek.dayOfMonth // indices must be unique for the visible range (2 weeks) val lastDayIndex = firstDayIndex + daysCnt val dayIndices = firstDayIndex..lastDayIndex val isAllDayEvent = firstDayIndex == lastDayIndex - val isRepeatingOverlappingEvent = eventEndDayStartTime - eventStartDayStartTime >= event.repeatInterval + val isRepeatingOverlappingEvent = + eventEndDayStartTime - eventStartDayStartTime >= event.repeatInterval var doesEventFit: Boolean var wasEventHandled = false @@ -849,7 +969,8 @@ class WeekFragment : Fragment(), WeeklyCalendar { val lastEventRowIdx = allDayEventToRow[lastEvent] val adjacentEvents = currEvents.filter { event.id == it.id } val repeatingEventIndex = adjacentEvents.indexOf(event) - val isRowValidForEvent = lastEvent == null || firstEventRowIdx!! + repeatingEventIndex == index && lastEventRowIdx!! < index + val isRowValidForEvent = + lastEvent == null || firstEventRowIdx!! + repeatingEventIndex == index && lastEventRowIdx!! < index if (doesEventFit && (!isRepeatingOverlappingEvent || isAllDayEvent || isRowValidForEvent)) { dayIndices.forEach { @@ -879,7 +1000,8 @@ class WeekFragment : Fragment(), WeeklyCalendar { val dayCodeStart = Formatter.getDayCodeFromDateTime(startDateTime).toInt() val dayCodeEnd = Formatter.getDayCodeFromDateTime(endDateTime).toInt() - val dayOfWeek = dayColumns.indexOfFirst { it.tag.toInt() == dayCodeStart || it.tag.toInt() in (dayCodeStart + 1)..dayCodeEnd } + val dayOfWeek = + dayColumns.indexOfFirst { it.tag.toInt() == dayCodeStart || it.tag.toInt() in (dayCodeStart + 1)..dayCodeEnd } if (dayOfWeek == -1) { return } diff --git a/app/src/main/kotlin/org/fossify/calendar/helpers/CalDAVHelper.kt b/app/src/main/kotlin/org/fossify/calendar/helpers/CalDAVHelper.kt index e17c73b73..ebe561688 100644 --- a/app/src/main/kotlin/org/fossify/calendar/helpers/CalDAVHelper.kt +++ b/app/src/main/kotlin/org/fossify/calendar/helpers/CalDAVHelper.kt @@ -11,8 +11,8 @@ import android.provider.CalendarContract.Events import android.provider.CalendarContract.Reminders import android.widget.Toast import org.fossify.calendar.R +import org.fossify.calendar.extensions.calendarsDB import org.fossify.calendar.extensions.config -import org.fossify.calendar.extensions.eventTypesDB import org.fossify.calendar.extensions.eventsDB import org.fossify.calendar.extensions.eventsHelper import org.fossify.calendar.extensions.queryCursorInlined @@ -23,8 +23,8 @@ import org.fossify.calendar.extensions.toUtcAllDayEvent import org.fossify.calendar.extensions.updateWidgets import org.fossify.calendar.models.Attendee import org.fossify.calendar.models.CalDAVCalendar +import org.fossify.calendar.models.CalendarEntity import org.fossify.calendar.models.Event -import org.fossify.calendar.models.EventType import org.fossify.calendar.models.Reminder import org.fossify.calendar.objects.States.isUpdatingCalDAV import org.fossify.commons.extensions.areDigitsOnly @@ -56,19 +56,19 @@ class CalDAVHelper(val context: Context) { val calDAVCalendars = getCalDAVCalendars(context.config.caldavSyncedCalendarIds, showToasts) for (calendar in calDAVCalendars) { - val localEventType = - eventsHelper.getEventTypeWithCalDAVCalendarId(calendar.id) ?: continue - if (calendar.displayName != localEventType.title || calendar.color != localEventType.color) { - localEventType.apply { + val localCalendar = + eventsHelper.getCalendarWithCalDAVCalendarId(calendar.id) ?: continue + if (calendar.displayName != localCalendar.title || calendar.color != localCalendar.color) { + localCalendar.apply { title = calendar.displayName caldavDisplayName = calendar.displayName caldavEmail = calendar.accountName color = calendar.color - eventsHelper.insertOrUpdateEventTypeSync(this) + eventsHelper.insertOrUpdateCalendarSync(this) } } - fetchCalDAVCalendarEvents(calendar, localEventType.id!!, showToasts) + fetchCalDAVCalendarEvents(calendar, localCalendar.id!!, showToasts) } if (scheduleNextSync) { @@ -121,44 +121,44 @@ class CalDAVHelper(val context: Context) { return calendars } - fun updateCalDAVCalendar(eventType: EventType) { + fun updateCalDAVCalendar(calendar: CalendarEntity) { val uri = - ContentUris.withAppendedId(Calendars.CONTENT_URI, eventType.caldavCalendarId.toLong()) + ContentUris.withAppendedId(Calendars.CONTENT_URI, calendar.caldavCalendarId.toLong()) val values = ContentValues().apply { - val colorKey = getCalDAVColorKey(eventType) + val colorKey = getCalDAVColorKey(calendar) if (colorKey != null) { - put(Calendars.CALENDAR_COLOR_KEY, getCalDAVColorKey(eventType)) + put(Calendars.CALENDAR_COLOR_KEY, getCalDAVColorKey(calendar)) } else { - put(Calendars.CALENDAR_COLOR, eventType.color) + put(Calendars.CALENDAR_COLOR, calendar.color) put(Calendars.CALENDAR_COLOR_KEY, "") } - put(Calendars.CALENDAR_DISPLAY_NAME, eventType.title) + put(Calendars.CALENDAR_DISPLAY_NAME, calendar.title) } try { context.contentResolver.update(uri, values, null, null) - context.eventTypesDB.insertOrUpdate(eventType) + context.calendarsDB.insertOrUpdate(calendar) } catch (_: IllegalArgumentException) { } catch (e: SecurityException) { context.showErrorToast(e) } } - private fun getCalDAVColorKey(eventType: EventType): String? { - val colors = getAvailableCalDAVCalendarColors(eventType) - return colors[eventType.color] + private fun getCalDAVColorKey(calendar: CalendarEntity): String? { + val colors = getAvailableCalDAVCalendarColors(calendar) + return colors[calendar.color] } @SuppressLint("MissingPermission") fun getAvailableCalDAVCalendarColors( - eventType: EventType, + calendar: CalendarEntity, colorType: Int = Colors.TYPE_CALENDAR, ): Map { val colors = mutableMapOf() 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(colorType.toString(), eventType.caldavEmail) + val selectionArgs = arrayOf(colorType.toString(), calendar.caldavEmail) context.queryCursor(uri, projection, selection, selectionArgs) { cursor -> val colorKey = cursor.getStringValue(Colors.COLOR_KEY) @@ -171,7 +171,7 @@ class CalDAVHelper(val context: Context) { @SuppressLint("MissingPermission") private fun fetchCalDAVCalendarEvents( calendar: CalDAVCalendar, - eventTypeId: Long, + localCalendarId: Long, showToasts: Boolean, ) { val calendarId = calendar.id @@ -282,7 +282,7 @@ class CalDAVHelper(val context: Context) { importId = importId, timeZone = eventTimeZone, flags = allDay, - eventType = eventTypeId, + calendarId = localCalendarId, source = source, accessLevel = accessLevel, availability = availability, @@ -309,7 +309,7 @@ class CalDAVHelper(val context: Context) { event = parentEvent, addToCalDAV = false, showToasts = false, - enableEventType = false, + enableCalendar = false, updateWidgets = false ) } @@ -325,7 +325,7 @@ class CalDAVHelper(val context: Context) { event = event, addToCalDAV = false, showToasts = false, - enableEventType = false, + enableCalendar = false, updateWidgets = false ) } else { @@ -386,7 +386,7 @@ class CalDAVHelper(val context: Context) { event = event, updateAtCalDAV = false, showToasts = false, - enableEventType = false, + enableCalendar = false, updateWidgets = false ) } @@ -397,7 +397,7 @@ class CalDAVHelper(val context: Context) { event = event, addToCalDAV = false, showToasts = false, - enableEventType = false, + enableCalendar = false, updateWidgets = false ) } @@ -507,7 +507,10 @@ class CalDAVHelper(val context: Context) { ) } - private fun fillEventContentValues(event: Event, originalInstanceTime: Long? = null): ContentValues { + private fun fillEventContentValues( + event: Event, + originalInstanceTime: Long? = null + ): ContentValues { val calendarId = event.getCalDAVCalendarId() return ContentValues().apply { put(Events.CALENDAR_ID, calendarId) @@ -521,8 +524,8 @@ class CalDAVHelper(val context: Context) { if (event.color == 0) { put(Events.EVENT_COLOR_KEY, "") } else { - val eventType = eventsHelper.getEventTypeWithCalDAVCalendarId(calendarId)!! - val colors = getAvailableCalDAVCalendarColors(eventType, Colors.TYPE_EVENT) + val calendar = eventsHelper.getCalendarWithCalDAVCalendarId(calendarId)!! + val colors = getAvailableCalDAVCalendarColors(calendar, Colors.TYPE_EVENT) put(Events.EVENT_COLOR_KEY, colors[event.color]) } diff --git a/app/src/main/kotlin/org/fossify/calendar/helpers/Config.kt b/app/src/main/kotlin/org/fossify/calendar/helpers/Config.kt index 1aa142c32..b37c4d35e 100644 --- a/app/src/main/kotlin/org/fossify/calendar/helpers/Config.kt +++ b/app/src/main/kotlin/org/fossify/calendar/helpers/Config.kt @@ -10,7 +10,6 @@ import org.fossify.commons.extensions.getDefaultAlarmTitle import org.fossify.commons.helpers.BaseConfig import org.fossify.commons.helpers.DAY_MINUTES import org.fossify.commons.helpers.YEAR_SECONDS -import java.util.Arrays class Config(context: Context) : BaseConfig(context) { companion object { @@ -27,11 +26,13 @@ class Config(context: Context) : BaseConfig(context) { var startWeekWithCurrentDay: Boolean get() = prefs.getBoolean(START_WEEK_WITH_CURRENT_DAY, false) - set(startWeekWithCurrentDay) = prefs.edit().putBoolean(START_WEEK_WITH_CURRENT_DAY, startWeekWithCurrentDay).apply() + set(startWeekWithCurrentDay) = prefs.edit() + .putBoolean(START_WEEK_WITH_CURRENT_DAY, startWeekWithCurrentDay).apply() var showMidnightSpanningEventsAtTop: Boolean get() = prefs.getBoolean(SHOW_MIDNIGHT_SPANNING_EVENTS_AT_TOP, true) - set(midnightSpanning) = prefs.edit().putBoolean(SHOW_MIDNIGHT_SPANNING_EVENTS_AT_TOP, midnightSpanning).apply() + set(midnightSpanning) = prefs.edit() + .putBoolean(SHOW_MIDNIGHT_SPANNING_EVENTS_AT_TOP, midnightSpanning).apply() var allowCustomizeDayCount: Boolean get() = prefs.getBoolean(ALLOW_CUSTOMIZE_DAY_COUNT, true) @@ -43,13 +44,20 @@ class Config(context: Context) : BaseConfig(context) { @Deprecated("Not used on Oreo+ devices") var reminderSoundUri: String - get() = prefs.getString(REMINDER_SOUND_URI, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION).toString())!! + get() = prefs.getString( + REMINDER_SOUND_URI, + RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION).toString() + )!! set(reminderSoundUri) = prefs.edit().putString(REMINDER_SOUND_URI, reminderSoundUri).apply() @Deprecated("Not used on Oreo+ devices") var reminderSoundTitle: String - get() = prefs.getString(REMINDER_SOUND_TITLE, context.getDefaultAlarmTitle(RingtoneManager.TYPE_NOTIFICATION))!! - set(reminderSoundTitle) = prefs.edit().putString(REMINDER_SOUND_TITLE, reminderSoundTitle).apply() + get() = prefs.getString( + REMINDER_SOUND_TITLE, + context.getDefaultAlarmTitle(RingtoneManager.TYPE_NOTIFICATION) + )!! + set(reminderSoundTitle) = prefs.edit().putString(REMINDER_SOUND_TITLE, reminderSoundTitle) + .apply() @Deprecated("Not used on Oreo+ devices") var lastSoundUri: String @@ -58,7 +66,8 @@ class Config(context: Context) : BaseConfig(context) { var lastReminderChannel: Long get() = prefs.getLong(LAST_REMINDER_CHANNEL_ID, 0L) - set(lastReminderChannel) = prefs.edit().putLong(LAST_REMINDER_CHANNEL_ID, lastReminderChannel).apply() + set(lastReminderChannel) = prefs.edit() + .putLong(LAST_REMINDER_CHANNEL_ID, lastReminderChannel).apply() var storedView: Int get() = prefs.getInt(VIEW, MONTHLY_VIEW) @@ -66,37 +75,43 @@ class Config(context: Context) : BaseConfig(context) { var lastEventReminderMinutes1: Int get() = prefs.getInt(LAST_EVENT_REMINDER_MINUTES, 10) - set(lastEventReminderMinutes) = prefs.edit().putInt(LAST_EVENT_REMINDER_MINUTES, lastEventReminderMinutes).apply() + set(lastEventReminderMinutes) = prefs.edit() + .putInt(LAST_EVENT_REMINDER_MINUTES, lastEventReminderMinutes).apply() var lastEventReminderMinutes2: Int get() = prefs.getInt(LAST_EVENT_REMINDER_MINUTES_2, REMINDER_OFF) - set(lastEventReminderMinutes2) = prefs.edit().putInt(LAST_EVENT_REMINDER_MINUTES_2, lastEventReminderMinutes2).apply() + set(lastEventReminderMinutes2) = prefs.edit() + .putInt(LAST_EVENT_REMINDER_MINUTES_2, lastEventReminderMinutes2).apply() var lastEventReminderMinutes3: Int get() = prefs.getInt(LAST_EVENT_REMINDER_MINUTES_3, REMINDER_OFF) - set(lastEventReminderMinutes3) = prefs.edit().putInt(LAST_EVENT_REMINDER_MINUTES_3, lastEventReminderMinutes3).apply() + set(lastEventReminderMinutes3) = prefs.edit() + .putInt(LAST_EVENT_REMINDER_MINUTES_3, lastEventReminderMinutes3).apply() var displayPastEvents: Int get() = prefs.getInt(DISPLAY_PAST_EVENTS, DAY_MINUTES) set(displayPastEvents) = prefs.edit().putInt(DISPLAY_PAST_EVENTS, displayPastEvents).apply() - var displayEventTypes: Set - get() = prefs.getStringSet(DISPLAY_EVENT_TYPES, HashSet())!! - set(displayEventTypes) = prefs.edit().remove(DISPLAY_EVENT_TYPES).putStringSet(DISPLAY_EVENT_TYPES, displayEventTypes).apply() + var displayCalendars: Set + get() = prefs.getStringSet(DISPLAY_CALENDARS, HashSet())!! + set(displayCalendars) = prefs.edit().remove(DISPLAY_CALENDARS) + .putStringSet(DISPLAY_CALENDARS, displayCalendars).apply() - var quickFilterEventTypes: Set - get() = prefs.getStringSet(QUICK_FILTER_EVENT_TYPES, HashSet())!! - set(quickFilterEventTypes) = prefs.edit().remove(QUICK_FILTER_EVENT_TYPES).putStringSet(QUICK_FILTER_EVENT_TYPES, quickFilterEventTypes).apply() + var quickFilterCalendars: Set + get() = prefs.getStringSet(QUICK_FILTER_CALENDARS, HashSet())!! + set(quickFilterCalendars) = prefs.edit().remove(QUICK_FILTER_CALENDARS) + .putStringSet(QUICK_FILTER_CALENDARS, quickFilterCalendars).apply() - fun addQuickFilterEventType(type: String) { - val currQuickFilterEventTypes = HashSet(quickFilterEventTypes) - currQuickFilterEventTypes.add(type) - quickFilterEventTypes = currQuickFilterEventTypes + fun addQuickFilterCalendar(type: String) { + val currQuickFilterCalendars = HashSet(quickFilterCalendars) + currQuickFilterCalendars.add(type) + quickFilterCalendars = currQuickFilterCalendars } var listWidgetViewToOpen: Int get() = prefs.getInt(LIST_WIDGET_VIEW_TO_OPEN, DAILY_VIEW) - set(viewToOpenFromListWidget) = prefs.edit().putInt(LIST_WIDGET_VIEW_TO_OPEN, viewToOpenFromListWidget).apply() + set(viewToOpenFromListWidget) = prefs.edit() + .putInt(LIST_WIDGET_VIEW_TO_OPEN, viewToOpenFromListWidget).apply() var caldavSync: Boolean get() = prefs.getBoolean(CALDAV_SYNC, false) @@ -110,28 +125,36 @@ class Config(context: Context) : BaseConfig(context) { set(calendarIDs) = prefs.edit().putString(CALDAV_SYNCED_CALENDAR_IDS, calendarIDs).apply() var lastUsedCaldavCalendarId: Int - get() = prefs.getInt(LAST_USED_CALDAV_CALENDAR, getSyncedCalendarIdsAsList().first().toInt()) + get() = prefs.getInt( + LAST_USED_CALDAV_CALENDAR, + getSyncedCalendarIdsAsList().first().toInt() + ) set(calendarId) = prefs.edit().putInt(LAST_USED_CALDAV_CALENDAR, calendarId).apply() - var lastUsedLocalEventTypeId: Long - get() = prefs.getLong(LAST_USED_LOCAL_EVENT_TYPE_ID, LOCAL_CALENDAR_ID) - set(lastUsedLocalEventTypeId) = prefs.edit().putLong(LAST_USED_LOCAL_EVENT_TYPE_ID, lastUsedLocalEventTypeId).apply() + var lastUsedLocalCalendarId: Long + get() = prefs.getLong(LAST_USED_LOCAL_CALENDAR_ID, LOCAL_CALENDAR_ID) + set(lastUsedLocalCalendarId) = prefs.edit() + .putLong(LAST_USED_LOCAL_CALENDAR_ID, lastUsedLocalCalendarId).apply() - var lastUsedIgnoreEventTypesState: Boolean - get() = prefs.getBoolean(LAST_USED_IGNORE_EVENT_TYPES_STATE, false) - set(lastUsedIgnoreEventTypesState) = prefs.edit().putBoolean(LAST_USED_IGNORE_EVENT_TYPES_STATE, lastUsedIgnoreEventTypesState).apply() + var lastUsedIgnoreCalendarsState: Boolean + get() = prefs.getBoolean(LAST_USED_IGNORE_CALENDARS_STATE, false) + set(lastUsedIgnoreCalendarsState) = prefs.edit() + .putBoolean(LAST_USED_IGNORE_CALENDARS_STATE, lastUsedIgnoreCalendarsState).apply() var reminderAudioStream: Int get() = prefs.getInt(REMINDER_AUDIO_STREAM, AudioManager.STREAM_NOTIFICATION) - set(reminderAudioStream) = prefs.edit().putInt(REMINDER_AUDIO_STREAM, reminderAudioStream).apply() + set(reminderAudioStream) = prefs.edit().putInt(REMINDER_AUDIO_STREAM, reminderAudioStream) + .apply() var replaceDescription: Boolean get() = prefs.getBoolean(REPLACE_DESCRIPTION, false) - set(replaceDescription) = prefs.edit().putBoolean(REPLACE_DESCRIPTION, replaceDescription).apply() + set(replaceDescription) = prefs.edit().putBoolean(REPLACE_DESCRIPTION, replaceDescription) + .apply() var displayDescription: Boolean get() = prefs.getBoolean(DISPLAY_DESCRIPTION, true) - set(displayDescription) = prefs.edit().putBoolean(DISPLAY_DESCRIPTION, displayDescription).apply() + set(displayDescription) = prefs.edit().putBoolean(DISPLAY_DESCRIPTION, displayDescription) + .apply() var showGrid: Boolean get() = prefs.getBoolean(SHOW_GRID, false) @@ -147,32 +170,36 @@ class Config(context: Context) : BaseConfig(context) { var dimCompletedTasks: Boolean get() = prefs.getBoolean(DIM_COMPLETED_TASKS, true) - set(dimCompletedTasks) = prefs.edit().putBoolean(DIM_COMPLETED_TASKS, dimCompletedTasks).apply() + set(dimCompletedTasks) = prefs.edit().putBoolean(DIM_COMPLETED_TASKS, dimCompletedTasks) + .apply() fun getSyncedCalendarIdsAsList() = - caldavSyncedCalendarIds.split(",").filter { it.trim().isNotEmpty() }.map { Integer.parseInt(it) }.toMutableList() as ArrayList + caldavSyncedCalendarIds.split(",").filter { it.trim().isNotEmpty() } + .map { Integer.parseInt(it) }.toMutableList() as ArrayList - fun getDisplayEventTypessAsList() = displayEventTypes.map { it.toLong() }.toMutableList() as ArrayList + fun getDisplayCalendarsAsList() = + displayCalendars.map { it.toLong() }.toMutableList() as ArrayList - fun addDisplayEventType(type: String) { - addDisplayEventTypes(HashSet(Arrays.asList(type))) + fun addDisplayCalendar(type: String) { + addDisplayCalendars(HashSet(listOf(type))) } - private fun addDisplayEventTypes(types: Set) { - val currDisplayEventTypes = HashSet(displayEventTypes) - currDisplayEventTypes.addAll(types) - displayEventTypes = currDisplayEventTypes + private fun addDisplayCalendars(types: Set) { + val currDisplayCalendars = HashSet(displayCalendars) + currDisplayCalendars.addAll(types) + displayCalendars = currDisplayCalendars } - fun removeDisplayEventTypes(types: Set) { - val currDisplayEventTypes = HashSet(displayEventTypes) - currDisplayEventTypes.removeAll(types) - displayEventTypes = currDisplayEventTypes + fun removeDisplayCalendars(types: Set) { + val currDisplayCalendars = HashSet(displayCalendars) + currDisplayCalendars.removeAll(types) + displayCalendars = currDisplayCalendars } var usePreviousEventReminders: Boolean get() = prefs.getBoolean(USE_PREVIOUS_EVENT_REMINDERS, true) - set(usePreviousEventReminders) = prefs.edit().putBoolean(USE_PREVIOUS_EVENT_REMINDERS, usePreviousEventReminders).apply() + set(usePreviousEventReminders) = prefs.edit() + .putBoolean(USE_PREVIOUS_EVENT_REMINDERS, usePreviousEventReminders).apply() var defaultReminder1: Int get() = prefs.getInt(DEFAULT_REMINDER_1, 10) @@ -192,7 +219,8 @@ class Config(context: Context) : BaseConfig(context) { var lastVibrateOnReminder: Boolean get() = prefs.getBoolean(LAST_VIBRATE_ON_REMINDER, context.config.vibrateOnReminder) - set(lastVibrateOnReminder) = prefs.edit().putBoolean(LAST_VIBRATE_ON_REMINDER, lastVibrateOnReminder).apply() + set(lastVibrateOnReminder) = prefs.edit() + .putBoolean(LAST_VIBRATE_ON_REMINDER, lastVibrateOnReminder).apply() var defaultStartTime: Int get() = prefs.getInt(DEFAULT_START_TIME, DEFAULT_START_TIME_NEXT_FULL_HOUR) @@ -202,29 +230,37 @@ class Config(context: Context) : BaseConfig(context) { get() = prefs.getInt(DEFAULT_DURATION, 0) set(defaultDuration) = prefs.edit().putInt(DEFAULT_DURATION, defaultDuration).apply() - var defaultEventTypeId: Long - get() = prefs.getLong(DEFAULT_EVENT_TYPE_ID, -1L) - set(defaultEventTypeId) = prefs.edit().putLong(DEFAULT_EVENT_TYPE_ID, defaultEventTypeId).apply() + var defaultCalendarId: Long + get() = prefs.getLong(DEFAULT_CALENDAR_ID, -1L) + set(defaultCalendarId) = prefs.edit().putLong(DEFAULT_CALENDAR_ID, defaultCalendarId) + .apply() var allowChangingTimeZones: Boolean get() = prefs.getBoolean(ALLOW_CHANGING_TIME_ZONES, false) - set(allowChangingTimeZones) = prefs.edit().putBoolean(ALLOW_CHANGING_TIME_ZONES, allowChangingTimeZones).apply() + set(allowChangingTimeZones) = prefs.edit() + .putBoolean(ALLOW_CHANGING_TIME_ZONES, allowChangingTimeZones).apply() var addBirthdaysAutomatically: Boolean get() = prefs.getBoolean(ADD_BIRTHDAYS_AUTOMATICALLY, false) - set(addBirthdaysAutomatically) = prefs.edit().putBoolean(ADD_BIRTHDAYS_AUTOMATICALLY, addBirthdaysAutomatically).apply() + set(addBirthdaysAutomatically) = prefs.edit() + .putBoolean(ADD_BIRTHDAYS_AUTOMATICALLY, addBirthdaysAutomatically).apply() var addAnniversariesAutomatically: Boolean get() = prefs.getBoolean(ADD_ANNIVERSARIES_AUTOMATICALLY, false) - set(addAnniversariesAutomatically) = prefs.edit().putBoolean(ADD_ANNIVERSARIES_AUTOMATICALLY, addAnniversariesAutomatically).apply() + set(addAnniversariesAutomatically) = prefs.edit() + .putBoolean(ADD_ANNIVERSARIES_AUTOMATICALLY, addAnniversariesAutomatically).apply() var birthdayReminders: ArrayList - get() = prefs.getString(BIRTHDAY_REMINDERS, REMINDER_DEFAULT_VALUE)!!.split(",").map { it.toInt() }.toMutableList() as ArrayList - set(birthdayReminders) = prefs.edit().putString(BIRTHDAY_REMINDERS, birthdayReminders.joinToString(",")).apply() + get() = prefs.getString(BIRTHDAY_REMINDERS, REMINDER_DEFAULT_VALUE)!!.split(",") + .map { it.toInt() }.toMutableList() as ArrayList + set(birthdayReminders) = prefs.edit() + .putString(BIRTHDAY_REMINDERS, birthdayReminders.joinToString(",")).apply() var anniversaryReminders: ArrayList - get() = prefs.getString(ANNIVERSARY_REMINDERS, REMINDER_DEFAULT_VALUE)!!.split(",").map { it.toInt() }.toMutableList() as ArrayList - set(anniversaryReminders) = prefs.edit().putString(ANNIVERSARY_REMINDERS, anniversaryReminders.joinToString(",")).apply() + get() = prefs.getString(ANNIVERSARY_REMINDERS, REMINDER_DEFAULT_VALUE)!!.split(",") + .map { it.toInt() }.toMutableList() as ArrayList + set(anniversaryReminders) = prefs.edit() + .putString(ANNIVERSARY_REMINDERS, anniversaryReminders.joinToString(",")).apply() var exportEvents: Boolean get() = prefs.getBoolean(EXPORT_EVENTS, true) @@ -236,11 +272,13 @@ class Config(context: Context) : BaseConfig(context) { var exportPastEntries: Boolean get() = prefs.getBoolean(EXPORT_PAST_EVENTS, true) - set(exportPastEvents) = prefs.edit().putBoolean(EXPORT_PAST_EVENTS, exportPastEvents).apply() + set(exportPastEvents) = prefs.edit().putBoolean(EXPORT_PAST_EVENTS, exportPastEvents) + .apply() var weeklyViewItemHeightMultiplier: Float get() = prefs.getFloat(WEEKLY_VIEW_ITEM_HEIGHT_MULTIPLIER, 1f) - set(weeklyViewItemHeightMultiplier) = prefs.edit().putFloat(WEEKLY_VIEW_ITEM_HEIGHT_MULTIPLIER, weeklyViewItemHeightMultiplier).apply() + set(weeklyViewItemHeightMultiplier) = prefs.edit() + .putFloat(WEEKLY_VIEW_ITEM_HEIGHT_MULTIPLIER, weeklyViewItemHeightMultiplier).apply() var weeklyViewDays: Int get() = prefs.getInt(WEEKLY_VIEW_DAYS, 7) @@ -248,31 +286,38 @@ class Config(context: Context) : BaseConfig(context) { var highlightWeekends: Boolean get() = prefs.getBoolean(HIGHLIGHT_WEEKENDS, false) - set(highlightWeekends) = prefs.edit().putBoolean(HIGHLIGHT_WEEKENDS, highlightWeekends).apply() + set(highlightWeekends) = prefs.edit().putBoolean(HIGHLIGHT_WEEKENDS, highlightWeekends) + .apply() var highlightWeekendsColor: Int get() = prefs.getInt(HIGHLIGHT_WEEKENDS_COLOR, context.resources.getColor(R.color.red_text)) - set(highlightWeekendsColor) = prefs.edit().putInt(HIGHLIGHT_WEEKENDS_COLOR, highlightWeekendsColor).apply() + set(highlightWeekendsColor) = prefs.edit() + .putInt(HIGHLIGHT_WEEKENDS_COLOR, highlightWeekendsColor).apply() var lastUsedEventSpan: Int get() = prefs.getInt(LAST_USED_EVENT_SPAN, YEAR_SECONDS) - set(lastUsedEventSpan) = prefs.edit().putInt(LAST_USED_EVENT_SPAN, lastUsedEventSpan).apply() + set(lastUsedEventSpan) = prefs.edit().putInt(LAST_USED_EVENT_SPAN, lastUsedEventSpan) + .apply() var allowCreatingTasks: Boolean get() = prefs.getBoolean(ALLOW_CREATING_TASKS, true) - set(allowCreatingTasks) = prefs.edit().putBoolean(ALLOW_CREATING_TASKS, allowCreatingTasks).apply() + set(allowCreatingTasks) = prefs.edit().putBoolean(ALLOW_CREATING_TASKS, allowCreatingTasks) + .apply() var wasFilteredOutWarningShown: Boolean get() = prefs.getBoolean(WAS_FILTERED_OUT_WARNING_SHOWN, false) - set(wasFilteredOutWarningShown) = prefs.edit().putBoolean(WAS_FILTERED_OUT_WARNING_SHOWN, wasFilteredOutWarningShown).apply() + set(wasFilteredOutWarningShown) = prefs.edit() + .putBoolean(WAS_FILTERED_OUT_WARNING_SHOWN, wasFilteredOutWarningShown).apply() - var autoBackupEventTypes: Set - get() = prefs.getStringSet(AUTO_BACKUP_EVENT_TYPES, HashSet())!! - set(autoBackupEventTypes) = prefs.edit().remove(AUTO_BACKUP_EVENT_TYPES).putStringSet(AUTO_BACKUP_EVENT_TYPES, autoBackupEventTypes).apply() + var autoBackupCalendars: Set + get() = prefs.getStringSet(AUTO_BACKUP_CALENDARS, HashSet())!! + set(autoBackupCalendars) = prefs.edit().remove(AUTO_BACKUP_CALENDARS) + .putStringSet(AUTO_BACKUP_CALENDARS, autoBackupCalendars).apply() var autoBackupEvents: Boolean get() = prefs.getBoolean(AUTO_BACKUP_EVENTS, true) - set(autoBackupEvents) = prefs.edit().putBoolean(AUTO_BACKUP_EVENTS, autoBackupEvents).apply() + set(autoBackupEvents) = prefs.edit().putBoolean(AUTO_BACKUP_EVENTS, autoBackupEvents) + .apply() var autoBackupTasks: Boolean get() = prefs.getBoolean(AUTO_BACKUP_TASKS, true) @@ -280,9 +325,11 @@ class Config(context: Context) : BaseConfig(context) { var autoBackupPastEntries: Boolean get() = prefs.getBoolean(AUTO_BACKUP_PAST_ENTRIES, true) - set(autoBackupPastEntries) = prefs.edit().putBoolean(AUTO_BACKUP_PAST_ENTRIES, autoBackupPastEntries).apply() + set(autoBackupPastEntries) = prefs.edit() + .putBoolean(AUTO_BACKUP_PAST_ENTRIES, autoBackupPastEntries).apply() var lastUsedShowListWidgetHeader: Boolean get() = prefs.getBoolean(LAST_USED_SHOW_LIST_WIDGET_HEADER, true) - set(lastUsedShowListWidgetHeader) = prefs.edit().putBoolean(LAST_USED_SHOW_LIST_WIDGET_HEADER, lastUsedShowListWidgetHeader).apply() + set(lastUsedShowListWidgetHeader) = prefs.edit() + .putBoolean(LAST_USED_SHOW_LIST_WIDGET_HEADER, lastUsedShowListWidgetHeader).apply() } diff --git a/app/src/main/kotlin/org/fossify/calendar/helpers/Constants.kt b/app/src/main/kotlin/org/fossify/calendar/helpers/Constants.kt index c0b1b4e92..661c2486f 100644 --- a/app/src/main/kotlin/org/fossify/calendar/helpers/Constants.kt +++ b/app/src/main/kotlin/org/fossify/calendar/helpers/Constants.kt @@ -97,14 +97,14 @@ const val VIEW = "view" const val LAST_EVENT_REMINDER_MINUTES = "reminder_minutes" const val LAST_EVENT_REMINDER_MINUTES_2 = "reminder_minutes_2" const val LAST_EVENT_REMINDER_MINUTES_3 = "reminder_minutes_3" -const val DISPLAY_EVENT_TYPES = "display_event_types" -const val QUICK_FILTER_EVENT_TYPES = "quick_filter_event_types" +const val DISPLAY_CALENDARS = "display_event_types" +const val QUICK_FILTER_CALENDARS = "quick_filter_event_types" const val LIST_WIDGET_VIEW_TO_OPEN = "list_widget_view_to_open" const val CALDAV_SYNC = "caldav_sync" const val CALDAV_SYNCED_CALENDAR_IDS = "caldav_synced_calendar_ids" const val LAST_USED_CALDAV_CALENDAR = "last_used_caldav_calendar" -const val LAST_USED_LOCAL_EVENT_TYPE_ID = "last_used_local_event_type_id" -const val LAST_USED_IGNORE_EVENT_TYPES_STATE = "last_used_ignore_event_types_state" +const val LAST_USED_LOCAL_CALENDAR_ID = "last_used_local_event_type_id" +const val LAST_USED_IGNORE_CALENDARS_STATE = "last_used_ignore_event_types_state" const val DISPLAY_PAST_EVENTS = "display_past_events" const val DISPLAY_DESCRIPTION = "display_description" const val REPLACE_DESCRIPTION = "replace_description" @@ -123,7 +123,7 @@ const val PULL_TO_REFRESH = "pull_to_refresh" const val LAST_VIBRATE_ON_REMINDER = "last_vibrate_on_reminder" const val DEFAULT_START_TIME = "default_start_time" const val DEFAULT_DURATION = "default_duration" -const val DEFAULT_EVENT_TYPE_ID = "default_event_type_id" +const val DEFAULT_CALENDAR_ID = "default_event_type_id" const val ALLOW_CHANGING_TIME_ZONES = "allow_changing_time_zones" const val ADD_BIRTHDAYS_AUTOMATICALLY = "add_birthdays_automatically" const val ADD_ANNIVERSARIES_AUTOMATICALLY = "add_anniversaries_automatically" @@ -143,7 +143,7 @@ const val WAS_FILTERED_OUT_WARNING_SHOWN = "was_filtered_out_warning_shown" const val AUTO_BACKUP = "auto_backup" const val AUTO_BACKUP_FOLDER = "auto_backup_folder" const val AUTO_BACKUP_FILENAME = "auto_backup_filename" -const val AUTO_BACKUP_EVENT_TYPES = "auto_backup_event_types" +const val AUTO_BACKUP_CALENDARS = "auto_backup_event_types" const val AUTO_BACKUP_EVENTS = "auto_backup_events" const val AUTO_BACKUP_TASKS = "auto_backup_tasks" const val AUTO_BACKUP_PAST_ENTRIES = "auto_backup_past_entries" @@ -276,7 +276,7 @@ const val ATTENDEES = "ATTENDEES" const val ORIGINAL_ATTENDEES = "ORIGINAL_ATTENDEES" const val AVAILABILITY = "AVAILABILITY" const val CLASS = "CLASS" -const val EVENT_TYPE_ID = "EVENT_TYPE_ID" +const val CALENDAR_ID = "CALENDAR_ID" const val EVENT_CALENDAR_ID = "EVENT_CALENDAR_ID" const val IS_NEW_EVENT = "IS_NEW_EVENT" const val EVENT_COLOR = "EVENT_COLOR" diff --git a/app/src/main/kotlin/org/fossify/calendar/helpers/EventsHelper.kt b/app/src/main/kotlin/org/fossify/calendar/helpers/EventsHelper.kt index 99136dcdd..0609177f7 100644 --- a/app/src/main/kotlin/org/fossify/calendar/helpers/EventsHelper.kt +++ b/app/src/main/kotlin/org/fossify/calendar/helpers/EventsHelper.kt @@ -6,9 +6,21 @@ import android.widget.Toast import androidx.annotation.ColorRes import androidx.collection.LongSparseArray import org.fossify.calendar.R -import org.fossify.calendar.extensions.* +import org.fossify.calendar.extensions.calDAVHelper +import org.fossify.calendar.extensions.calendarsDB +import org.fossify.calendar.extensions.cancelNotification +import org.fossify.calendar.extensions.cancelPendingIntent +import org.fossify.calendar.extensions.completedTasksDB +import org.fossify.calendar.extensions.config +import org.fossify.calendar.extensions.eventsDB +import org.fossify.calendar.extensions.isTsOnProperDay +import org.fossify.calendar.extensions.isXWeeklyRepetition +import org.fossify.calendar.extensions.maybeAdjustRepeatLimitCount +import org.fossify.calendar.extensions.scheduleNextEventReminder +import org.fossify.calendar.extensions.seconds +import org.fossify.calendar.extensions.updateWidgets +import org.fossify.calendar.models.CalendarEntity import org.fossify.calendar.models.Event -import org.fossify.calendar.models.EventType import org.fossify.commons.extensions.getProperPrimaryColor import org.fossify.commons.extensions.toast import org.fossify.commons.helpers.CHOPPED_LIST_DEFAULT_SIZE @@ -17,58 +29,67 @@ import org.fossify.commons.helpers.ensureBackgroundThread class EventsHelper(val context: Context) { private val config = context.config private val eventsDB = context.eventsDB - private val eventTypesDB = context.eventTypesDB + private val calendarsDB = context.calendarsDB private val completedTasksDB = context.completedTasksDB - fun getEventTypes(activity: Activity, showWritableOnly: Boolean, callback: (eventTypes: ArrayList) -> Unit) { + fun getCalendars( + activity: Activity, + showWritableOnly: Boolean, + callback: (calendars: ArrayList) -> Unit + ) { ensureBackgroundThread { - var eventTypes = ArrayList() + var calendars = ArrayList() try { - eventTypes = eventTypesDB.getEventTypes().toMutableList() as ArrayList + calendars = calendarsDB.getCalendars().toMutableList() as ArrayList } catch (ignored: Exception) { } if (showWritableOnly) { val caldavCalendars = activity.calDAVHelper.getCalDAVCalendars("", true) - eventTypes = eventTypes.filter { - val eventType = it - it.caldavCalendarId == 0 || caldavCalendars.firstOrNull { it.id == eventType.caldavCalendarId }?.canWrite() == true - }.toMutableList() as ArrayList + calendars = calendars.filter { + val calendar = it + it.caldavCalendarId == 0 || caldavCalendars.firstOrNull { it.id == calendar.caldavCalendarId } + ?.canWrite() == true + }.toMutableList() as ArrayList } activity.runOnUiThread { - callback(eventTypes) + callback(calendars) } } } - fun getEventTypesSync() = eventTypesDB.getEventTypes().toMutableList() as ArrayList + fun getCalendarsSync() = calendarsDB.getCalendars().toMutableList() as ArrayList - fun insertOrUpdateEventType(activity: Activity, eventType: EventType, callback: ((newEventTypeId: Long) -> Unit)? = null) { + fun insertOrUpdateCalendar( + activity: Activity, + calendar: CalendarEntity, + callback: ((newCalendarId: Long) -> Unit)? = null + ) { ensureBackgroundThread { - val eventTypeId = insertOrUpdateEventTypeSync(eventType) + val calendarId = insertOrUpdateCalendarSync(calendar) activity.runOnUiThread { - callback?.invoke(eventTypeId) + callback?.invoke(calendarId) } } } - fun insertOrUpdateEventTypeSync(eventType: EventType): Long { - if (eventType.id != null && eventType.id!! > 0 && eventType.caldavCalendarId != 0) { - context.calDAVHelper.updateCalDAVCalendar(eventType) + fun insertOrUpdateCalendarSync(calendar: CalendarEntity): Long { + if (calendar.id != null && calendar.id!! > 0 && calendar.caldavCalendarId != 0) { + context.calDAVHelper.updateCalDAVCalendar(calendar) } - val newId = eventTypesDB.insertOrUpdate(eventType) - if (eventType.id == null) { - config.addDisplayEventType(newId.toString()) + val newId = calendarsDB.insertOrUpdate(calendar) + if (calendar.id == null) { + config.addDisplayCalendar(newId.toString()) - if (config.quickFilterEventTypes.isNotEmpty()) { - config.addQuickFilterEventType(newId.toString()) + if (config.quickFilterCalendars.isNotEmpty()) { + config.addQuickFilterCalendar(newId.toString()) } else { - val eventTypes = getEventTypesSync() - if (eventTypes.size == 2) { - eventTypes.forEach { - config.addQuickFilterEventType(it.id.toString()) + val calendars = getCalendarsSync() + if (calendars.size == 2) { + calendars.forEach { + config.addQuickFilterCalendar(it.id.toString()) } } } @@ -76,41 +97,44 @@ class EventsHelper(val context: Context) { return newId } - fun getEventTypeIdWithTitle(title: String) = eventTypesDB.getEventTypeIdWithTitle(title) ?: -1L + fun getCalendarIdWithTitle(title: String) = calendarsDB.getCalendarIdWithTitle(title) ?: -1L - fun getEventTypeIdWithClass(classId: Int) = eventTypesDB.getEventTypeIdWithClass(classId) ?: -1L + fun getCalendarIdWithClass(classId: Int) = calendarsDB.getCalendarIdWithClass(classId) ?: -1L - private fun getLocalEventTypeIdWithTitle(title: String) = eventTypesDB.getLocalEventTypeIdWithTitle(title) ?: -1L + private fun getLocalCalendarIdWithTitle(title: String) = + calendarsDB.getLocalCalendarIdWithTitle(title) ?: -1L - private fun getLocalEventTypeIdWithClass(classId: Int) = eventTypesDB.getLocalEventTypeIdWithClass(classId) ?: -1L + private fun getLocalCalendarIdWithClass(classId: Int) = + calendarsDB.getLocalCalendarIdWithClass(classId) ?: -1L - fun getEventTypeWithCalDAVCalendarId(calendarId: Int) = eventTypesDB.getEventTypeWithCalDAVCalendarId(calendarId) + fun getCalendarWithCalDAVCalendarId(calendarId: Int) = + calendarsDB.getCalendarWithCalDAVCalendarId(calendarId) - fun deleteEventTypes(eventTypes: ArrayList, deleteEvents: Boolean) { - val typesToDelete = eventTypes + fun deleteCalendars(calendars: ArrayList, deleteEvents: Boolean) { + val typesToDelete = calendars .asSequence() .filter { it.caldavCalendarId == 0 && it.id != LOCAL_CALENDAR_ID } .toMutableList() val deleteIds = typesToDelete.map { it.id }.toMutableList() val deletedSet = deleteIds.map { it.toString() }.toHashSet() - config.removeDisplayEventTypes(deletedSet) + config.removeDisplayCalendars(deletedSet) if (deleteIds.isEmpty()) { return } - for (eventTypeId in deleteIds) { + for (calendarId in deleteIds) { if (deleteEvents) { - deleteEventsAndTasksWithType(eventTypeId!!) + deleteEventsAndTasksWithCalendarId(calendarId!!) } else { - eventsDB.resetEventsAndTasksWithType(eventTypeId!!) + eventsDB.resetEventsAndTasksWithCalendarId(calendarId!!) } } - eventTypesDB.deleteEventTypes(typesToDelete) + calendarsDB.deleteCalendars(typesToDelete) - if (getEventTypesSync().size == 1) { - config.quickFilterEventTypes = HashSet() + if (getCalendarsSync().size == 1) { + config.quickFilterCalendars = HashSet() } } @@ -118,7 +142,7 @@ class EventsHelper(val context: Context) { event: Event, addToCalDAV: Boolean, showToasts: Boolean, - enableEventType: Boolean = true, + enableCalendar: Boolean = true, eventOccurrenceTS: Long? = null, updateWidgets: Boolean = true, callback: ((id: Long) -> Unit)? = null @@ -129,7 +153,7 @@ class EventsHelper(val context: Context) { } event.id = eventsDB.insertOrUpdate(event) - ensureEventTypeVisibility(event, enableEventType) + ensureCalendarVisibility(event, enableCalendar) if (updateWidgets) context.updateWidgets() context.scheduleNextEventReminder(event, showToasts) @@ -140,9 +164,14 @@ class EventsHelper(val context: Context) { callback?.invoke(event.id!!) } - fun insertTask(task: Event, showToasts: Boolean, enableEventType: Boolean = true, callback: () -> Unit) { + fun insertTask( + task: Event, + showToasts: Boolean, + enableCalendar: Boolean = true, + callback: () -> Unit + ) { task.id = eventsDB.insertOrUpdate(task) - ensureEventTypeVisibility(task, enableEventType) + ensureCalendarVisibility(task, enableCalendar) context.updateWidgets() context.scheduleNextEventReminder(task, showToasts) callback() @@ -157,7 +186,7 @@ class EventsHelper(val context: Context) { } event.id = eventsDB.insertOrUpdate(event) - ensureEventTypeVisibility(event, true) + ensureCalendarVisibility(event, true) context.scheduleNextEventReminder(event, false) if (addToCalDAV && event.source != SOURCE_SIMPLE_CALENDAR && event.source != SOURCE_IMPORTED_ICS && config.caldavSync) { context.calDAVHelper.insertCalDAVEvent(event) @@ -172,12 +201,12 @@ class EventsHelper(val context: Context) { event: Event, updateAtCalDAV: Boolean, showToasts: Boolean, - enableEventType: Boolean = true, + enableCalendar: Boolean = true, updateWidgets: Boolean = true, callback: (() -> Unit)? = null ) { eventsDB.insertOrUpdate(event) - ensureEventTypeVisibility(event, enableEventType) + ensureCalendarVisibility(event, enableCalendar) if (updateWidgets) context.updateWidgets() context.scheduleNextEventReminder(event, showToasts) if (updateAtCalDAV && event.source != SOURCE_SIMPLE_CALENDAR && config.caldavSync) { @@ -199,11 +228,20 @@ class EventsHelper(val context: Context) { } } - fun editSelectedOccurrence(event: Event, eventOccurrenceTS: Long, showToasts: Boolean, callback: () -> Unit) { + fun editSelectedOccurrence( + event: Event, + eventOccurrenceTS: Long, + showToasts: Boolean, + callback: () -> Unit + ) { ensureBackgroundThread { - val originalEvent = eventsDB.getEventOrTaskWithId(event.id!!) ?: return@ensureBackgroundThread + val originalEvent = + eventsDB.getEventOrTaskWithId(event.id!!) ?: return@ensureBackgroundThread originalEvent.addRepetitionException(Formatter.getDayCodeFromTS(eventOccurrenceTS)) - eventsDB.updateEventRepetitionExceptions(originalEvent.repetitionExceptions.toString(), originalEvent.id!!) + eventsDB.updateEventRepetitionExceptions( + originalEvent.repetitionExceptions.toString(), + originalEvent.id!! + ) context.scheduleNextEventReminder(originalEvent, false) event.apply { @@ -228,10 +266,16 @@ class EventsHelper(val context: Context) { } } - fun editFutureOccurrences(event: Event, eventOccurrenceTS: Long, showToasts: Boolean, callback: () -> Unit) { + fun editFutureOccurrences( + event: Event, + eventOccurrenceTS: Long, + showToasts: Boolean, + callback: () -> Unit + ) { ensureBackgroundThread { val eventId = event.id!! - val originalEvent = eventsDB.getEventOrTaskWithId(event.id!!) ?: return@ensureBackgroundThread + val originalEvent = + eventsDB.getEventOrTaskWithId(event.id!!) ?: return@ensureBackgroundThread event.maybeAdjustRepeatLimitCount(originalEvent, eventOccurrenceTS) event.id = null addEventRepeatLimit(eventId, eventOccurrenceTS) @@ -249,19 +293,30 @@ class EventsHelper(val context: Context) { } } - fun editAllOccurrences(event: Event, originalStartTS: Long, originalEndTS: Long = 0, showToasts: Boolean, callback: () -> Unit) { + fun editAllOccurrences( + event: Event, + originalStartTS: Long, + originalEndTS: Long = 0, + showToasts: Boolean, + callback: () -> Unit + ) { ensureBackgroundThread { applyOriginalStartEndTimes(event, originalStartTS, originalEndTS) - updateEvent(event, updateAtCalDAV = !event.isTask(), showToasts = showToasts, callback = callback) + updateEvent( + event, + updateAtCalDAV = !event.isTask(), + showToasts = showToasts, + callback = callback + ) } } - private fun ensureEventTypeVisibility(event: Event, enableEventType: Boolean) { - if (enableEventType) { - val eventType = event.eventType.toString() - val displayEventTypes = config.displayEventTypes - if (!displayEventTypes.contains(eventType)) { - config.displayEventTypes = displayEventTypes.plus(eventType) + private fun ensureCalendarVisibility(event: Event, enableCalendar: Boolean) { + if (enableCalendar) { + val calendar = event.calendarId.toString() + val displayCalendars = config.displayCalendars + if (!displayCalendars.contains(calendar)) { + config.displayCalendars = displayCalendars.plus(calendar) } } } @@ -317,15 +372,17 @@ class EventsHelper(val context: Context) { } } - private fun deleteEventsAndTasksWithType(eventTypeId: Long) { - val eventIds = eventsDB.getEventAndTasksIdsByEventType(eventTypeId).toMutableList() + private fun deleteEventsAndTasksWithCalendarId(calendarId: Long) { + val eventIds = eventsDB.getEventAndTasksIdsByCalendar(calendarId).toMutableList() deleteEvents(eventIds, true) } fun addEventRepeatLimit(eventId: Long, occurrenceTS: Long) { val event = eventsDB.getEventOrTaskWithId(eventId) ?: return - val previousOccurrenceTS = occurrenceTS - event.repeatInterval // always update repeat limit of the occurrence preceding the one being edited - val repeatLimitDateTime = Formatter.getDateTimeFromTS(previousOccurrenceTS).withTimeAtStartOfDay() + val previousOccurrenceTS = + occurrenceTS - event.repeatInterval // always update repeat limit of the occurrence preceding the one being edited + val repeatLimitDateTime = + Formatter.getDateTimeFromTS(previousOccurrenceTS).withTimeAtStartOfDay() val repeatLimitTS = if (event.getIsAllDay()) { repeatLimitDateTime.seconds() } else { @@ -347,19 +404,30 @@ class EventsHelper(val context: Context) { } } - fun doEventTypesContainEventsOrTasks(eventTypeIds: ArrayList, callback: (contain: Boolean) -> Unit) { + fun doCalendarsContainEventsOrTasks( + calendarIds: ArrayList, + callback: (contain: Boolean) -> Unit + ) { ensureBackgroundThread { - val eventIds = eventsDB.getEventAndTasksIdsByEventType(eventTypeIds) + val eventIds = eventsDB.getEventAndTasksIdsByCalendar(calendarIds) callback(eventIds.isNotEmpty()) } } - fun deleteRepeatingEventOccurrence(parentEventId: Long, occurrenceTS: Long, addToCalDAV: Boolean) { + fun deleteRepeatingEventOccurrence( + parentEventId: Long, + occurrenceTS: Long, + addToCalDAV: Boolean + ) { ensureBackgroundThread { - val parentEvent = eventsDB.getEventOrTaskWithId(parentEventId) ?: return@ensureBackgroundThread + val parentEvent = + eventsDB.getEventOrTaskWithId(parentEventId) ?: return@ensureBackgroundThread val occurrenceDayCode = Formatter.getDayCodeFromTS(occurrenceTS) parentEvent.addRepetitionException(occurrenceDayCode) - eventsDB.updateEventRepetitionExceptions(parentEvent.repetitionExceptions.toString(), parentEventId) + eventsDB.updateEventRepetitionExceptions( + parentEvent.repetitionExceptions.toString(), + parentEventId + ) context.scheduleNextEventReminder(parentEvent, false) if (addToCalDAV && config.caldavSync) { @@ -393,24 +461,35 @@ class EventsHelper(val context: Context) { searchQuery: String = "", callback: (events: ArrayList) -> Unit ) { - val birthDayEventId = getLocalBirthdaysEventTypeId(createIfNotExists = false) - val anniversaryEventId = getAnniversariesEventTypeId(createIfNotExists = false) + val birthDayEventId = getLocalBirthdaysCalendarId(createIfNotExists = false) + val anniversaryEventId = getAnniversariesCalendarId(createIfNotExists = false) var events = ArrayList() if (applyTypeFilter) { - val displayEventTypes = context.config.displayEventTypes - if (displayEventTypes.isEmpty()) { + val displayCalendars = context.config.displayCalendars + if (displayCalendars.isEmpty()) { callback(ArrayList()) return } else { try { - val typesList = context.config.getDisplayEventTypessAsList() + val typesList = context.config.getDisplayCalendarsAsList() if (searchQuery.isEmpty()) { - events.addAll(eventsDB.getOneTimeEventsFromToWithTypes(toTS, fromTS, typesList).toMutableList() as ArrayList) + events.addAll( + eventsDB.getOneTimeEventsFromToWithCalendarIds( + toTS, + fromTS, + typesList + ).toMutableList() as ArrayList + ) } else { events.addAll( - eventsDB.getOneTimeEventsFromToWithTypesForSearch(toTS, fromTS, typesList, "%$searchQuery%").toMutableList() as ArrayList + eventsDB.getOneTimeEventsFromToWithTypesForSearch( + toTS, + fromTS, + typesList, + "%$searchQuery%" + ).toMutableList() as ArrayList ) } } catch (e: Exception) { @@ -421,9 +500,11 @@ class EventsHelper(val context: Context) { events.addAll( if (eventId == -1L) { - eventsDB.getOneTimeEventsOrTasksFromTo(toTS, fromTS).toMutableList() as ArrayList + eventsDB.getOneTimeEventsOrTasksFromTo(toTS, fromTS) + .toMutableList() as ArrayList } else { - eventsDB.getOneTimeEventFromToWithId(eventId, toTS, fromTS).toMutableList() as ArrayList + eventsDB.getOneTimeEventFromToWithId(eventId, toTS, fromTS) + .toMutableList() as ArrayList } ) } @@ -436,7 +517,7 @@ class EventsHelper(val context: Context) { .filterNot { it.repetitionExceptions.contains(Formatter.getDayCodeFromTS(it.startTS)) } .toMutableList() as ArrayList - val eventTypeColors = getEventTypeColors() + val calendarColors = getCalendarColors() events.forEach { if (it.isTask()) { @@ -446,8 +527,8 @@ class EventsHelper(val context: Context) { it.updateIsPastEvent() val originalEvent = eventsDB.getEventWithId(it.id!!) if (originalEvent != null && - (birthDayEventId != -1L && it.eventType == birthDayEventId) or - (anniversaryEventId != -1L && it.eventType == anniversaryEventId) + (birthDayEventId != -1L && it.calendarId == birthDayEventId) or + (anniversaryEventId != -1L && it.calendarId == anniversaryEventId) ) { val eventStartDate = Formatter.getDateFromTS(it.startTS) val originalEventStartDate = Formatter.getDateFromTS(originalEvent.startTS) @@ -460,63 +541,90 @@ class EventsHelper(val context: Context) { } if (it.color == 0) { - it.color = eventTypeColors.get(it.eventType) ?: context.getProperPrimaryColor() + it.color = calendarColors.get(it.calendarId) ?: context.getProperPrimaryColor() } } callback(events) } - fun createPredefinedEventType(title: String, @ColorRes colorResId: Int, type: Int, caldav: Boolean = false): Long { - val eventType = EventType(id = null, title = title, color = context.resources.getColor(colorResId), type = type) + fun createPredefinedCalendar( + title: String, @ColorRes colorResId: Int, type: Int, caldav: Boolean = false + ): Long { + val calendar = CalendarEntity( + id = null, + title = title, + color = context.resources.getColor(colorResId), + type = type + ) // check if the event type already exists but without the type (e.g. BIRTHDAY_EVENT) so as to avoid duplication - val originalEventTypeId = if (caldav) { - getEventTypeIdWithTitle(title) + val originalCalendarId = if (caldav) { + getCalendarIdWithTitle(title) } else { - getLocalEventTypeIdWithTitle(title) + getLocalCalendarIdWithTitle(title) } - if (originalEventTypeId != -1L) { - eventType.id = originalEventTypeId + if (originalCalendarId != -1L) { + calendar.id = originalCalendarId } - return insertOrUpdateEventTypeSync(eventType) + return insertOrUpdateCalendarSync(calendar) } - fun getLocalBirthdaysEventTypeId(createIfNotExists: Boolean = true): Long { - var eventTypeId = getLocalEventTypeIdWithClass(BIRTHDAY_EVENT) - if (eventTypeId == -1L && createIfNotExists) { + fun getLocalBirthdaysCalendarId(createIfNotExists: Boolean = true): Long { + var calendarId = getLocalCalendarIdWithClass(BIRTHDAY_EVENT) + if (calendarId == -1L && createIfNotExists) { val birthdays = context.getString(R.string.birthdays) - eventTypeId = createPredefinedEventType(birthdays, R.color.default_birthdays_color, BIRTHDAY_EVENT) + calendarId = + createPredefinedCalendar(birthdays, R.color.default_birthdays_color, BIRTHDAY_EVENT) } - return eventTypeId + return calendarId } - fun getAnniversariesEventTypeId(createIfNotExists: Boolean = true): Long { - var eventTypeId = getLocalEventTypeIdWithClass(ANNIVERSARY_EVENT) - if (eventTypeId == -1L && createIfNotExists) { + fun getAnniversariesCalendarId(createIfNotExists: Boolean = true): Long { + var calendarId = getLocalCalendarIdWithClass(ANNIVERSARY_EVENT) + if (calendarId == -1L && createIfNotExists) { val anniversaries = context.getString(R.string.anniversaries) - eventTypeId = createPredefinedEventType(anniversaries, R.color.default_anniversaries_color, ANNIVERSARY_EVENT) + calendarId = createPredefinedCalendar( + anniversaries, + R.color.default_anniversaries_color, + ANNIVERSARY_EVENT + ) } - return eventTypeId + return calendarId } - fun getRepeatableEventsFor(fromTS: Long, toTS: Long, eventId: Long = -1L, applyTypeFilter: Boolean = false, searchQuery: String = ""): List { + fun getRepeatableEventsFor( + fromTS: Long, + toTS: Long, + eventId: Long = -1L, + applyTypeFilter: Boolean = false, + searchQuery: String = "" + ): List { val events = if (applyTypeFilter) { - val displayEventTypes = context.config.displayEventTypes - if (displayEventTypes.isEmpty()) { + val displayCalendars = context.config.displayCalendars + if (displayCalendars.isEmpty()) { return ArrayList() } else if (searchQuery.isEmpty()) { - eventsDB.getRepeatableEventsOrTasksWithTypes(toTS, context.config.getDisplayEventTypessAsList()).toMutableList() as ArrayList + eventsDB.getRepeatableEventsOrTasksWithCalendarIds( + toTS, + context.config.getDisplayCalendarsAsList() + ).toMutableList() as ArrayList } else { - eventsDB.getRepeatableEventsOrTasksWithTypesForSearch(toTS, context.config.getDisplayEventTypessAsList(), "%$searchQuery%") + eventsDB.getRepeatableEventsOrTasksWithTypesForSearch( + toTS, + context.config.getDisplayCalendarsAsList(), + "%$searchQuery%" + ) .toMutableList() as ArrayList } } else { if (eventId == -1L) { - eventsDB.getRepeatableEventsOrTasksWithTypes(toTS).toMutableList() as ArrayList + eventsDB.getRepeatableEventsOrTasksWithCalendarIds(toTS) + .toMutableList() as ArrayList } else { - eventsDB.getRepeatableEventsOrTasksWithId(eventId, toTS).toMutableList() as ArrayList + eventsDB.getRepeatableEventsOrTasksWithId(eventId, toTS) + .toMutableList() as ArrayList } } @@ -534,7 +642,12 @@ class EventsHelper(val context: Context) { return newEvents } - private fun getEventsRepeatingXTimes(fromTS: Long, toTS: Long, startTimes: LongSparseArray, event: Event): ArrayList { + private fun getEventsRepeatingXTimes( + fromTS: Long, + toTS: Long, + startTimes: LongSparseArray, + event: Event + ): ArrayList { val original = event.copy() val events = ArrayList() while (event.repeatLimit < 0 && event.startTS <= toTS) { @@ -576,7 +689,12 @@ class EventsHelper(val context: Context) { return events } - private fun getEventsRepeatingTillDateOrForever(fromTS: Long, toTS: Long, startTimes: LongSparseArray, event: Event): ArrayList { + private fun getEventsRepeatingTillDateOrForever( + fromTS: Long, + toTS: Long, + startTimes: LongSparseArray, + event: Event + ): ArrayList { val original = event.copy() val events = ArrayList() while (event.startTS <= toTS && (event.repeatLimit == 0L || event.repeatLimit >= event.startTS)) { @@ -635,7 +753,8 @@ class EventsHelper(val context: Context) { fun getRunningEventsOrTasks(): List { val ts = getNowSeconds() - val events = eventsDB.getOneTimeEventsOrTasksFromTo(ts, ts).toMutableList() as ArrayList + val events = + eventsDB.getOneTimeEventsOrTasksFromTo(ts, ts).toMutableList() as ArrayList events.addAll(getRepeatableEventsFor(ts, ts)) events.forEach { if (it.isTask()) updateIsTaskCompleted(it) @@ -643,23 +762,28 @@ class EventsHelper(val context: Context) { return events } - fun getEventsToExport(eventTypes: List, exportEvents: Boolean, exportTasks: Boolean, exportPastEntries: Boolean): MutableList { + fun getEventsToExport( + calendars: List, + exportEvents: Boolean, + exportTasks: Boolean, + exportPastEntries: Boolean + ): MutableList { val currTS = getNowSeconds() var events = mutableListOf() val tasks = mutableListOf() if (exportPastEntries) { if (exportEvents) { - events.addAll(eventsDB.getAllEventsWithTypes(eventTypes)) + events.addAll(eventsDB.getAllEventsWithCalendarIds(calendars)) } if (exportTasks) { - tasks.addAll(eventsDB.getAllTasksWithTypes(eventTypes)) + tasks.addAll(eventsDB.getAllTasksWithCalendarIds(calendars)) } } else { if (exportEvents) { - events.addAll(eventsDB.getAllFutureEventsWithTypes(currTS, eventTypes)) + events.addAll(eventsDB.getAllFutureEventsWithCalendarIds(currTS, calendars)) } if (exportTasks) { - tasks.addAll(eventsDB.getAllFutureTasksWithTypes(currTS, eventTypes)) + tasks.addAll(eventsDB.getAllFutureTasksWithCalendarIds(currTS, calendars)) } } @@ -672,12 +796,12 @@ class EventsHelper(val context: Context) { return events } - fun getEventTypeColors(): LongSparseArray { - val eventTypeColors = LongSparseArray() - context.eventTypesDB.getEventTypes().forEach { - eventTypeColors.put(it.id!!, it.color) + fun getCalendarColors(): LongSparseArray { + val calendarColors = LongSparseArray() + context.calendarsDB.getCalendars().forEach { + calendarColors.put(it.id!!, it.color) } - return eventTypeColors + return calendarColors } } diff --git a/app/src/main/kotlin/org/fossify/calendar/helpers/IcsExporter.kt b/app/src/main/kotlin/org/fossify/calendar/helpers/IcsExporter.kt index 1e58db4a3..3a71f2c8f 100644 --- a/app/src/main/kotlin/org/fossify/calendar/helpers/IcsExporter.kt +++ b/app/src/main/kotlin/org/fossify/calendar/helpers/IcsExporter.kt @@ -4,7 +4,7 @@ import android.content.Context import android.provider.CalendarContract.Events import org.fossify.calendar.R import org.fossify.calendar.extensions.calDAVHelper -import org.fossify.calendar.extensions.eventTypesDB +import org.fossify.calendar.extensions.calendarsDB import org.fossify.calendar.extensions.eventsHelper import org.fossify.calendar.helpers.IcsExporter.ExportResult.EXPORT_FAIL import org.fossify.calendar.helpers.IcsExporter.ExportResult.EXPORT_OK @@ -94,7 +94,8 @@ class IcsExporter(private val context: Context) { writeLn("$ACTION$DISPLAY") } else { writeLn("$ACTION$EMAIL") - val attendee = calendars.firstOrNull { it.id == event.getCalDAVCalendarId() }?.accountName + val attendee = + calendars.firstOrNull { it.id == event.getCalDAVCalendarId() }?.accountName if (attendee != null) { writeLn("$ATTENDEE$MAILTO$attendee") } @@ -141,20 +142,20 @@ class IcsExporter(private val context: Context) { } private fun writeEvent(writer: BufferedWriter, event: Event) { - val eventTypeColors = context.eventsHelper.getEventTypeColors() + val calendarColors = context.eventsHelper.getCalendarColors() with(writer) { writeLn(BEGIN_EVENT) event.title.replace("\n", "\\n").let { if (it.isNotEmpty()) writeLn("$SUMMARY:$it") } event.importId.let { if (it.isNotEmpty()) writeLn("$UID$it") } - writeLn("$CATEGORY_COLOR${context.eventTypesDB.getEventTypeWithId(event.eventType)?.color}") - if (event.color != 0 && event.color != eventTypeColors[event.eventType]) { + writeLn("$CATEGORY_COLOR${context.calendarsDB.getCalendarWithId(event.calendarId)?.color}") + if (event.color != 0 && event.color != calendarColors[event.calendarId]) { val color = CssColors.findClosestCssColor(event.color) if (color != null) { writeLn("$COLOR${color}") } writeLn("$FOSSIFY_COLOR${event.color}") } - writeLn("$CATEGORIES${context.eventTypesDB.getEventTypeWithId(event.eventType)?.title}") + writeLn("$CATEGORIES${context.calendarsDB.getCalendarWithId(event.calendarId)?.title}") writeLn("$LAST_MODIFIED:${Formatter.getExportedTime(event.lastUpdated)}") writeLn("$TRANSP${if (event.availability == Events.AVAILABILITY_FREE) TRANSPARENT else OPAQUE}") event.location.let { if (it.isNotEmpty()) writeLn("$LOCATION:$it") } @@ -166,7 +167,14 @@ class IcsExporter(private val context: Context) { DateTimeZone.getDefault() } writeLn("$DTSTART;$VALUE=$DATE:${Formatter.getDayCodeFromTS(event.startTS, tz)}") - writeLn("$DTEND;$VALUE=$DATE:${Formatter.getDayCodeFromTS(event.endTS + TWELVE_HOURS, tz)}") + writeLn( + "$DTEND;$VALUE=$DATE:${ + Formatter.getDayCodeFromTS( + event.endTS + TWELVE_HOURS, + tz + ) + }" + ) } else { writeLn("$DTSTART:${Formatter.getExportedTime(event.startTS * 1000L)}") writeLn("$DTEND:${Formatter.getExportedTime(event.endTS * 1000L)}") @@ -188,20 +196,20 @@ class IcsExporter(private val context: Context) { } private fun writeTask(writer: BufferedWriter, task: Event) { - val eventTypeColors = context.eventsHelper.getEventTypeColors() + val calendarColors = context.eventsHelper.getCalendarColors() with(writer) { writeLn(BEGIN_TASK) task.title.replace("\n", "\\n").let { if (it.isNotEmpty()) writeLn("$SUMMARY:$it") } task.importId.let { if (it.isNotEmpty()) writeLn("$UID$it") } - writeLn("$CATEGORY_COLOR${context.eventTypesDB.getEventTypeWithId(task.eventType)?.color}") - if (task.color != 0 && task.color != eventTypeColors[task.eventType]) { + writeLn("$CATEGORY_COLOR${context.calendarsDB.getCalendarWithId(task.calendarId)?.color}") + if (task.color != 0 && task.color != calendarColors[task.calendarId]) { val color = CssColors.findClosestCssColor(task.color) if (color != null) { writeLn("$COLOR${color}") } writeLn("$FOSSIFY_COLOR${task.color}") } - writeLn("$CATEGORIES${context.eventTypesDB.getEventTypeWithId(task.eventType)?.title}") + writeLn("$CATEGORIES${context.calendarsDB.getCalendarWithId(task.calendarId)?.title}") writeLn("$LAST_MODIFIED:${Formatter.getExportedTime(task.lastUpdated)}") task.location.let { if (it.isNotEmpty()) writeLn("$LOCATION:$it") } diff --git a/app/src/main/kotlin/org/fossify/calendar/helpers/IcsImporter.kt b/app/src/main/kotlin/org/fossify/calendar/helpers/IcsImporter.kt index e4a0384ed..714d014e6 100644 --- a/app/src/main/kotlin/org/fossify/calendar/helpers/IcsImporter.kt +++ b/app/src/main/kotlin/org/fossify/calendar/helpers/IcsImporter.kt @@ -9,8 +9,8 @@ import org.fossify.calendar.helpers.IcsImporter.ImportResult.IMPORT_FAIL import org.fossify.calendar.helpers.IcsImporter.ImportResult.IMPORT_NOTHING_NEW import org.fossify.calendar.helpers.IcsImporter.ImportResult.IMPORT_OK import org.fossify.calendar.helpers.IcsImporter.ImportResult.IMPORT_PARTIAL +import org.fossify.calendar.models.CalendarEntity import org.fossify.calendar.models.Event -import org.fossify.calendar.models.EventType import org.fossify.calendar.models.Reminder import org.fossify.commons.extensions.areDigitsOnly import org.fossify.commons.extensions.showErrorToast @@ -43,7 +43,7 @@ class IcsImporter(val activity: SimpleActivity) { private var curRepeatInterval = 0 private var curRepeatLimit = 0L private var curRepeatRule = 0 - private var curEventTypeId = LOCAL_CALENDAR_ID + private var curCalendarId = LOCAL_CALENDAR_ID private var curLastModified = 0L private var curCategoryColor = -2 private var curAvailability = Events.AVAILABILITY_BUSY @@ -66,15 +66,16 @@ class IcsImporter(val activity: SimpleActivity) { fun importEvents( path: String, - defaultEventTypeId: Long, + defaultCalendarId: Long, calDAVCalendarId: Int, - overrideFileEventTypes: Boolean, + overrideFileCalendars: Boolean, eventReminders: ArrayList? = null, loadFromAssets: Boolean = false, ): ImportResult { try { - val eventTypes = eventsHelper.getEventTypesSync() - val existingEvents = activity.eventsDB.getEventsOrTasksWithImportIds().toMutableList() as ArrayList + val calendars = eventsHelper.getCalendarsSync() + val existingEvents = activity.eventsDB.getEventsOrTasksWithImportIds() + .toMutableList() as ArrayList val eventsToInsert = ArrayList() var line = "" @@ -98,11 +99,11 @@ class IcsImporter(val activity: SimpleActivity) { if (line.trim() == BEGIN_EVENT) { resetValues() - curEventTypeId = defaultEventTypeId + curCalendarId = defaultCalendarId isParsingEvent = true } else if (line.trim() == BEGIN_TASK) { resetValues() - curEventTypeId = defaultEventTypeId + curCalendarId = defaultCalendarId isParsingTask = true curType = TYPE_TASK } else if (line.startsWith(DUE)) { @@ -155,7 +156,8 @@ class IcsImporter(val activity: SimpleActivity) { val action = line.substring(ACTION.length).trim() isProperReminderAction = action == DISPLAY || action == EMAIL if (isProperReminderAction) { - curReminderTriggerAction = if (action == DISPLAY) REMINDER_NOTIFICATION else REMINDER_EMAIL + curReminderTriggerAction = + if (action == DISPLAY) REMINDER_NOTIFICATION else REMINDER_EMAIL } } else if (line.startsWith(TRIGGER)) { val value = line.substringAfterLast(":") @@ -197,9 +199,9 @@ class IcsImporter(val activity: SimpleActivity) { if (line.substring(SMT_MISSING_YEAR.length) == "1") { curFlags = curFlags or FLAG_MISSING_YEAR } - } else if (line.startsWith(CLASS)){ + } else if (line.startsWith(CLASS)) { val value = line.substringAfterLast(":") - curAccessLevel = when (value){ + curAccessLevel = when (value) { PRIVATE -> Events.ACCESS_PRIVATE CONFIDENTIAL -> Events.ACCESS_CONFIDENTIAL else -> Events.ACCESS_PUBLIC @@ -218,7 +220,7 @@ class IcsImporter(val activity: SimpleActivity) { if (isParsingTask && line.substring(COMPLETED.length).trim().isNotEmpty()) { curFlags = curFlags or FLAG_TASK_COMPLETED } - } else if (line.startsWith(CATEGORIES) && !overrideFileEventTypes) { + } else if (line.startsWith(CATEGORIES) && !overrideFileCalendars) { val categories = line.substring(CATEGORIES.length) tryAddCategories(categories) } else if (line.startsWith(LAST_MODIFIED)) { @@ -231,13 +233,20 @@ class IcsImporter(val activity: SimpleActivity) { if (value.contains(",")) { value.split(",").forEach { exdate -> - curRepeatExceptions.add(Formatter.getDayCodeFromTS(getTimestamp(exdate))) + curRepeatExceptions.add( + Formatter.getDayCodeFromTS( + getTimestamp( + exdate + ) + ) + ) } } else { curRepeatExceptions.add(Formatter.getDayCodeFromTS(getTimestamp(value))) } } else if (line.startsWith(LOCATION)) { - curLocation = getLocation(line.substring(LOCATION.length).replace("\\,", ",")) + curLocation = + getLocation(line.substring(LOCATION.length).replace("\\,", ",")) if (curLocation.trim().isEmpty()) { curLocation = "" } @@ -247,7 +256,10 @@ class IcsImporter(val activity: SimpleActivity) { } else if (line.startsWith(SEQUENCE)) { isSequence = true } else if (line.startsWith(TRANSP)) { - line.substring(TRANSP.length).let { curAvailability = if (it == TRANSPARENT) Events.AVAILABILITY_FREE else Events.AVAILABILITY_BUSY } + line.substring(TRANSP.length).let { + curAvailability = + if (it == TRANSPARENT) Events.AVAILABILITY_FREE else Events.AVAILABILITY_BUSY + } } else if (line.trim() == BEGIN_ALARM) { isNotificationDescription = true } else if (line.trim() == END_ALARM) { @@ -269,23 +281,39 @@ class IcsImporter(val activity: SimpleActivity) { } // repeating event exceptions can have the same import id as their parents, so pick the latest event to update - val eventToUpdate = existingEvents.filter { curImportId.isNotEmpty() && curImportId == it.importId }.maxByOrNull { it.lastUpdated } + val eventToUpdate = + existingEvents.filter { curImportId.isNotEmpty() && curImportId == it.importId } + .maxByOrNull { it.lastUpdated } if (eventToUpdate != null && eventToUpdate.lastUpdated >= curLastModified) { eventsAlreadyExist++ line = curLine continue } - var reminders = eventReminders?.map { reminderMinutes -> Reminder(reminderMinutes, REMINDER_NOTIFICATION) } ?: arrayListOf( - Reminder(curReminderMinutes.getOrElse(0) { REMINDER_OFF }, curReminderActions.getOrElse(0) { REMINDER_NOTIFICATION }), - Reminder(curReminderMinutes.getOrElse(1) { REMINDER_OFF }, curReminderActions.getOrElse(1) { REMINDER_NOTIFICATION }), - Reminder(curReminderMinutes.getOrElse(2) { REMINDER_OFF }, curReminderActions.getOrElse(2) { REMINDER_NOTIFICATION }) + var reminders = eventReminders?.map { reminderMinutes -> + Reminder( + reminderMinutes, + REMINDER_NOTIFICATION + ) + } ?: arrayListOf( + Reminder( + curReminderMinutes.getOrElse(0) { REMINDER_OFF }, + curReminderActions.getOrElse(0) { REMINDER_NOTIFICATION }), + Reminder( + curReminderMinutes.getOrElse(1) { REMINDER_OFF }, + curReminderActions.getOrElse(1) { REMINDER_NOTIFICATION }), + Reminder( + curReminderMinutes.getOrElse(2) { REMINDER_OFF }, + curReminderActions.getOrElse(2) { REMINDER_NOTIFICATION }) ) - reminders = reminders.sortedBy { it.minutes }.sortedBy { it.minutes == REMINDER_OFF }.toMutableList() as ArrayList + reminders = reminders.sortedBy { it.minutes } + .sortedBy { it.minutes == REMINDER_OFF } + .toMutableList() as ArrayList - val eventType = eventTypes.firstOrNull { it.id == curEventTypeId } - val source = if (calDAVCalendarId == 0 || eventType?.isSyncedEventType() == false) SOURCE_IMPORTED_ICS else "$CALDAV-$calDAVCalendarId" + val calendar = calendars.firstOrNull { it.id == curCalendarId } + val source = + if (calDAVCalendarId == 0 || calendar?.isSyncedCalendar() == false) SOURCE_IMPORTED_ICS else "$CALDAV-$calDAVCalendarId" val isAllDay = curFlags and FLAG_ALL_DAY != 0 val event = Event( null, @@ -308,7 +336,7 @@ class IcsImporter(val activity: SimpleActivity) { curImportId, DateTimeZone.getDefault().id, curFlags, - curEventTypeId, + curCalendarId, 0, curLastModified, source, @@ -342,13 +370,25 @@ class IcsImporter(val activity: SimpleActivity) { // if an event belongs to a sequence insert it immediately, to avoid some glitches with linked events if (isSequence) { if (curRecurrenceDayCode.isEmpty()) { - eventsHelper.insertEvent(event, addToCalDAV = !event.isTask(), showToasts = false) + eventsHelper.insertEvent( + event, + addToCalDAV = !event.isTask(), + showToasts = false + ) } else { // if an event contains the RECURRENCE-ID field, it is an exception to a recurring event, so update its parent too - val parentEvent = activity.eventsDB.getEventWithImportId(event.importId) - if (parentEvent != null && !parentEvent.repetitionExceptions.contains(curRecurrenceDayCode)) { + val parentEvent = + activity.eventsDB.getEventWithImportId(event.importId) + if (parentEvent != null && !parentEvent.repetitionExceptions.contains( + curRecurrenceDayCode + ) + ) { parentEvent.addRepetitionException(curRecurrenceDayCode) - eventsHelper.insertEvent(parentEvent, !parentEvent.isTask(), showToasts = false) + eventsHelper.insertEvent( + parentEvent, + !parentEvent.isTask(), + showToasts = false + ) event.parentId = parentEvent.id!! eventsToInsert.add(event) @@ -359,7 +399,11 @@ class IcsImporter(val activity: SimpleActivity) { } } else { event.id = eventToUpdate.id - eventsHelper.updateEvent(event, updateAtCalDAV = !event.isTask(), showToasts = false) + eventsHelper.updateEvent( + event, + updateAtCalDAV = !event.isTask(), + showToasts = false + ) } eventsImported++ resetValues() @@ -408,13 +452,15 @@ class IcsImporter(val activity: SimpleActivity) { // Ideally, we should parse BEGIN:VTIMEZONE and derive the timezone from there, but to get things working, let's assume TZID refers to one // of the known timezones if (fullString.contains(':')) { - val timeZoneId = fullString.substringAfter("%s=".format(TZID)).substringBefore(':') + val timeZoneId = + fullString.substringAfter("%s=".format(TZID)).substringBefore(':') if (DateTimeZone.getAvailableIDs().contains(timeZoneId)) { timeZone = DateTimeZone.forID(timeZoneId) } } - val value = fullString.substring(fullString.lastIndexOf(':') + 1).replace(" ", "") + val value = + fullString.substring(fullString.lastIndexOf(':') + 1).replace(" ", "") if (value.isEmpty()) { return 0 } else if (!value.contains("T")) { @@ -424,7 +470,9 @@ class IcsImporter(val activity: SimpleActivity) { Parser().parseDateTimeValue(value, timeZone) } - fullString.startsWith(":") -> Parser().parseDateTimeValue(fullString.substring(1).trim(), timeZone) + fullString.startsWith(":") -> Parser().parseDateTimeValue( + fullString.substring(1).trim(), timeZone + ) else -> Parser().parseDateTimeValue(fullString) } @@ -444,24 +492,24 @@ class IcsImporter(val activity: SimpleActivity) { } private fun tryAddCategories(categories: String) { - val eventTypeTitle = if (categories.contains(",")) { + val calendarTitle = if (categories.contains(",")) { categories.split(",")[0] } else { categories } - val eventId = eventsHelper.getEventTypeIdWithTitle(eventTypeTitle) - curEventTypeId = if (eventId == -1L) { + val calendarId = eventsHelper.getCalendarIdWithTitle(calendarTitle) + curCalendarId = if (calendarId == -1L) { val newTypeColor = if (curCategoryColor == -2) { activity.resources.getColor(org.fossify.commons.R.color.color_primary) } else { curCategoryColor } - val eventType = EventType(null, eventTypeTitle, newTypeColor) - eventsHelper.insertOrUpdateEventTypeSync(eventType) + val calendar = CalendarEntity(null, calendarTitle, newTypeColor) + eventsHelper.insertOrUpdateCalendarSync(calendar) } else { - eventId + calendarId } } @@ -496,7 +544,7 @@ class IcsImporter(val activity: SimpleActivity) { curRepeatInterval = 0 curRepeatLimit = 0L curRepeatRule = 0 - curEventTypeId = LOCAL_CALENDAR_ID + curCalendarId = LOCAL_CALENDAR_ID curLastModified = 0L curCategoryColor = -2 isNotificationDescription = false diff --git a/app/src/main/kotlin/org/fossify/calendar/interfaces/CalendarsDao.kt b/app/src/main/kotlin/org/fossify/calendar/interfaces/CalendarsDao.kt new file mode 100644 index 000000000..09f455600 --- /dev/null +++ b/app/src/main/kotlin/org/fossify/calendar/interfaces/CalendarsDao.kt @@ -0,0 +1,41 @@ +package org.fossify.calendar.interfaces + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import org.fossify.calendar.models.CalendarEntity + +@Dao +interface CalendarsDao { + @Query("SELECT * FROM event_types ORDER BY title ASC") + fun getCalendars(): List + + @Query("SELECT * FROM event_types WHERE id = :id") + fun getCalendarWithId(id: Long): CalendarEntity? + + @Query("SELECT id FROM event_types WHERE title = :title COLLATE NOCASE") + fun getCalendarIdWithTitle(title: String): Long? + + @Query("SELECT id FROM event_types WHERE title = :title AND caldav_calendar_id = 0 COLLATE NOCASE") + fun getLocalCalendarIdWithTitle(title: String): Long? + + @Query("SELECT id FROM event_types WHERE type = :classId") + fun getCalendarIdWithClass(classId: Int): Long? + + @Query("SELECT id FROM event_types WHERE type = :classId AND caldav_calendar_id = 0") + fun getLocalCalendarIdWithClass(classId: Int): Long? + + @Query("SELECT * FROM event_types WHERE caldav_calendar_id = :calendarId") + fun getCalendarWithCalDAVCalendarId(calendarId: Int): CalendarEntity? + + @Query("DELETE FROM event_types WHERE caldav_calendar_id IN (:ids)") + fun deleteCalendarsWithCalendarIds(ids: List) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insertOrUpdate(calendar: CalendarEntity): Long + + @Delete + fun deleteCalendars(calendars: List) +} diff --git a/app/src/main/kotlin/org/fossify/calendar/interfaces/DeleteCalendarsListener.kt b/app/src/main/kotlin/org/fossify/calendar/interfaces/DeleteCalendarsListener.kt new file mode 100644 index 000000000..8567f8581 --- /dev/null +++ b/app/src/main/kotlin/org/fossify/calendar/interfaces/DeleteCalendarsListener.kt @@ -0,0 +1,7 @@ +package org.fossify.calendar.interfaces + +import org.fossify.calendar.models.CalendarEntity + +interface DeleteCalendarsListener { + fun deleteCalendars(calendars: ArrayList, deleteEvents: Boolean): Boolean +} diff --git a/app/src/main/kotlin/org/fossify/calendar/interfaces/DeleteEventTypesListener.kt b/app/src/main/kotlin/org/fossify/calendar/interfaces/DeleteEventTypesListener.kt deleted file mode 100644 index 5e9101d98..000000000 --- a/app/src/main/kotlin/org/fossify/calendar/interfaces/DeleteEventTypesListener.kt +++ /dev/null @@ -1,7 +0,0 @@ -package org.fossify.calendar.interfaces - -import org.fossify.calendar.models.EventType - -interface DeleteEventTypesListener { - fun deleteEventTypes(eventTypes: ArrayList, deleteEvents: Boolean): Boolean -} diff --git a/app/src/main/kotlin/org/fossify/calendar/interfaces/EventTypesDao.kt b/app/src/main/kotlin/org/fossify/calendar/interfaces/EventTypesDao.kt deleted file mode 100644 index ca40a6efc..000000000 --- a/app/src/main/kotlin/org/fossify/calendar/interfaces/EventTypesDao.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.fossify.calendar.interfaces - -import androidx.room.* -import org.fossify.calendar.models.EventType - -@Dao -interface EventTypesDao { - @Query("SELECT * FROM event_types ORDER BY title ASC") - fun getEventTypes(): List - - @Query("SELECT * FROM event_types WHERE id = :id") - fun getEventTypeWithId(id: Long): EventType? - - @Query("SELECT id FROM event_types WHERE title = :title COLLATE NOCASE") - fun getEventTypeIdWithTitle(title: String): Long? - - @Query("SELECT id FROM event_types WHERE title = :title AND caldav_calendar_id = 0 COLLATE NOCASE") - fun getLocalEventTypeIdWithTitle(title: String): Long? - - @Query("SELECT id FROM event_types WHERE type = :classId") - fun getEventTypeIdWithClass(classId: Int): Long? - - @Query("SELECT id FROM event_types WHERE type = :classId AND caldav_calendar_id = 0") - fun getLocalEventTypeIdWithClass(classId: Int): Long? - - @Query("SELECT * FROM event_types WHERE caldav_calendar_id = :calendarId") - fun getEventTypeWithCalDAVCalendarId(calendarId: Int): EventType? - - @Query("DELETE FROM event_types WHERE caldav_calendar_id IN (:ids)") - fun deleteEventTypesWithCalendarId(ids: List) - - @Insert(onConflict = OnConflictStrategy.REPLACE) - fun insertOrUpdate(eventType: EventType): Long - - @Delete - fun deleteEventTypes(eventTypes: List) -} diff --git a/app/src/main/kotlin/org/fossify/calendar/interfaces/EventsDao.kt b/app/src/main/kotlin/org/fossify/calendar/interfaces/EventsDao.kt index b0aeed489..788a1e7e8 100644 --- a/app/src/main/kotlin/org/fossify/calendar/interfaces/EventsDao.kt +++ b/app/src/main/kotlin/org/fossify/calendar/interfaces/EventsDao.kt @@ -4,7 +4,11 @@ import androidx.room.Dao import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query -import org.fossify.calendar.helpers.* +import org.fossify.calendar.helpers.LOCAL_CALENDAR_ID +import org.fossify.calendar.helpers.SOURCE_CONTACT_ANNIVERSARY +import org.fossify.calendar.helpers.SOURCE_CONTACT_BIRTHDAY +import org.fossify.calendar.helpers.TYPE_EVENT +import org.fossify.calendar.helpers.TYPE_TASK import org.fossify.calendar.models.Event @Dao @@ -15,17 +19,17 @@ interface EventsDao { @Query("SELECT * FROM events WHERE type = $TYPE_TASK") fun getAllTasks(): List - @Query("SELECT * FROM events WHERE event_type IN (:eventTypeIds) AND type = $TYPE_EVENT") - fun getAllEventsWithTypes(eventTypeIds: List): List + @Query("SELECT * FROM events WHERE event_type IN (:calendarIds) AND type = $TYPE_EVENT") + fun getAllEventsWithCalendarIds(calendarIds: List): List - @Query("SELECT * FROM events WHERE event_type IN (:eventTypeIds) AND type = $TYPE_TASK") - fun getAllTasksWithTypes(eventTypeIds: List): List + @Query("SELECT * FROM events WHERE event_type IN (:calendarIds) AND type = $TYPE_TASK") + fun getAllTasksWithCalendarIds(calendarIds: List): List - @Query("SELECT * FROM events WHERE end_ts > :currTS AND event_type IN (:eventTypeIds) AND type = $TYPE_EVENT") - fun getAllFutureEventsWithTypes(currTS: Long, eventTypeIds: List): List + @Query("SELECT * FROM events WHERE end_ts > :currTS AND event_type IN (:calendarIds) AND type = $TYPE_EVENT") + fun getAllFutureEventsWithCalendarIds(currTS: Long, calendarIds: List): List - @Query("SELECT * FROM events WHERE end_ts > :currTS AND event_type IN (:eventTypeIds) AND type = $TYPE_TASK") - fun getAllFutureTasksWithTypes(currTS: Long, eventTypeIds: List): List + @Query("SELECT * FROM events WHERE end_ts > :currTS AND event_type IN (:calendarIds) AND type = $TYPE_TASK") + fun getAllFutureTasksWithCalendarIds(currTS: Long, calendarIds: List): List @Query("SELECT * FROM events WHERE id = :id AND type = $TYPE_EVENT") fun getEventWithId(id: Long): Event? @@ -42,29 +46,42 @@ interface EventsDao { @Query("SELECT * FROM events WHERE start_ts <= :toTS AND end_ts >= :fromTS AND repeat_interval = 0") fun getOneTimeEventsOrTasksFromTo(toTS: Long, fromTS: Long): List - @Query("SELECT * FROM events WHERE start_ts <= :toTS AND start_ts >= :fromTS AND event_type IN (:eventTypeIds) AND type = $TYPE_TASK") - fun getTasksFromTo(fromTS: Long, toTS: Long, eventTypeIds: List): List + @Query("SELECT * FROM events WHERE start_ts <= :toTS AND start_ts >= :fromTS AND event_type IN (:calendarIds) AND type = $TYPE_TASK") + fun getTasksFromTo(fromTS: Long, toTS: Long, calendarIds: List): List @Query("SELECT * FROM events WHERE id = :id AND start_ts <= :toTS AND end_ts >= :fromTS AND repeat_interval = 0") fun getOneTimeEventFromToWithId(id: Long, toTS: Long, fromTS: Long): List - @Query("SELECT * FROM events WHERE start_ts <= :toTS AND end_ts >= :fromTS AND start_ts != 0 AND repeat_interval = 0 AND event_type IN (:eventTypeIds)") - fun getOneTimeEventsFromToWithTypes(toTS: Long, fromTS: Long, eventTypeIds: List): List + @Query("SELECT * FROM events WHERE start_ts <= :toTS AND end_ts >= :fromTS AND start_ts != 0 AND repeat_interval = 0 AND event_type IN (:calendarIds)") + fun getOneTimeEventsFromToWithCalendarIds( + toTS: Long, + fromTS: Long, + calendarIds: List + ): List - @Query("SELECT * FROM events WHERE start_ts <= :toTS AND end_ts >= :fromTS AND start_ts != 0 AND repeat_interval = 0 AND event_type IN (:eventTypeIds) AND (title LIKE :searchQuery OR location LIKE :searchQuery OR description LIKE :searchQuery)") - fun getOneTimeEventsFromToWithTypesForSearch(toTS: Long, fromTS: Long, eventTypeIds: List, searchQuery: String): List + @Query("SELECT * FROM events WHERE start_ts <= :toTS AND end_ts >= :fromTS AND start_ts != 0 AND repeat_interval = 0 AND event_type IN (:calendarIds) AND (title LIKE :searchQuery OR location LIKE :searchQuery OR description LIKE :searchQuery)") + fun getOneTimeEventsFromToWithTypesForSearch( + toTS: Long, + fromTS: Long, + calendarIds: List, + searchQuery: String + ): List @Query("SELECT * FROM events WHERE start_ts <= :toTS AND repeat_interval != 0") - fun getRepeatableEventsOrTasksWithTypes(toTS: Long): List + fun getRepeatableEventsOrTasksWithCalendarIds(toTS: Long): List @Query("SELECT * FROM events WHERE id = :id AND start_ts <= :toTS AND repeat_interval != 0") fun getRepeatableEventsOrTasksWithId(id: Long, toTS: Long): List - @Query("SELECT * FROM events WHERE start_ts <= :toTS AND start_ts != 0 AND repeat_interval != 0 AND event_type IN (:eventTypeIds)") - fun getRepeatableEventsOrTasksWithTypes(toTS: Long, eventTypeIds: List): List + @Query("SELECT * FROM events WHERE start_ts <= :toTS AND start_ts != 0 AND repeat_interval != 0 AND event_type IN (:calendarIds)") + fun getRepeatableEventsOrTasksWithCalendarIds(toTS: Long, calendarIds: List): List - @Query("SELECT * FROM events WHERE start_ts <= :toTS AND start_ts != 0 AND repeat_interval != 0 AND event_type IN (:eventTypeIds) AND (title LIKE :searchQuery OR location LIKE :searchQuery OR description LIKE :searchQuery)") - fun getRepeatableEventsOrTasksWithTypesForSearch(toTS: Long, eventTypeIds: List, searchQuery: String): List + @Query("SELECT * FROM events WHERE start_ts <= :toTS AND start_ts != 0 AND repeat_interval != 0 AND event_type IN (:calendarIds) AND (title LIKE :searchQuery OR location LIKE :searchQuery OR description LIKE :searchQuery)") + fun getRepeatableEventsOrTasksWithTypesForSearch( + toTS: Long, + calendarIds: List, + searchQuery: String + ): List @Query("SELECT * FROM events WHERE id IN (:ids) AND import_id != \"\" AND type = $TYPE_EVENT") fun getEventsByIdsWithImportIds(ids: List): List @@ -97,11 +114,11 @@ interface EventsDao { @Query("SELECT id FROM events WHERE import_id LIKE :importId AND type = $TYPE_EVENT") fun getEventIdWithLastImportId(importId: String): Long? - @Query("SELECT id FROM events WHERE event_type = :eventTypeId") - fun getEventAndTasksIdsByEventType(eventTypeId: Long): List + @Query("SELECT id FROM events WHERE event_type = :calendarId") + fun getEventAndTasksIdsByCalendar(calendarId: Long): List - @Query("SELECT id FROM events WHERE event_type IN (:eventTypeIds)") - fun getEventAndTasksIdsByEventType(eventTypeIds: List): List + @Query("SELECT id FROM events WHERE event_type IN (:calendarIds)") + fun getEventAndTasksIdsByCalendar(calendarIds: List): List @Query("SELECT id FROM events WHERE parent_id IN (:parentIds)") fun getEventIdsWithParentIds(parentIds: List): List @@ -109,8 +126,8 @@ interface EventsDao { @Query("SELECT id FROM events WHERE source = :source AND import_id != \"\" AND type = $TYPE_EVENT") fun getCalDAVCalendarEvents(source: String): List - @Query("UPDATE events SET event_type = $LOCAL_CALENDAR_ID WHERE event_type = :eventTypeId") - fun resetEventsAndTasksWithType(eventTypeId: Long) + @Query("UPDATE events SET event_type = $LOCAL_CALENDAR_ID WHERE event_type = :calendarId") + fun resetEventsAndTasksWithCalendarId(calendarId: Long) @Query("UPDATE events SET import_id = :importId, source = :source WHERE id = :id AND type = $TYPE_EVENT") fun updateEventImportIdAndSource(importId: String, source: String, id: Long) diff --git a/app/src/main/kotlin/org/fossify/calendar/models/CalDAVCalendar.kt b/app/src/main/kotlin/org/fossify/calendar/models/CalDAVCalendar.kt index 0841ab775..09b2da96e 100644 --- a/app/src/main/kotlin/org/fossify/calendar/models/CalDAVCalendar.kt +++ b/app/src/main/kotlin/org/fossify/calendar/models/CalDAVCalendar.kt @@ -1,8 +1,13 @@ package org.fossify.calendar.models data class CalDAVCalendar( - val id: Int, val displayName: String, val accountName: String, val accountType: String, val ownerName: String, - var color: Int, val accessLevel: Int + val id: Int, + val displayName: String, + val accountName: String, + val accountType: String, + val ownerName: String, + var color: Int, + val accessLevel: Int ) { fun canWrite() = accessLevel >= 500 diff --git a/app/src/main/kotlin/org/fossify/calendar/models/EventType.kt b/app/src/main/kotlin/org/fossify/calendar/models/CalendarEntity.kt similarity index 79% rename from app/src/main/kotlin/org/fossify/calendar/models/EventType.kt rename to app/src/main/kotlin/org/fossify/calendar/models/CalendarEntity.kt index 96b824ba0..7cb93715b 100644 --- a/app/src/main/kotlin/org/fossify/calendar/models/EventType.kt +++ b/app/src/main/kotlin/org/fossify/calendar/models/CalendarEntity.kt @@ -7,7 +7,7 @@ import androidx.room.PrimaryKey import org.fossify.calendar.helpers.OTHER_EVENT @Entity(tableName = "event_types", indices = [(Index(value = ["id"], unique = true))]) -data class EventType( +data class CalendarEntity( @PrimaryKey(autoGenerate = true) var id: Long?, @ColumnInfo(name = "title") var title: String, @ColumnInfo(name = "color") var color: Int, @@ -16,7 +16,8 @@ data class EventType( @ColumnInfo(name = "caldav_email") var caldavEmail: String = "", @ColumnInfo(name = "type") var type: Int = OTHER_EVENT ) { - fun getDisplayTitle() = if (caldavCalendarId == 0) title else "$caldavDisplayName ($caldavEmail)" + fun getDisplayTitle() = + if (caldavCalendarId == 0) title else "$caldavDisplayName ($caldavEmail)" - fun isSyncedEventType() = caldavCalendarId != 0 + fun isSyncedCalendar() = caldavCalendarId != 0 } diff --git a/app/src/main/kotlin/org/fossify/calendar/models/Event.kt b/app/src/main/kotlin/org/fossify/calendar/models/Event.kt index 80e9469a8..74312ff04 100644 --- a/app/src/main/kotlin/org/fossify/calendar/models/Event.kt +++ b/app/src/main/kotlin/org/fossify/calendar/models/Event.kt @@ -8,7 +8,27 @@ import androidx.room.Entity import androidx.room.Index import androidx.room.PrimaryKey import org.fossify.calendar.extensions.seconds -import org.fossify.calendar.helpers.* +import org.fossify.calendar.helpers.CALDAV +import org.fossify.calendar.helpers.DAY +import org.fossify.calendar.helpers.FLAG_ALL_DAY +import org.fossify.calendar.helpers.FLAG_IS_IN_PAST +import org.fossify.calendar.helpers.FLAG_MISSING_YEAR +import org.fossify.calendar.helpers.FLAG_TASK_COMPLETED +import org.fossify.calendar.helpers.Formatter +import org.fossify.calendar.helpers.LOCAL_CALENDAR_ID +import org.fossify.calendar.helpers.MONTH +import org.fossify.calendar.helpers.REMINDER_NOTIFICATION +import org.fossify.calendar.helpers.REMINDER_OFF +import org.fossify.calendar.helpers.REPEAT_ORDER_WEEKDAY +import org.fossify.calendar.helpers.REPEAT_ORDER_WEEKDAY_USE_LAST +import org.fossify.calendar.helpers.REPEAT_SAME_DAY +import org.fossify.calendar.helpers.SOURCE_SIMPLE_CALENDAR +import org.fossify.calendar.helpers.TYPE_EVENT +import org.fossify.calendar.helpers.TYPE_TASK +import org.fossify.calendar.helpers.WEEK +import org.fossify.calendar.helpers.YEAR +import org.fossify.calendar.helpers.getAllTimeZones +import org.fossify.calendar.helpers.getNowSeconds import org.fossify.commons.extensions.addBitIf import org.joda.time.DateTime import org.joda.time.DateTimeConstants @@ -38,7 +58,7 @@ data class Event( @ColumnInfo(name = "import_id") var importId: String = "", @ColumnInfo(name = "time_zone") var timeZone: String = "", @ColumnInfo(name = "flags") var flags: Int = 0, - @ColumnInfo(name = "event_type") var eventType: Long = LOCAL_CALENDAR_ID, + @ColumnInfo(name = "event_type") var calendarId: Long = LOCAL_CALENDAR_ID, @ColumnInfo(name = "parent_id") var parentId: Long = 0, @ColumnInfo(name = "last_updated") var lastUpdated: Long = 0L, @ColumnInfo(name = "source") var source: String = SOURCE_SIMPLE_CALENDAR, @@ -69,7 +89,8 @@ data class Event( REPEAT_SAME_DAY -> addMonthsWithSameDay(oldStart, original) REPEAT_ORDER_WEEKDAY -> addXthDayInterval(oldStart, original, false) REPEAT_ORDER_WEEKDAY_USE_LAST -> addXthDayInterval(oldStart, original, true) - else -> oldStart.plusMonths(repeatInterval / MONTH).dayOfMonth().withMaximumValue() + else -> oldStart.plusMonths(repeatInterval / MONTH).dayOfMonth() + .withMaximumValue() } repeatInterval % WEEK == 0 -> { @@ -109,7 +130,9 @@ data class Event( return newDateTime } - while (newDateTime.dayOfMonth().maximumValue < Formatter.getDateTimeFromTS(original.startTS).dayOfMonth().maximumValue) { + while (newDateTime.dayOfMonth().maximumValue < Formatter.getDateTimeFromTS(original.startTS) + .dayOfMonth().maximumValue + ) { newDateTime = newDateTime.plusMonths(repeatInterval / MONTH) newDateTime = try { newDateTime.withDayOfMonth(currStart.dayOfMonth) @@ -121,26 +144,34 @@ data class Event( } // handle monthly repetitions like Third Monday - private fun addXthDayInterval(currStart: DateTime, original: Event, forceLastWeekday: Boolean): DateTime { + private fun addXthDayInterval( + currStart: DateTime, + original: Event, + forceLastWeekday: Boolean + ): DateTime { val day = currStart.dayOfWeek var order = (currStart.dayOfMonth - 1) / 7 - var properMonth = currStart.withDayOfMonth(7).plusMonths(repeatInterval / MONTH).withDayOfWeek(day) + var properMonth = + currStart.withDayOfMonth(7).plusMonths(repeatInterval / MONTH).withDayOfWeek(day) var wantedDay: Int // check if it should be for example Fourth Monday, or Last Monday if (forceLastWeekday && (order == 3 || order == 4)) { val originalDateTime = Formatter.getDateTimeFromTS(original.startTS) - val isLastWeekday = originalDateTime.monthOfYear != originalDateTime.plusDays(7).monthOfYear + val isLastWeekday = + originalDateTime.monthOfYear != originalDateTime.plusDays(7).monthOfYear if (isLastWeekday) order = -1 } if (order == -1) { - wantedDay = properMonth.dayOfMonth + ((properMonth.dayOfMonth().maximumValue - properMonth.dayOfMonth) / 7) * 7 + wantedDay = + properMonth.dayOfMonth + ((properMonth.dayOfMonth().maximumValue - properMonth.dayOfMonth) / 7) * 7 } else { wantedDay = properMonth.dayOfMonth + (order - (properMonth.dayOfMonth - 1) / 7) * 7 while (properMonth.dayOfMonth().maximumValue < wantedDay) { - properMonth = properMonth.withDayOfMonth(7).plusMonths(repeatInterval / MONTH).withDayOfWeek(day) + properMonth = properMonth.withDayOfMonth(7).plusMonths(repeatInterval / MONTH) + .withDayOfWeek(day) wantedDay = properMonth.dayOfMonth + (order - (properMonth.dayOfMonth - 1) / 7) * 7 } } @@ -176,7 +207,9 @@ data class Event( } } - fun getCalDAVCalendarId() = if (source.startsWith(CALDAV)) (source.split("-").lastOrNull() ?: "0").toString().toInt() else 0 + fun getCalDAVCalendarId() = + if (source.startsWith(CALDAV)) (source.split("-").lastOrNull() ?: "0").toString() + .toInt() else 0 // check if it's the proper week, for events repeating every x weeks fun isOnProperWeek(startTimes: LongSparseArray): Boolean { @@ -209,7 +242,8 @@ data class Event( fun addRepetitionException(dayCode: String) { var newRepetitionExceptions = repetitionExceptions.toMutableList() newRepetitionExceptions.add(dayCode) - newRepetitionExceptions = newRepetitionExceptions.distinct().toMutableList() as ArrayList + newRepetitionExceptions = + newRepetitionExceptions.distinct().toMutableList() as ArrayList repetitionExceptions = newRepetitionExceptions } @@ -220,7 +254,8 @@ data class Event( } fun getTimeZoneString(): String { - return if (timeZone.isNotEmpty() && getAllTimeZones().map { it.zoneName }.contains(timeZone)) { + return if (timeZone.isNotEmpty() && getAllTimeZones().map { it.zoneName } + .contains(timeZone)) { timeZone } else { DateTimeZone.getDefault().id diff --git a/app/src/main/res/layout/activity_event.xml b/app/src/main/res/layout/activity_event.xml index a98135f5e..a3004435a 100644 --- a/app/src/main/res/layout/activity_event.xml +++ b/app/src/main/res/layout/activity_event.xml @@ -640,28 +640,28 @@ android:visibility="gone" /> @@ -684,7 +684,7 @@ android:id="@+id/event_color_image" android:layout_width="@dimen/smaller_icon_size" android:layout_height="@dimen/smaller_icon_size" - android:layout_below="@+id/event_type_divider" + android:layout_below="@+id/calendar_divider" android:layout_alignTop="@+id/event_color_holder" android:layout_alignBottom="@+id/event_color_holder" android:layout_marginStart="@dimen/normal_margin" @@ -695,7 +695,7 @@ android:id="@+id/event_color_holder" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_below="@+id/event_type_divider" + android:layout_below="@+id/calendar_divider" android:layout_marginTop="@dimen/medium_margin" android:layout_marginBottom="@dimen/medium_margin" android:layout_toEndOf="@+id/event_color_image" diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index df44e0856..eac99df0e 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -27,7 +27,7 @@ android:id="@+id/swipe_refresh_layout" android:layout_width="match_parent" android:layout_height="0dp" - app:layout_constraintBottom_toTopOf="@+id/quick_event_type_filter" + app:layout_constraintBottom_toTopOf="@+id/quick_calendar_filter" app:layout_constraintTop_toTopOf="parent"> + android:layout_height="wrap_content" /> @@ -146,7 +146,7 @@ @@ -493,7 +493,7 @@ @@ -506,7 +506,7 @@ android:text="@string/default_event_type" /> @@ -27,15 +27,15 @@ + app:layout_constraintTop_toTopOf="@+id/import_calendar_hint" /> + app:layout_constraintTop_toBottomOf="@+id/import_calendar_hint"> diff --git a/app/src/main/res/menu/cab_event_type.xml b/app/src/main/res/menu/cab_calendar.xml similarity index 100% rename from app/src/main/res/menu/cab_event_type.xml rename to app/src/main/res/menu/cab_calendar.xml diff --git a/app/src/main/res/menu/menu_event_types.xml b/app/src/main/res/menu/menu_calendars.xml similarity index 88% rename from app/src/main/res/menu/menu_event_types.xml rename to app/src/main/res/menu/menu_calendars.xml index a982e40f6..2b98e2425 100644 --- a/app/src/main/res/menu/menu_event_types.xml +++ b/app/src/main/res/menu/menu_calendars.xml @@ -2,7 +2,7 @@