refactor: rename "EventType" symbols to "Calendar" (#942)

Zero behavioral change.
This commit is contained in:
Naveen Singh
2025-12-15 16:29:31 +05:30
committed by GitHub
parent 8e97b2cc5b
commit db84d77ebb
60 changed files with 3402 additions and 2223 deletions

View File

@@ -7,34 +7,34 @@
<ID>ComplexCondition:EventListWidgetAdapter.kt$EventListWidgetAdapter$item.isTask &amp;&amp; item.isTaskCompleted &amp;&amp; dimCompletedTasks || dimPastEvents &amp;&amp; item.isPastEvent &amp;&amp; !item.isTask</ID>
<ID>ComplexCondition:EventsHelper.kt$EventsHelper$addToCalDAV &amp;&amp; config.caldavSync &amp;&amp; event.source != SOURCE_SIMPLE_CALENDAR &amp;&amp; event.source != SOURCE_IMPORTED_ICS</ID>
<ID>ComplexCondition:EventsHelper.kt$EventsHelper$addToCalDAV &amp;&amp; event.source != SOURCE_SIMPLE_CALENDAR &amp;&amp; event.source != SOURCE_IMPORTED_ICS &amp;&amp; config.caldavSync</ID>
<ID>ComplexCondition:EventsHelper.kt$EventsHelper$originalEvent != null &amp;&amp; (birthDayEventId != -1L &amp;&amp; it.eventType == birthDayEventId) or (anniversaryEventId != -1L &amp;&amp; it.eventType == anniversaryEventId)</ID>
<ID>ComplexCondition:EventsHelper.kt$EventsHelper$originalEvent != null &amp;&amp; (birthDayEventId != -1L &amp;&amp; it.calendarId == birthDayEventId) or (anniversaryEventId != -1L &amp;&amp; it.calendarId == anniversaryEventId)</ID>
<ID>ComplexCondition:MainActivity.kt$MainActivity$mStoredFirstDayOfWeek != config.firstDayOfWeek || mStoredUse24HourFormat != config.use24HourFormat || mStoredMidnightSpan != config.showMidnightSpanningEventsAtTop || mStoredStartWeekWithCurrentDay != config.startWeekWithCurrentDay</ID>
<ID>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</ID>
<ID>ComplexCondition:MonthView.kt$MonthView$isMonthDayView &amp;&amp; !isDaySelected &amp;&amp; !day.isToday &amp;&amp; day.dayEvents.isNotEmpty()</ID>
<ID>ComplexCondition:SettingsActivity.kt$SettingsActivity$requestCode == PICK_EVENTS_EXPORT_FILE_INTENT &amp;&amp; resultCode == Activity.RESULT_OK &amp;&amp; resultData != null &amp;&amp; resultData.data != null</ID>
<ID>ComplexCondition:SettingsActivity.kt$SettingsActivity$requestCode == PICK_EVENTS_IMPORT_SOURCE_INTENT &amp;&amp; resultCode == Activity.RESULT_OK &amp;&amp; resultData != null &amp;&amp; resultData.data != null</ID>
<ID>ComplexCondition:SettingsActivity.kt$SettingsActivity$requestCode == PICK_SETTINGS_IMPORT_SOURCE_INTENT &amp;&amp; resultCode == Activity.RESULT_OK &amp;&amp; resultData != null &amp;&amp; resultData.data != null</ID>
<ID>ComplexCondition:SettingsActivity.kt$SettingsActivity$requestCode == PICK_EVENTS_EXPORT_FILE_INTENT &amp;&amp; resultCode == RESULT_OK &amp;&amp; resultData != null &amp;&amp; resultData.data != null</ID>
<ID>ComplexCondition:SettingsActivity.kt$SettingsActivity$requestCode == PICK_EVENTS_IMPORT_SOURCE_INTENT &amp;&amp; resultCode == RESULT_OK &amp;&amp; resultData != null &amp;&amp; resultData.data != null</ID>
<ID>ComplexCondition:SettingsActivity.kt$SettingsActivity$requestCode == PICK_SETTINGS_IMPORT_SOURCE_INTENT &amp;&amp; resultCode == RESULT_OK &amp;&amp; resultData != null &amp;&amp; resultData.data != null</ID>
<ID>ComplexCondition:TaskActivity.kt$TaskActivity$config.wasAlarmWarningShown || (mReminder1Minutes == REMINDER_OFF &amp;&amp; mReminder2Minutes == REMINDER_OFF &amp;&amp; mReminder3Minutes == REMINDER_OFF)</ID>
<ID>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</ID>
<ID>ComplexCondition:WeekFragment.kt$WeekFragment$doesEventFit &amp;&amp; (!isRepeatingOverlappingEvent || isAllDayEvent || isRowValidForEvent)</ID>
<ID>ConstructorParameterNaming:Task.kt$Task$@ColumnInfo(name = "task_id") var task_id: Long</ID>
<ID>CyclomaticComplexMethod:CalDAVHelper.kt$CalDAVHelper$@SuppressLint("MissingPermission") private fun fetchCalDAVCalendarEvents( calendar: CalDAVCalendar, eventTypeId: Long, showToasts: Boolean, )</ID>
<ID>CyclomaticComplexMethod:Context.kt$@SuppressLint("NewApi") fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content: String, publicVersion: Boolean = false): Notification?</ID>
<ID>CyclomaticComplexMethod:CalDAVHelper.kt$CalDAVHelper$@SuppressLint("MissingPermission") private fun fetchCalDAVCalendarEvents( calendar: CalDAVCalendar, localCalendarId: Long, showToasts: Boolean, )</ID>
<ID>CyclomaticComplexMethod:Context.kt$@SuppressLint("NewApi") fun Context.getNotification( pendingIntent: PendingIntent, event: Event, content: String, publicVersion: Boolean = false ): Notification?</ID>
<ID>CyclomaticComplexMethod:Context.kt$fun Context.notifyEvent(originalEvent: Event)</ID>
<ID>CyclomaticComplexMethod:DayEventsAdapter.kt$DayEventsAdapter$private fun setupView(view: View, event: Event)</ID>
<ID>CyclomaticComplexMethod:EventActivity.kt$EventActivity$private fun getOrderString(repeatRule: Int): String</ID>
<ID>CyclomaticComplexMethod:EventActivity.kt$EventActivity$private fun gotEvent( savedInstanceState: Bundle?, localEventType: EventType?, event: Event?, )</ID>
<ID>CyclomaticComplexMethod:EventActivity.kt$EventActivity$private fun gotEvent( savedInstanceState: Bundle?, localCalendar: CalendarEntity?, event: Event?, )</ID>
<ID>CyclomaticComplexMethod:EventActivity.kt$EventActivity$private fun isEventChanged(): Boolean</ID>
<ID>CyclomaticComplexMethod:EventActivity.kt$EventActivity$private fun saveEvent()</ID>
<ID>CyclomaticComplexMethod:EventListAdapter.kt$EventListAdapter$private fun setupListEvent(view: View, listEvent: ListEvent)</ID>
<ID>CyclomaticComplexMethod:EventListWidgetAdapter.kt$EventListWidgetAdapter$private fun setupListEvent(remoteView: RemoteViews, item: ListEvent)</ID>
<ID>CyclomaticComplexMethod:EventsHelper.kt$EventsHelper$fun getEventsSync( fromTS: Long, toTS: Long, eventId: Long = -1L, applyTypeFilter: Boolean, searchQuery: String = "", callback: (events: ArrayList&lt;Event&gt;) -&gt; Unit )</ID>
<ID>CyclomaticComplexMethod:EventsHelper.kt$EventsHelper$private fun getEventsRepeatingTillDateOrForever(fromTS: Long, toTS: Long, startTimes: LongSparseArray&lt;Long&gt;, event: Event): ArrayList&lt;Event&gt;</ID>
<ID>CyclomaticComplexMethod:EventsHelper.kt$EventsHelper$private fun getEventsRepeatingTillDateOrForever( fromTS: Long, toTS: Long, startTimes: LongSparseArray&lt;Long&gt;, event: Event ): ArrayList&lt;Event&gt;</ID>
<ID>CyclomaticComplexMethod:IcsExporter.kt$IcsExporter$private fun writeEvent(writer: BufferedWriter, event: Event)</ID>
<ID>CyclomaticComplexMethod:IcsExporter.kt$IcsExporter$private fun writeTask(writer: BufferedWriter, task: Event)</ID>
<ID>CyclomaticComplexMethod:IcsImporter.kt$IcsImporter$fun importEvents( path: String, defaultEventTypeId: Long, calDAVCalendarId: Int, overrideFileEventTypes: Boolean, eventReminders: ArrayList&lt;Int&gt;? = null, loadFromAssets: Boolean = false, ): ImportResult</ID>
<ID>CyclomaticComplexMethod:IcsImporter.kt$IcsImporter$fun importEvents( path: String, defaultCalendarId: Long, calDAVCalendarId: Int, overrideFileCalendars: Boolean, eventReminders: ArrayList&lt;Int&gt;? = null, loadFromAssets: Boolean = false, ): ImportResult</ID>
<ID>CyclomaticComplexMethod:MainActivity.kt$MainActivity$override fun onResume()</ID>
<ID>CyclomaticComplexMethod:MainActivity.kt$MainActivity$private fun addContactEvents(birthdays: Boolean, reminders: ArrayList&lt;Int&gt;, initEventsFound: Int, initEventsAdded: Int, callback: (Int) -&gt; Unit)</ID>
<ID>CyclomaticComplexMethod:MainActivity.kt$MainActivity$private fun addContactEvents( birthdays: Boolean, reminders: ArrayList&lt;Int&gt;, initEventsFound: Int, initEventsAdded: Int, callback: (Int) -&gt; Unit )</ID>
<ID>CyclomaticComplexMethod:MainActivity.kt$MainActivity$private fun addPrivateEvents( birthdays: Boolean, contacts: ArrayList&lt;SimpleContact&gt;, reminders: ArrayList&lt;Int&gt;, callback: (eventsFound: Int, eventsAdded: Int) -&gt; Unit )</ID>
<ID>CyclomaticComplexMethod:MainActivity.kt$MainActivity$private fun setupOptionsMenu()</ID>
<ID>CyclomaticComplexMethod:MonthView.kt$MonthView$override fun onDraw(canvas: Canvas)</ID>
@@ -43,7 +43,7 @@
<ID>CyclomaticComplexMethod:SettingsActivity.kt$SettingsActivity$override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?)</ID>
<ID>CyclomaticComplexMethod:SettingsActivity.kt$SettingsActivity$private fun parseFile(inputStream: InputStream?)</ID>
<ID>CyclomaticComplexMethod:TaskActivity.kt$TaskActivity$private fun getOrderString(repeatRule: Int): String</ID>
<ID>CyclomaticComplexMethod:TaskActivity.kt$TaskActivity$private fun gotTask(savedInstanceState: Bundle?, localEventType: EventType?, task: Event?)</ID>
<ID>CyclomaticComplexMethod:TaskActivity.kt$TaskActivity$private fun gotTask(savedInstanceState: Bundle?, localCalendar: CalendarEntity?, task: Event?)</ID>
<ID>CyclomaticComplexMethod:TaskActivity.kt$TaskActivity$private fun saveTask()</ID>
<ID>CyclomaticComplexMethod:WeekFragment.kt$WeekFragment$@SuppressLint("NewApi") private fun addAllDayEvent(event: Event)</ID>
<ID>CyclomaticComplexMethod:WeekFragment.kt$WeekFragment$private fun addEvents(events: ArrayList&lt;Event&gt;)</ID>
@@ -55,7 +55,7 @@
<ID>EmptyFunctionBlock:EventListFragment.kt$EventListFragment${}</ID>
<ID>EmptyFunctionBlock:EventListWidgetAdapter.kt$EventListWidgetAdapter${}</ID>
<ID>EmptyFunctionBlock:EventListWidgetAdapterEmpty.kt$EventListWidgetAdapterEmpty${}</ID>
<ID>EmptyFunctionBlock:ManageEventTypesAdapter.kt$ManageEventTypesAdapter${}</ID>
<ID>EmptyFunctionBlock:ManageCalendarsAdapter.kt$ManageCalendarsAdapter${}</ID>
<ID>EmptyFunctionBlock:MonthDayFragment.kt$MonthDayFragment${}</ID>
<ID>EmptyFunctionBlock:MonthDayFragmentsHolder.kt$MonthDayFragmentsHolder${}</ID>
<ID>EmptyFunctionBlock:MonthDayFragmentsHolder.kt$MonthDayFragmentsHolder.&lt;no name provided&gt;${}</ID>
@@ -69,19 +69,20 @@
<ID>ForbiddenComment:AutoCompleteTextViewAdapter.kt$AutoCompleteTextViewAdapter$// TODO: Dark text color is set for dynamic theme only because light themes are</ID>
<ID>ImplicitDefaultLocale:SettingsActivity.kt$SettingsActivity$String.format("%02d:00", hours)</ID>
<ID>LargeClass:EventActivity.kt$EventActivity : SimpleActivity</ID>
<ID>LargeClass:EventsHelper.kt$EventsHelper</ID>
<ID>LargeClass:MainActivity.kt$MainActivity : SimpleActivityRefreshRecyclerViewListener</ID>
<ID>LargeClass:SettingsActivity.kt$SettingsActivity : SimpleActivity</ID>
<ID>LargeClass:TaskActivity.kt$TaskActivity : SimpleActivity</ID>
<ID>LargeClass:WeekFragment.kt$WeekFragment : FragmentWeeklyCalendar</ID>
<ID>LongMethod:CalDAVHelper.kt$CalDAVHelper$@SuppressLint("MissingPermission") private fun fetchCalDAVCalendarEvents( calendar: CalDAVCalendar, eventTypeId: Long, showToasts: Boolean, )</ID>
<ID>LongMethod:EventActivity.kt$EventActivity$private fun gotEvent( savedInstanceState: Bundle?, localEventType: EventType?, event: Event?, )</ID>
<ID>LongMethod:CalDAVHelper.kt$CalDAVHelper$@SuppressLint("MissingPermission") private fun fetchCalDAVCalendarEvents( calendar: CalDAVCalendar, localCalendarId: Long, showToasts: Boolean, )</ID>
<ID>LongMethod:EventActivity.kt$EventActivity$private fun gotEvent( savedInstanceState: Bundle?, localCalendar: CalendarEntity?, event: Event?, )</ID>
<ID>LongMethod:EventActivity.kt$EventActivity$private fun saveEvent()</ID>
<ID>LongMethod:IcsImporter.kt$IcsImporter$fun importEvents( path: String, defaultEventTypeId: Long, calDAVCalendarId: Int, overrideFileEventTypes: Boolean, eventReminders: ArrayList&lt;Int&gt;? = null, loadFromAssets: Boolean = false, ): ImportResult</ID>
<ID>LongMethod:IcsImporter.kt$IcsImporter$fun importEvents( path: String, defaultCalendarId: Long, calDAVCalendarId: Int, overrideFileCalendars: Boolean, eventReminders: ArrayList&lt;Int&gt;? = null, loadFromAssets: Boolean = false, ): ImportResult</ID>
<ID>LongMethod:MyTimeZones.kt$fun getAllTimeZones()</ID>
<ID>LongMethod:WeekFragment.kt$WeekFragment$private fun addEvents(events: ArrayList&lt;Event&gt;)</ID>
<ID>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) -&gt; Unit )</ID>
<ID>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) -&gt; Unit )</ID>
<ID>LoopWithTooManyJumpStatements:IcsImporter.kt$IcsImporter$while</ID>
<ID>LoopWithTooManyJumpStatements:ManageEventTypesAdapter.kt$ManageEventTypesAdapter$for</ID>
<ID>LoopWithTooManyJumpStatements:ManageCalendarsAdapter.kt$ManageCalendarsAdapter$for</ID>
<ID>LoopWithTooManyJumpStatements:WeekFragment.kt$WeekFragment$do</ID>
<ID>MagicNumber:AutomaticBackupReceiver.kt$AutomaticBackupReceiver$3000</ID>
<ID>MagicNumber:CalDAVCalendar.kt$CalDAVCalendar$500</ID>
@@ -181,16 +182,13 @@
<ID>MagicNumber:Parser.kt$Parser$6</ID>
<ID>MagicNumber:Parser.kt$Parser$60</ID>
<ID>MagicNumber:Parser.kt$Parser$7</ID>
<ID>MagicNumber:QuickFilterEventTypeAdapter.kt$QuickFilterEventTypeAdapter.QuickFilterViewHolder$300</ID>
<ID>MagicNumber:QuickFilterCalendarAdapter.kt$QuickFilterCalendarAdapter.QuickFilterViewHolder$300</ID>
<ID>MagicNumber:RepeatLimitTypePickerDialog.kt$RepeatLimitTypePickerDialog$23</ID>
<ID>MagicNumber:RepeatLimitTypePickerDialog.kt$RepeatLimitTypePickerDialog$59</ID>
<ID>MagicNumber:RepeatRuleWeeklyDialog.kt$RepeatRuleWeeklyDialog$6</ID>
<ID>MagicNumber:RepeatRuleWeeklyDialog.kt$RepeatRuleWeeklyDialog$7</ID>
<ID>MagicNumber:SelectEventTypeDialog.kt$SelectEventTypeDialog$2L</ID>
<ID>MagicNumber:SetRemindersDialog.kt$SetRemindersDialog$60</ID>
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$16</ID>
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$3</ID>
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$4</ID>
<ID>MagicNumber:SettingsActivity.kt$SettingsActivity$60</ID>
<ID>MagicNumber:SimpleActivity.kt$SimpleActivity$3000L</ID>
<ID>MagicNumber:SmallMonthView.kt$SmallMonthView$0.41f</ID>
@@ -255,55 +253,10 @@
<ID>MaxLineLength:CalDAVHelper.kt$CalDAVHelper$// store the event in the local db only if it is an occurrence that has been modified and not deleted</ID>
<ID>MaxLineLength:CheckableColorAdapter.kt$CheckableColorAdapter$class</ID>
<ID>MaxLineLength:CheckableColorAdapter.kt$CheckableColorAdapter.CheckableColorViewHolder$inner</ID>
<ID>MaxLineLength:Config.kt$Config$caldavSyncedCalendarIds.split(",").filter { it.trim().isNotEmpty() }.map { Integer.parseInt(it) }.toMutableList() as ArrayList&lt;Int&gt;</ID>
<ID>MaxLineLength:Config.kt$Config$get() = prefs.getString(ANNIVERSARY_REMINDERS, REMINDER_DEFAULT_VALUE)!!.split(",").map { it.toInt() }.toMutableList() as ArrayList&lt;Int&gt;</ID>
<ID>MaxLineLength:Config.kt$Config$get() = prefs.getString(BIRTHDAY_REMINDERS, REMINDER_DEFAULT_VALUE)!!.split(",").map { it.toInt() }.toMutableList() as ArrayList&lt;Int&gt;</ID>
<ID>MaxLineLength:Config.kt$Config$get() = prefs.getString(REMINDER_SOUND_URI, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION).toString())!!</ID>
<ID>MaxLineLength:Config.kt$Config$set(addAnniversariesAutomatically) = prefs.edit().putBoolean(ADD_ANNIVERSARIES_AUTOMATICALLY, addAnniversariesAutomatically).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(addBirthdaysAutomatically) = prefs.edit().putBoolean(ADD_BIRTHDAYS_AUTOMATICALLY, addBirthdaysAutomatically).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(anniversaryReminders) = prefs.edit().putString(ANNIVERSARY_REMINDERS, anniversaryReminders.joinToString(",")).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(autoBackupEventTypes) = prefs.edit().remove(AUTO_BACKUP_EVENT_TYPES).putStringSet(AUTO_BACKUP_EVENT_TYPES, autoBackupEventTypes).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(displayEventTypes) = prefs.edit().remove(DISPLAY_EVENT_TYPES).putStringSet(DISPLAY_EVENT_TYPES, displayEventTypes).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(lastEventReminderMinutes) = prefs.edit().putInt(LAST_EVENT_REMINDER_MINUTES, lastEventReminderMinutes).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(lastEventReminderMinutes2) = prefs.edit().putInt(LAST_EVENT_REMINDER_MINUTES_2, lastEventReminderMinutes2).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(lastEventReminderMinutes3) = prefs.edit().putInt(LAST_EVENT_REMINDER_MINUTES_3, lastEventReminderMinutes3).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(lastUsedIgnoreEventTypesState) = prefs.edit().putBoolean(LAST_USED_IGNORE_EVENT_TYPES_STATE, lastUsedIgnoreEventTypesState).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(lastUsedLocalEventTypeId) = prefs.edit().putLong(LAST_USED_LOCAL_EVENT_TYPE_ID, lastUsedLocalEventTypeId).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(lastUsedShowListWidgetHeader) = prefs.edit().putBoolean(LAST_USED_SHOW_LIST_WIDGET_HEADER, lastUsedShowListWidgetHeader).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(quickFilterEventTypes) = prefs.edit().remove(QUICK_FILTER_EVENT_TYPES).putStringSet(QUICK_FILTER_EVENT_TYPES, quickFilterEventTypes).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(startWeekWithCurrentDay) = prefs.edit().putBoolean(START_WEEK_WITH_CURRENT_DAY, startWeekWithCurrentDay).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(usePreviousEventReminders) = prefs.edit().putBoolean(USE_PREVIOUS_EVENT_REMINDERS, usePreviousEventReminders).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(wasFilteredOutWarningShown) = prefs.edit().putBoolean(WAS_FILTERED_OUT_WARNING_SHOWN, wasFilteredOutWarningShown).apply()</ID>
<ID>MaxLineLength:Config.kt$Config$set(weeklyViewItemHeightMultiplier) = prefs.edit().putFloat(WEEKLY_VIEW_ITEM_HEIGHT_MULTIPLIER, weeklyViewItemHeightMultiplier).apply()</ID>
<ID>MaxLineLength:Constants.kt$4</ID>
<ID>MaxLineLength:Context.kt$// Assume this is a manual synchronisation when we showToasts to the user (swipe refresh, MainMenu-&gt; refresh caldav calendars, ...)</ID>
<ID>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</ID>
<ID>MaxLineLength:Context.kt$IcsExporter.ExportResult.EXPORT_PARTIAL -&gt; toast(org.fossify.commons.R.string.exporting_some_entries_failed)</ID>
<ID>MaxLineLength:Context.kt$PendingIntent.getActivity(context, event.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)</ID>
<ID>MaxLineLength:Context.kt$PendingIntent.getBroadcast(this, id.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE).cancel()</ID>
<ID>MaxLineLength:Context.kt$PendingIntent.getService(context, event.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)</ID>
<ID>MaxLineLength:Context.kt$addAction(R.drawable.ic_task_vector, getString(R.string.mark_completed), getMarkCompletedPendingIntent(this@getNotification, event))</ID>
<ID>MaxLineLength:Context.kt$alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + syncCheckInterval, syncCheckInterval, pendingIntent)</ID>
<ID>MaxLineLength:Context.kt$arrayOf(currEvent.reminder3Minutes, currEvent.reminder2Minutes, currEvent.reminder1Minutes).filter { it != REMINDER_OFF }.max()</ID>
<ID>MaxLineLength:Context.kt$eventStartTS = if (currEvent.getIsAllDay()) Formatter.getDayStartTS(Formatter.getDayCodeFromTS(currEvent.startTS)) else currEvent.startTS</ID>
<ID>MaxLineLength:Context.kt$fun</ID>
<ID>MaxLineLength:Context.kt$private fun getFormattedEventTime(startTime: String, endTime: String)</ID>
<ID>MaxLineLength:Context.kt$return PendingIntent.getActivity(context, event.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)</ID>
<ID>MaxLineLength:Context.kt$return PendingIntent.getBroadcast(this, AUTOMATIC_BACKUP_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)</ID>
<ID>MaxLineLength:Context.kt$return PendingIntent.getBroadcast(this, event.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)</ID>
<ID>MaxLineLength:Context.kt$return PendingIntent.getService(context, task.id!!.toInt(), intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)</ID>
<ID>MaxLineLength:Context.kt$seconds % MONTH == 0 -&gt; resources.getQuantityString(org.fossify.commons.R.plurals.months, seconds / MONTH, seconds / MONTH)</ID>
<ID>MaxLineLength:Context.kt$seconds % WEEK == 0 -&gt; resources.getQuantityString(org.fossify.commons.R.plurals.weeks, seconds / WEEK, seconds / WEEK)</ID>
<ID>MaxLineLength:Context.kt$seconds % YEAR == 0 -&gt; resources.getQuantityString(org.fossify.commons.R.plurals.years, seconds / YEAR, seconds / YEAR)</ID>
<ID>MaxLineLength:Context.kt$val</ID>
<ID>MaxLineLength:Context.kt$val dayBits = withFirstDayOfWeekToFront(listOf(MONDAY_BIT, TUESDAY_BIT, WEDNESDAY_BIT, THURSDAY_BIT, FRIDAY_BIT, SATURDAY_BIT, SUNDAY_BIT))</ID>
<ID>MaxLineLength:Context.kt$val eventLayoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)</ID>
<ID>MaxLineLength:Context.kt$val events = eventsHelper.getRepeatableEventsFor(currentSeconds - WEEK_SECONDS, currentSeconds + YEAR_SECONDS, event.id!!)</ID>
<ID>MaxLineLength:Context.kt$val msg = String.format(getString(org.fossify.commons.R.string.time_remaining), formatSecondsToTimeString(secondsTillNotification.toInt()))</ID>
<ID>MaxLineLength:Context.kt$val oldChannelId = "simple_calendar_${config.lastReminderChannel}_${config.reminderAudioStream}_${event.eventType}"</ID>
<ID>MaxLineLength:Context.kt$val snoozeClass = if (context.config.useSameSnooze) SnoozeService::class.java else SnoozeReminderActivity::class.java</ID>
<ID>MaxLineLength:Context.kt$val weekDays = withFirstDayOfWeekToFront(resources.getStringArray(org.fossify.commons.R.array.week_days_short).toList())</ID>
<ID>MaxLineLength:Context.kt$var eventStartTS = if (event.getIsAllDay()) Formatter.getDayStartTS(Formatter.getDayCodeFromTS(event.startTS)) else event.startTS</ID>
<ID>MaxLineLength:CustomPeriodPickerDialog.kt$CustomPeriodPickerDialog$private</ID>
<ID>MaxLineLength:DayEventsAdapter.kt$DayEventsAdapter$class</ID>
<ID>MaxLineLength:DayEventsAdapter.kt$DayEventsAdapter$eventItemDescription.text = if (replaceDescriptionWithLocation) event.location else event.description.replace("\n", " ")</ID>
@@ -311,13 +264,8 @@
<ID>MaxLineLength:DayEventsAdapter.kt$DayEventsAdapter$val nonRepeatingEventIDs = eventsToDelete.asSequence().filter { it.repeatInterval == 0 }.mapNotNull { it.id }.toMutableList()</ID>
<ID>MaxLineLength:DayEventsAdapter.kt$DayEventsAdapter$val repeatingEventIDs = eventsToDelete.asSequence().filter { it.repeatInterval != 0 }.mapNotNull { it.id }.toList()</ID>
<ID>MaxLineLength:DayFragment.kt$DayFragment$val</ID>
<ID>MaxLineLength:EditEventTypeDialog.kt$EditEventTypeDialog$activity</ID>
<ID>MaxLineLength:EditEventTypeDialog.kt$EditEventTypeDialog$class</ID>
<ID>MaxLineLength:EditRepeatingEventDialog.kt$EditRepeatingEventDialog$class</ID>
<ID>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</ID>
<ID>MaxLineLength:Event.kt$Event$fun getCalDAVCalendarId()</ID>
<ID>MaxLineLength:Event.kt$Event$wantedDay = properMonth.dayOfMonth + ((properMonth.dayOfMonth().maximumValue - properMonth.dayOfMonth) / 7) * 7</ID>
<ID>MaxLineLength:Event.kt$Event$while</ID>
<ID>MaxLineLength:EventActivity.kt$EventActivity$if</ID>
<ID>MaxLineLength:EventListAdapter.kt$EventListAdapter$activity: SimpleActivity</ID>
<ID>MaxLineLength:EventListAdapter.kt$EventListAdapter$eventItemDescription.text = if (replaceDescription) listEvent.location else listEvent.description.replace("\n", " ")</ID>
@@ -326,38 +274,22 @@
<ID>MaxLineLength:EventListAdapter.kt$EventListAdapter$if</ID>
<ID>MaxLineLength:EventListAdapter.kt$EventListAdapter$listItems.filter { it is ListEvent &amp;&amp; selectedKeys.contains(it.hashCode()) }.map { (it as ListEvent).id }.toMutableList() as ArrayList&lt;Long&gt;</ID>
<ID>MaxLineLength:EventListAdapter.kt$EventListAdapter$val eventsToDelete = listItems.filter { selectedKeys.contains((it as? ListEvent)?.hashCode()) } as List&lt;ListEvent&gt;</ID>
<ID>MaxLineLength:EventListFragment.kt$EventListFragment$(binding.calendarEventsList.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(firstNonPastSectionIndex, 0)</ID>
<ID>MaxLineLength:EventListFragment.kt$EventListFragment$binding.calendarEventsList.smoothScrollBy(0, requireContext().resources.getDimension(R.dimen.endless_scroll_move_height).toInt())</ID>
<ID>MaxLineLength:EventListFragment.kt$EventListFragment$val lastPosition = (binding.calendarEventsList.layoutManager as MyLinearLayoutManager).findLastVisibleItemPosition()</ID>
<ID>MaxLineLength:EventListWidgetAdapter.kt$EventListWidgetAdapter$if</ID>
<ID>MaxLineLength:EventListWidgetAdapter.kt$EventListWidgetAdapter$}</ID>
<ID>MaxLineLength:EventsDao.kt$EventsDao$//val selection = "$COL_REMINDER_MINUTES != -1 AND ($COL_START_TS &gt; ? OR $COL_REPEAT_INTERVAL != 0) AND $COL_START_TS != 0"</ID>
<ID>MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE reminder_1_minutes != -1 AND (start_ts &gt; :currentTS OR repeat_interval != 0) AND start_ts != 0")</ID>
<ID>MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts &lt;= :toTS AND end_ts &gt;= :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)")</ID>
<ID>MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts &lt;= :toTS AND end_ts &gt;= :fromTS AND start_ts != 0 AND repeat_interval = 0 AND event_type IN (:eventTypeIds)")</ID>
<ID>MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts &lt;= :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)")</ID>
<ID>MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts &lt;= :toTS AND start_ts != 0 AND repeat_interval != 0 AND event_type IN (:eventTypeIds)")</ID>
<ID>MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts &lt;= :toTS AND start_ts &gt;= :fromTS AND event_type IN (:eventTypeIds) AND type = $TYPE_TASK")</ID>
<ID>MaxLineLength:EventsDao.kt$EventsDao$fun</ID>
<ID>MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts &lt;= :toTS AND end_ts &gt;= :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)")</ID>
<ID>MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts &lt;= :toTS AND end_ts &gt;= :fromTS AND start_ts != 0 AND repeat_interval = 0 AND event_type IN (:calendarIds)")</ID>
<ID>MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts &lt;= :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)")</ID>
<ID>MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts &lt;= :toTS AND start_ts != 0 AND repeat_interval != 0 AND event_type IN (:calendarIds)")</ID>
<ID>MaxLineLength:EventsDao.kt$EventsDao$@Query("SELECT * FROM events WHERE start_ts &lt;= :toTS AND start_ts &gt;= :fromTS AND event_type IN (:calendarIds) AND type = $TYPE_TASK")</ID>
<ID>MaxLineLength:EventsDatabase.kt$EventsDatabase.Companion.&lt;no name provided&gt;$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)")</ID>
<ID>MaxLineLength:EventsDatabase.kt$EventsDatabase.Companion.&lt;no name provided&gt;$execSQL("CREATE TABLE IF NOT EXISTS `widgets` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `widget_id` INTEGER NOT NULL, `period` INTEGER NOT NULL)")</ID>
<ID>MaxLineLength:EventsDatabase.kt$EventsDatabase.Companion.&lt;no name provided&gt;$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)")</ID>
<ID>MaxLineLength:EventsHelper.kt$EventsHelper$eventTypeId = createPredefinedEventType(anniversaries, R.color.default_anniversaries_color, ANNIVERSARY_EVENT)</ID>
<ID>MaxLineLength:EventsHelper.kt$EventsHelper$events.addAll(eventsDB.getOneTimeEventsFromToWithTypes(toTS, fromTS, typesList).toMutableList() as ArrayList&lt;Event&gt;)</ID>
<ID>MaxLineLength:EventsHelper.kt$EventsHelper$eventsDB.getOneTimeEventsFromToWithTypesForSearch(toTS, fromTS, typesList, "%$searchQuery%").toMutableList() as ArrayList&lt;Event&gt;</ID>
<ID>MaxLineLength:EventsHelper.kt$EventsHelper$eventsDB.getRepeatableEventsOrTasksWithTypes(toTS, context.config.getDisplayEventTypessAsList()).toMutableList() as ArrayList&lt;Event&gt;</ID>
<ID>MaxLineLength:EventsHelper.kt$EventsHelper$eventsDB.getRepeatableEventsOrTasksWithTypesForSearch(toTS, context.config.getDisplayEventTypessAsList(), "%$searchQuery%")</ID>
<ID>MaxLineLength:EventsHelper.kt$EventsHelper$fun</ID>
<ID>MaxLineLength:EventsHelper.kt$EventsHelper$if</ID>
<ID>MaxLineLength:EventsHelper.kt$EventsHelper$it.caldavCalendarId == 0 || caldavCalendars.firstOrNull { it.id == eventType.caldavCalendarId }?.canWrite() == true</ID>
<ID>MaxLineLength:EventsHelper.kt$EventsHelper$private</ID>
<ID>MaxLineLength:EventsHelper.kt$EventsHelper$val previousOccurrenceTS = occurrenceTS - event.repeatInterval // always update repeat limit of the occurrence preceding the one being edited</ID>
<ID>MaxLineLength:EventsHelper.kt$EventsHelper$val typesToDelete = eventTypes.asSequence().filter { it.caldavCalendarId == 0 &amp;&amp; it.id != REGULAR_EVENT_TYPE_ID }.toMutableList()</ID>
<ID>MaxLineLength:EventsHelper.kt$EventsHelper$occurrenceTS - event.repeatInterval</ID>
<ID>MaxLineLength:ExportEventsDialog.kt$ExportEventsDialog$(binding.exportEventsTypesList.adapter as FilterCalendarAdapter).getSelectedItemsList()</ID>
<ID>MaxLineLength:ExportEventsDialog.kt$ExportEventsDialog$exportEventsFilename.setText("${activity.getString(R.string.events)}_${activity.getCurrentFormattedDateTime()}")</ID>
<ID>MaxLineLength:ExportEventsDialog.kt$ExportEventsDialog$val eventTypes = (binding.exportEventsTypesList.adapter as FilterEventTypeAdapter).getSelectedItemsList()</ID>
<ID>MaxLineLength:FilterEventTypeAdapter.kt$FilterEventTypeAdapter$class</ID>
<ID>MaxLineLength:FilterEventTypeAdapter.kt$FilterEventTypeAdapter$override fun onBindViewHolder(holder: EventTypeViewHolder, position: Int)</ID>
<ID>MaxLineLength:FilterEventTypeAdapter.kt$FilterEventTypeAdapter.EventTypeViewHolder$filterEventTypeCheckbox.setColors(activity.getProperTextColor(), activity.getProperPrimaryColor(), activity.getProperBackgroundColor())</ID>
<ID>MaxLineLength:Formatter.kt$Formatter$DateTimeFormat.forPattern(DAYCODE_PATTERN).withZone(DateTimeZone.getDefault()).parseLocalDate(dayCode).toDateTimeAtStartOfDay()</ID>
<ID>MaxLineLength:Formatter.kt$Formatter$fun</ID>
<ID>MaxLineLength:Formatter.kt$Formatter$fun getDate(context: Context, dateTime: DateTime, addDayOfWeek: Boolean = true)</ID>
@@ -371,39 +303,11 @@
<ID>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</ID>
<ID>MaxLineLength:IcsImporter.kt$IcsImporter$// repeating event exceptions can have the same import id as their parents, so pick the latest event to update</ID>
<ID>MaxLineLength:IcsImporter.kt$IcsImporter$// some RRULEs need to know the events start datetime. If it's yet unknown, postpone RRULE parsing</ID>
<ID>MaxLineLength:IcsImporter.kt$IcsImporter$Reminder(curReminderMinutes.getOrElse(0) { REMINDER_OFF }, curReminderActions.getOrElse(0) { REMINDER_NOTIFICATION })</ID>
<ID>MaxLineLength:IcsImporter.kt$IcsImporter$Reminder(curReminderMinutes.getOrElse(1) { REMINDER_OFF }, curReminderActions.getOrElse(1) { REMINDER_NOTIFICATION })</ID>
<ID>MaxLineLength:IcsImporter.kt$IcsImporter$Reminder(curReminderMinutes.getOrElse(2) { REMINDER_OFF }, curReminderActions.getOrElse(2) { REMINDER_NOTIFICATION })</ID>
<ID>MaxLineLength:IcsImporter.kt$IcsImporter$if</ID>
<ID>MaxLineLength:IcsImporter.kt$IcsImporter$line.substring(TRANSP.length).let { curAvailability = if (it == TRANSPARENT) Events.AVAILABILITY_FREE else Events.AVAILABILITY_BUSY }</ID>
<ID>MaxLineLength:IcsImporter.kt$IcsImporter$reminders = reminders.sortedBy { it.minutes }.sortedBy { it.minutes == REMINDER_OFF }.toMutableList() as ArrayList&lt;Reminder&gt;</ID>
<ID>MaxLineLength:IcsImporter.kt$IcsImporter$val eventToUpdate = existingEvents.filter { curImportId.isNotEmpty() &amp;&amp; curImportId == it.importId }.maxByOrNull { it.lastUpdated }</ID>
<ID>MaxLineLength:IcsImporter.kt$IcsImporter$val source = if (calDAVCalendarId == 0 || eventType?.isSyncedEventType() == false) SOURCE_IMPORTED_ICS else "$CALDAV-$calDAVCalendarId"</ID>
<ID>MaxLineLength:IcsImporter.kt$IcsImporter$var</ID>
<ID>MaxLineLength:ImportEventsDialog.kt$ImportEventsDialog$val isLastCaldavCalendarOK = config.caldavSync &amp;&amp; config.getSyncedCalendarIdsAsList().contains(config.lastUsedCaldavCalendarId)</ID>
<ID>MaxLineLength:ImportEventsDialog.kt$ImportEventsDialog$val lastUsedCalDAVCalendar = activity.eventsHelper.getEventTypeWithCalDAVCalendarId(config.lastUsedCaldavCalendarId)</ID>
<ID>MaxLineLength:ImportEventsDialog.kt$ImportEventsDialog$val result = IcsImporter(activity).importEvents(path, currEventTypeId, currEventTypeCalDAVCalendarId, overrideFileEventTypes)</ID>
<ID>MaxLineLength:IcsImporter.kt$IcsImporter$if (calDAVCalendarId == 0 || calendar?.isSyncedCalendar() == false) SOURCE_IMPORTED_ICS else "$CALDAV-$calDAVCalendarId"</ID>
<ID>MaxLineLength:ListSectionDay.kt$ListSectionDay : ListItem</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$(newEventDrawable as LayerDrawable).findDrawableByLayerId(R.id.shortcut_event_background).applyColorFilter(appIconColor)</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$(newTaskDrawable as LayerDrawable).findDrawableByLayerId(R.id.shortcut_task_background).applyColorFilter(appIconColor)</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$// private contacts are created in Simple Contacts Pro, so we can guarantee that they exist only in these 2 formats</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$binding.searchResultsList.smoothScrollBy(0, resources.getDimension(R.dimen.endless_scroll_move_height).toInt())</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$binding.swipeRefreshLayout.isEnabled = config.caldavSync &amp;&amp; config.pullToRefresh &amp;&amp; config.storedView != WEEKLY_VIEW</ID>
<ID>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))</ID>
<ID>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))</ID>
<ID>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))</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(org.fossify.commons.R.bool.hide_google_relations)</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$if</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$it.title.contains(currentSearchQuery, true) || it.location.contains(currentSearchQuery, true)</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$null</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$private</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$reminder3Minutes = reminders[2]</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$repeatInterval = YEAR</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$val eventTypeId = if (birthdays) eventsHelper.getLocalBirthdaysEventTypeId() else eventsHelper.getAnniversariesEventTypeId()</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$val lastPosition = (binding.searchResultsList.layoutManager as MyLinearLayoutManager).findLastVisibleItemPosition()</ID>
<ID>MaxLineLength:MainActivity.kt$MainActivity$||</ID>
<ID>MaxLineLength:ManageAutomaticBackupsDialog.kt$ManageAutomaticBackupsDialog$activity</ID>
<ID>MaxLineLength:ManageEventTypesAdapter.kt$ManageEventTypesAdapter$activity: SimpleActivity</ID>
<ID>MaxLineLength:MonthDayFragment.kt$MonthDayFragment$binding.monthDaySelectedDayLabel.text = Formatter.getDateFromCode(requireActivity(), mSelectedDayCode, false)</ID>
<ID>MaxLineLength:MonthDayFragment.kt$MonthDayFragment$override</ID>
<ID>MaxLineLength:MonthDayFragment.kt$MonthDayFragment$shownMonthDateTime.year == startDateTime.year &amp;&amp; shownMonthDateTime.monthOfYear == startDateTime.monthOfYear</ID>
@@ -447,61 +351,23 @@
<ID>MaxLineLength:ReminderWarningDialog.kt$ReminderWarningDialog$activity</ID>
<ID>MaxLineLength:RepeatLimitTypePickerDialog.kt$RepeatLimitTypePickerDialog$class</ID>
<ID>MaxLineLength:RepeatLimitTypePickerDialog.kt$RepeatLimitTypePickerDialog$private</ID>
<ID>MaxLineLength:SelectCalendarsDialog.kt$SelectCalendarsDialog$CalendarItemAccountBinding.inflate(activity.layoutInflater, binding.dialogSelectCalendarsHolder, false)</ID>
<ID>MaxLineLength:SelectCalendarsDialog.kt$SelectCalendarsDialog$CalendarItemCalendarBinding.inflate(activity.layoutInflater, binding.dialogSelectCalendarsHolder, false)</ID>
<ID>MaxLineLength:SelectEventCalendarDialog.kt$SelectEventCalendarDialog$class</ID>
<ID>MaxLineLength:SelectEventCalendarDialog.kt$SelectEventCalendarDialog$radioGroup.addView(radioBinding.root, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))</ID>
<ID>MaxLineLength:SelectEventColorDialog.kt$SelectEventColorDialog$class</ID>
<ID>MaxLineLength:SelectEventTypeColorDialog.kt$SelectEventTypeColorDialog$class</ID>
<ID>MaxLineLength:SelectEventTypeDialog.kt$SelectEventTypeDialog$radioGroup.addView(radioBinding.root, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))</ID>
<ID>MaxLineLength:SelectEventTypeDialog.kt$SelectEventTypeDialog$val activity: Activity</ID>
<ID>MaxLineLength:SelectEventTypeDialog.kt$SelectEventTypeDialog$val addLastUsedOneAsFirstOption: Boolean</ID>
<ID>MaxLineLength:SelectEventTypeDialog.kt$SelectEventTypeDialog$val lastUsedEventType = EventType(LAST_USED_EVENT_TYPE_ID, activity.getString(R.string.last_used_one), Color.TRANSPARENT, 0)</ID>
<ID>MaxLineLength:SelectEventTypeDialog.kt$SelectEventTypeDialog$val newEventType = EventType(NEW_EVENT_TYPE_ID, activity.getString(R.string.add_new_type), Color.TRANSPARENT, 0)</ID>
<ID>MaxLineLength:SelectEventTypesDialog.kt$SelectEventTypesDialog$class</ID>
<ID>MaxLineLength:SelectTimeZoneAdapter.kt$SelectTimeZoneAdapter$class</ID>
<ID>MaxLineLength:SetRemindersDialog.kt$SetRemindersDialog$class</ID>
<ID>MaxLineLength:SetRemindersDialog.kt$SetRemindersDialog$val tempReminders = arrayListOf(mReminder1Minutes, mReminder2Minutes, mReminder3Minutes).filter { it != REMINDER_OFF }.sorted()</ID>
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$IcsExporter.ExportResult.EXPORT_PARTIAL -&gt; org.fossify.commons.R.string.exporting_some_entries_failed</ID>
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$PermissionRequiredDialog(this, org.fossify.commons.R.string.allow_notifications_reminders, { openNotificationSettings() })</ID>
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$arrayOf(settingsDefaultReminder1Holder, settingsDefaultReminder2Holder, settingsDefaultReminder3Holder)</ID>
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$settingsUseEnglishHolder.beVisibleIf((config.wasUseEnglishToggled || Locale.getDefault().language != "en") &amp;&amp; !isTiramisuPlus())</ID>
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$val eventType = EventType(null, it.displayName, it.color, it.id, it.displayName, it.accountName)</ID>
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$val events = eventsHelper.getEventsToExport(eventTypes, config.exportEvents, config.exportTasks, config.exportPastEntries)</ID>
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$val reminders = sortedSetOf(config.defaultReminder1, config.defaultReminder2, config.defaultReminder3).filter { it != REMINDER_OFF }</ID>
<ID>MaxLineLength:SettingsActivity.kt$SettingsActivity$}</ID>
<ID>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</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$// the stored value might be incorrect so update it (e.g. user completed the task via notification action before editing)</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$ColorPickerDialog</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$DELETE_SELECTED_OCCURRENCE -&gt; eventsHelper.deleteRepeatingEventOccurrence(mTask.id!!, mTaskOccurrenceTS, false)</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$PermissionRequiredDialog(this, org.fossify.commons.R.string.allow_notifications_reminders, { openNotificationSettings() })</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$binding.taskRepetitionRuleHolder.beVisibleIf(mRepeatInterval.isXWeeklyRepetition() || mRepeatInterval.isXMonthlyRepetition() || mRepeatInterval.isXYearlyRepetition())</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$if</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$items.add(RadioItem(REPEAT_ORDER_WEEKDAY_USE_LAST, getRepeatXthDayInMonthString(true, REPEAT_ORDER_WEEKDAY_USE_LAST)))</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$items.add(RadioItem(REPEAT_ORDER_WEEKDAY_USE_LAST, getRepeatXthDayString(true, REPEAT_ORDER_WEEKDAY_USE_LAST)))</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$mEventTypeId = if (config.defaultEventTypeId == -1L) config.lastUsedLocalEventTypeId else config.defaultEventTypeId</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$mReminder1Minutes = if (usePreviousEventReminders &amp;&amp; lastEventReminderMinutes1 &gt;= -1) lastEventReminderMinutes1 else defaultReminder1</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$mReminder2Minutes = if (usePreviousEventReminders &amp;&amp; lastEventReminderMinutes2 &gt;= -1) lastEventReminderMinutes2 else defaultReminder2</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$mReminder3Minutes = if (usePreviousEventReminders &amp;&amp; lastEventReminderMinutes3 &gt;= -1) lastEventReminderMinutes3 else defaultReminder3</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$private fun isLastDayOfTheMonth()</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$reminders = reminders.filter { it.minutes != REMINDER_OFF }.sortedBy { it.minutes }.toMutableList() as ArrayList&lt;Reminder&gt;</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$this</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$val</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$val everyString = getString(if (isMaleGender(mTaskDateTime.dayOfWeek)) R.string.every_m else R.string.every_f)</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$if (usePreviousEventReminders &amp;&amp; lastEventReminderMinutes1 &gt;= -1) lastEventReminderMinutes1 else defaultReminder1</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$if (usePreviousEventReminders &amp;&amp; lastEventReminderMinutes2 &gt;= -1) lastEventReminderMinutes2 else defaultReminder2</ID>
<ID>MaxLineLength:TaskActivity.kt$TaskActivity$if (usePreviousEventReminders &amp;&amp; lastEventReminderMinutes3 &gt;= -1) lastEventReminderMinutes3 else defaultReminder3</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$((currentEventWeeklyView.range.upper - currentEventWeeklyView.range.lower) * minuteHeight).toInt() - 1</ID>
<ID>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</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$// we need to refresh all fragments because they can contain future occurrences</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$DragEvent.ACTION_DRAG_STARTED -&gt; dragEvent.clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$compareBy&lt;Event&gt; { it.startTS }.thenBy { it.endTS }.thenBy { it.title }.thenBy { if (replaceDescription) it.location else it.description }</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$context?.eventsHelper</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$dayColumns.indexOfFirst { it.tag.toInt() == dayCodeStart || it.tag.toInt() in (dayCodeStart + 1)..dayCodeEnd }</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$eventWeeklyView.range.upper &gt; eventWeeklyViewToCheck.range.lower</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$scrollView.layoutParams.height = fullHeight - res.getDimension(org.fossify.commons.R.dimen.one_dp).toInt()</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$val (eventId, originalStartTS, originalEndTS) = dragEvent.clipData.getItemAt(0).text.toString().split(";").map { it.toLong() }</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$val clipData = ClipData.newPlainText(WEEKLY_EVENT_ID_LABEL, "${event.id};${event.startTS};${event.endTS}")</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$val dayOfWeek = dayColumns.indexOfFirst { it.tag.toInt() == dayCodeStart || it.tag.toInt() in (dayCodeStart + 1)..dayCodeEnd }</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$val isRowValidForEvent = lastEvent == null || firstEventRowIdx!! + repeatingEventIndex == index &amp;&amp; lastEventRowIdx!! &lt; index</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$val isStartTimeDay = Formatter.getDateTimeFromTS(maxTS) == Formatter.getDateTimeFromTS(maxTS).withTimeAtStartOfDay()</ID>
<ID>MaxLineLength:WeekFragment.kt$WeekFragment$val numDays = Days.daysBetween(Formatter.getDateTimeFromTS(minTS).toLocalDate(), Formatter.getDateTimeFromTS(maxTS).toLocalDate()).days</ID>
<ID>MaxLineLength:WeekFragmentsHolder.kt$WeekFragmentsHolder$binding.weekViewDaysCount.text = requireContext().resources.getQuantityString(org.fossify.commons.R.plurals.days, cnt, cnt)</ID>
<ID>MaxLineLength:WidgetDateConfigureActivity.kt$WidgetDateConfigureActivity$if</ID>
<ID>MaxLineLength:WidgetListConfigureActivity.kt$WidgetListConfigureActivity$EventListAdapter(this@WidgetListConfigureActivity, getListItems(), false, null, configWidgetPreview.configEventsList) {}</ID>
@@ -518,13 +384,13 @@
<ID>NestedBlockDepth:CalDAVHelper.kt$CalDAVHelper$fun refreshCalendars(showToasts: Boolean, scheduleNextSync: Boolean, callback: () -&gt; Unit)</ID>
<ID>NestedBlockDepth:Context.kt$inline fun Context.queryCursorInlined( uri: Uri, projection: Array&lt;String&gt;, selection: String? = null, selectionArgs: Array&lt;String&gt;? = null, sortOrder: String? = null, showErrors: Boolean = false, callback: (cursor: Cursor) -&gt; Unit )</ID>
<ID>NestedBlockDepth:DayEventsAdapter.kt$DayEventsAdapter$private fun setupView(view: View, event: Event)</ID>
<ID>NestedBlockDepth:EventActivity.kt$EventActivity$private fun gotEvent( savedInstanceState: Bundle?, localEventType: EventType?, event: Event?, )</ID>
<ID>NestedBlockDepth:EventActivity.kt$EventActivity$private fun gotEvent( savedInstanceState: Bundle?, localCalendar: CalendarEntity?, event: Event?, )</ID>
<ID>NestedBlockDepth:EventsHelper.kt$EventsHelper$fun getEventsSync( fromTS: Long, toTS: Long, eventId: Long = -1L, applyTypeFilter: Boolean, searchQuery: String = "", callback: (events: ArrayList&lt;Event&gt;) -&gt; Unit )</ID>
<ID>NestedBlockDepth:EventsHelper.kt$EventsHelper$fun insertOrUpdateEventTypeSync(eventType: EventType): Long</ID>
<ID>NestedBlockDepth:EventsHelper.kt$EventsHelper$private fun getEventsRepeatingTillDateOrForever(fromTS: Long, toTS: Long, startTimes: LongSparseArray&lt;Long&gt;, event: Event): ArrayList&lt;Event&gt;</ID>
<ID>NestedBlockDepth:EventsHelper.kt$EventsHelper$private fun getEventsRepeatingXTimes(fromTS: Long, toTS: Long, startTimes: LongSparseArray&lt;Long&gt;, event: Event): ArrayList&lt;Event&gt;</ID>
<ID>NestedBlockDepth:EventsHelper.kt$EventsHelper$fun insertOrUpdateCalendarSync(calendar: CalendarEntity): Long</ID>
<ID>NestedBlockDepth:EventsHelper.kt$EventsHelper$private fun getEventsRepeatingTillDateOrForever( fromTS: Long, toTS: Long, startTimes: LongSparseArray&lt;Long&gt;, event: Event ): ArrayList&lt;Event&gt;</ID>
<ID>NestedBlockDepth:EventsHelper.kt$EventsHelper$private fun getEventsRepeatingXTimes( fromTS: Long, toTS: Long, startTimes: LongSparseArray&lt;Long&gt;, event: Event ): ArrayList&lt;Event&gt;</ID>
<ID>NestedBlockDepth:IcsExporter.kt$IcsExporter$private fun fillReminders(event: Event, out: BufferedWriter, reminderLabel: String)</ID>
<ID>NestedBlockDepth:IcsImporter.kt$IcsImporter$fun importEvents( path: String, defaultEventTypeId: Long, calDAVCalendarId: Int, overrideFileEventTypes: Boolean, eventReminders: ArrayList&lt;Int&gt;? = null, loadFromAssets: Boolean = false, ): ImportResult</ID>
<ID>NestedBlockDepth:IcsImporter.kt$IcsImporter$fun importEvents( path: String, defaultCalendarId: Long, calDAVCalendarId: Int, overrideFileCalendars: Boolean, eventReminders: ArrayList&lt;Int&gt;? = null, loadFromAssets: Boolean = false, ): ImportResult</ID>
<ID>NestedBlockDepth:IcsImporter.kt$IcsImporter$private fun getTimestamp(fullString: String): Long</ID>
<ID>NestedBlockDepth:MainActivity.kt$MainActivity$private fun addPrivateEvents( birthdays: Boolean, contacts: ArrayList&lt;SimpleContact&gt;, reminders: ArrayList&lt;Int&gt;, callback: (eventsFound: Int, eventsAdded: Int) -&gt; Unit )</ID>
<ID>NestedBlockDepth:MainActivity.kt$MainActivity$private fun checkIsViewIntent()</ID>
@@ -568,7 +434,7 @@
<ID>TooManyFunctions:EventsHelper.kt$EventsHelper</ID>
<ID>TooManyFunctions:Formatter.kt$Formatter</ID>
<ID>TooManyFunctions:MainActivity.kt$MainActivity : SimpleActivityRefreshRecyclerViewListener</ID>
<ID>TooManyFunctions:ManageEventTypesAdapter.kt$ManageEventTypesAdapter : MyRecyclerViewAdapter</ID>
<ID>TooManyFunctions:ManageCalendarsAdapter.kt$ManageCalendarsAdapter : MyRecyclerViewAdapter</ID>
<ID>TooManyFunctions:MonthDayFragment.kt$MonthDayFragment : FragmentMonthlyCalendarRefreshRecyclerViewListener</ID>
<ID>TooManyFunctions:MonthDayFragmentsHolder.kt$MonthDayFragmentsHolder : MyFragmentHolderNavigationListener</ID>
<ID>TooManyFunctions:MonthFragmentsHolder.kt$MonthFragmentsHolder : MyFragmentHolderNavigationListener</ID>
@@ -583,17 +449,17 @@
<ID>TooManyFunctions:WidgetMonthlyConfigureActivity.kt$WidgetMonthlyConfigureActivity : SimpleActivityMonthlyCalendar</ID>
<ID>TooManyFunctions:YearFragmentsHolder.kt$YearFragmentsHolder : MyFragmentHolderNavigationListener</ID>
<ID>UnusedPrivateProperty:YearlyCalendarImpl.kt$YearlyCalendarImpl$i</ID>
<ID>VariableNaming:CalendarPickerActivity.kt$CalendarPickerActivity$private val TYPE_EVENT = 0</ID>
<ID>VariableNaming:CalendarPickerActivity.kt$CalendarPickerActivity$private val TYPE_TASK = 1</ID>
<ID>VariableNaming:DayFragmentsHolder.kt$DayFragmentsHolder$private val PREFILLED_DAYS = 251</ID>
<ID>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+)?)\$"</ID>
<ID>VariableNaming:EventActivity.kt$EventActivity$private val SELECT_TIME_ZONE_INTENT = 1</ID>
<ID>VariableNaming:EventListWidgetAdapter.kt$EventListWidgetAdapter$private val ITEM_EVENT = 0</ID>
<ID>VariableNaming:EventListWidgetAdapter.kt$EventListWidgetAdapter$private val ITEM_SECTION_DAY = 1</ID>
<ID>VariableNaming:EventListWidgetAdapter.kt$EventListWidgetAdapter$private val ITEM_SECTION_MONTH = 2</ID>
<ID>VariableNaming:EventTypePickerActivity.kt$EventTypePickerActivity$private val TYPE_EVENT = 0</ID>
<ID>VariableNaming:EventTypePickerActivity.kt$EventTypePickerActivity$private val TYPE_TASK = 1</ID>
<ID>VariableNaming:IcsExporter.kt$IcsExporter$private val MAX_LINE_LENGTH = 75</ID>
<ID>VariableNaming:ManageEventTypesAdapter.kt$ManageEventTypesAdapter$private val DELETE_EVENTS = 1</ID>
<ID>VariableNaming:ManageEventTypesAdapter.kt$ManageEventTypesAdapter$private val MOVE_EVENTS = 0</ID>
<ID>VariableNaming:ManageCalendarsAdapter.kt$ManageCalendarsAdapter$private val DELETE_EVENTS = 1</ID>
<ID>VariableNaming:ManageCalendarsAdapter.kt$ManageCalendarsAdapter$private val MOVE_EVENTS = 0</ID>
<ID>VariableNaming:MonthDayFragmentsHolder.kt$MonthDayFragmentsHolder$private val PREFILLED_MONTHS = 251</ID>
<ID>VariableNaming:MonthFragmentsHolder.kt$MonthFragmentsHolder$private val PREFILLED_MONTHS = 251</ID>
<ID>VariableNaming:MonthlyCalendarImpl.kt$MonthlyCalendarImpl$private val DAYS_CNT = 42</ID>
@@ -606,12 +472,6 @@
<ID>VariableNaming:MyWidgetMonthlyProvider.kt$MyWidgetMonthlyProvider$private val NEW_EVENT = "new_event"</ID>
<ID>VariableNaming:MyWidgetMonthlyProvider.kt$MyWidgetMonthlyProvider$private val NEXT = "next"</ID>
<ID>VariableNaming:MyWidgetMonthlyProvider.kt$MyWidgetMonthlyProvider$private val PREV = "prev"</ID>
<ID>VariableNaming:SelectEventTypeDialog.kt$SelectEventTypeDialog$private val LAST_USED_EVENT_TYPE_ID = -1L</ID>
<ID>VariableNaming:SelectEventTypeDialog.kt$SelectEventTypeDialog$private val NEW_EVENT_TYPE_ID = -2L</ID>
<ID>VariableNaming:SettingsActivity.kt$SettingsActivity$private val GET_RINGTONE_URI = 1</ID>
<ID>VariableNaming:SettingsActivity.kt$SettingsActivity$private val PICK_EVENTS_EXPORT_FILE_INTENT = 4</ID>
<ID>VariableNaming:SettingsActivity.kt$SettingsActivity$private val PICK_EVENTS_IMPORT_SOURCE_INTENT = 3</ID>
<ID>VariableNaming:SettingsActivity.kt$SettingsActivity$private val PICK_SETTINGS_IMPORT_SOURCE_INTENT = 2</ID>
<ID>VariableNaming:SimpleActivity.kt$SimpleActivity$val CALDAV_REFRESH_DELAY = 3000L</ID>
<ID>VariableNaming:WeekFragment.kt$WeekFragment$private val MAX_SCALE_FACTOR = 5f</ID>
<ID>VariableNaming:WeekFragment.kt$WeekFragment$private val MIN_SCALE_DIFFERENCE = 0.02f</ID>
@@ -630,25 +490,12 @@
<ID>WildcardImport:DayEventsAdapter.kt$import org.fossify.calendar.extensions.*</ID>
<ID>WildcardImport:DayFragment.kt$import org.fossify.calendar.helpers.*</ID>
<ID>WildcardImport:DayFragment.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:EditEventTypeDialog.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:Event.kt$import org.fossify.calendar.helpers.*</ID>
<ID>WildcardImport:EventListAdapter.kt$import org.fossify.calendar.extensions.*</ID>
<ID>WildcardImport:EventListAdapter.kt$import org.fossify.calendar.helpers.*</ID>
<ID>WildcardImport:EventListFragment.kt$import org.fossify.calendar.extensions.*</ID>
<ID>WildcardImport:EventListFragment.kt$import org.fossify.calendar.helpers.*</ID>
<ID>WildcardImport:EventListFragment.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:EventListWidgetAdapter.kt$import org.fossify.calendar.extensions.*</ID>
<ID>WildcardImport:EventListWidgetAdapter.kt$import org.fossify.calendar.helpers.*</ID>
<ID>WildcardImport:EventListWidgetAdapter.kt$import org.fossify.calendar.models.*</ID>
<ID>WildcardImport:EventListWidgetAdapter.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:EventTypesDao.kt$import androidx.room.*</ID>
<ID>WildcardImport:EventsDao.kt$import org.fossify.calendar.helpers.*</ID>
<ID>WildcardImport:EventsHelper.kt$import org.fossify.calendar.extensions.*</ID>
<ID>WildcardImport:ExportEventsDialog.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:ImportEventsDialog.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:ManageAutomaticBackupsDialog.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:ManageEventTypesAdapter.kt$import android.view.*</ID>
<ID>WildcardImport:ManageEventTypesAdapter.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:MonthDayFragment.kt$import org.fossify.calendar.extensions.*</ID>
<ID>WildcardImport:MonthView.kt$import android.graphics.*</ID>
<ID>WildcardImport:MonthView.kt$import org.fossify.calendar.extensions.*</ID>
@@ -659,27 +506,7 @@
<ID>WildcardImport:Parser.kt$import org.fossify.commons.helpers.*</ID>
<ID>WildcardImport:ReminderWarningDialog.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:RepeatLimitTypePickerDialog.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:SelectEventCalendarDialog.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:SelectEventTypeDialog.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:SetRemindersDialog.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:SettingsActivity.kt$import org.fossify.calendar.dialogs.*</ID>
<ID>WildcardImport:SettingsActivity.kt$import org.fossify.calendar.extensions.*</ID>
<ID>WildcardImport:SettingsActivity.kt$import org.fossify.calendar.helpers.*</ID>
<ID>WildcardImport:SettingsActivity.kt$import org.fossify.commons.dialogs.*</ID>
<ID>WildcardImport:SettingsActivity.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:SettingsActivity.kt$import org.fossify.commons.helpers.*</ID>
<ID>WildcardImport:SplashActivity.kt$import org.fossify.calendar.helpers.*</ID>
<ID>WildcardImport:TaskActivity.kt$import org.fossify.calendar.dialogs.*</ID>
<ID>WildcardImport:TaskActivity.kt$import org.fossify.calendar.extensions.*</ID>
<ID>WildcardImport:TaskActivity.kt$import org.fossify.calendar.helpers.*</ID>
<ID>WildcardImport:TaskActivity.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:TaskActivity.kt$import org.fossify.commons.helpers.*</ID>
<ID>WildcardImport:WeekFragment.kt$import android.view.*</ID>
<ID>WildcardImport:WeekFragment.kt$import org.fossify.calendar.databinding.*</ID>
<ID>WildcardImport:WeekFragment.kt$import org.fossify.calendar.extensions.*</ID>
<ID>WildcardImport:WeekFragment.kt$import org.fossify.calendar.helpers.*</ID>
<ID>WildcardImport:WeekFragment.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:WeekFragment.kt$import org.fossify.commons.helpers.*</ID>
<ID>WildcardImport:WeekFragmentsHolder.kt$import org.fossify.calendar.extensions.*</ID>
<ID>WildcardImport:WeekFragmentsHolder.kt$import org.fossify.commons.extensions.*</ID>
<ID>WildcardImport:WidgetDateConfigureActivity.kt$import org.fossify.commons.extensions.*</ID>

View File

File diff suppressed because it is too large Load Diff

View File

@@ -200,7 +200,7 @@
</activity>
<activity
android:name=".activities.ManageEventTypesActivity"
android:name=".activities.ManageCalendarsActivity"
android:configChanges="orientation"
android:exported="false"
android:label="@string/event_types"
@@ -214,7 +214,7 @@
android:theme="@style/Theme.Transparent" />
<activity
android:name=".activities.EventTypePickerActivity"
android:name=".activities.CalendarPickerActivity"
android:configChanges="orientation"
android:excludeFromRecents="true"
android:exported="false"

View File

@@ -8,7 +8,7 @@ import org.fossify.calendar.extensions.launchNewTaskIntent
import org.fossify.commons.dialogs.RadioGroupDialog
import org.fossify.commons.models.RadioItem
class EventTypePickerActivity : AppCompatActivity() {
class CalendarPickerActivity : AppCompatActivity() {
private val TYPE_EVENT = 0
private val TYPE_TASK = 1

View File

@@ -37,13 +37,13 @@ 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.dialogs.SelectEventCalendarDialog
import org.fossify.calendar.dialogs.SelectEventColorDialog
import org.fossify.calendar.dialogs.SelectEventTypeDialog
import org.fossify.calendar.extensions.calDAVHelper
import org.fossify.calendar.extensions.calendarsDB
import org.fossify.calendar.extensions.cancelNotification
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.getNewEventTimestampFromCode
@@ -59,7 +59,7 @@ import org.fossify.calendar.extensions.showEventRepeatIntervalDialog
import org.fossify.calendar.helpers.ATTENDEES
import org.fossify.calendar.helpers.AVAILABILITY
import org.fossify.calendar.helpers.CALDAV
import org.fossify.calendar.helpers.ORIGINAL_ATTENDEES
import org.fossify.calendar.helpers.CALENDAR_ID
import org.fossify.calendar.helpers.CLASS
import org.fossify.calendar.helpers.CURRENT_TIME_ZONE
import org.fossify.calendar.helpers.DELETE_ALL_OCCURRENCES
@@ -74,16 +74,16 @@ import org.fossify.calendar.helpers.EVENT_CALENDAR_ID
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.EVENT_TYPE_ID
import org.fossify.calendar.helpers.FLAG_ALL_DAY
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.LOCAL_CALENDAR_ID
import org.fossify.calendar.helpers.NEW_EVENT_SET_HOUR_DURATION
import org.fossify.calendar.helpers.NEW_EVENT_START_TS
import org.fossify.calendar.helpers.ORIGINAL_ATTENDEES
import org.fossify.calendar.helpers.ORIGINAL_END_TS
import org.fossify.calendar.helpers.ORIGINAL_START_TS
import org.fossify.calendar.helpers.LOCAL_CALENDAR_ID
import org.fossify.calendar.helpers.REMINDER_1_MINUTES
import org.fossify.calendar.helpers.REMINDER_1_TYPE
import org.fossify.calendar.helpers.REMINDER_2_MINUTES
@@ -109,8 +109,8 @@ import org.fossify.calendar.helpers.TIME_ZONE
import org.fossify.calendar.helpers.generateImportId
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.MyTimeZone
import org.fossify.calendar.models.Reminder
import org.fossify.commons.dialogs.ColorPickerDialog
@@ -186,7 +186,7 @@ class EventActivity : SimpleActivity() {
private var mRepeatInterval = 0
private var mRepeatLimit = 0L
private var mRepeatRule = 0
private var mEventTypeId = LOCAL_CALENDAR_ID
private var mCalendarId = LOCAL_CALENDAR_ID
private var mEventOccurrenceTS = 0L
private var mLastSavePromptTS = 0L
private var mEventCalendarId = STORED_LOCALLY_ONLY
@@ -200,7 +200,7 @@ class EventActivity : SimpleActivity() {
private var mAvailability = Attendees.AVAILABILITY_BUSY
private var mAccessLevel = Events.ACCESS_DEFAULT
private var mStatus = Events.STATUS_CONFIRMED
private var mStoredEventTypes = ArrayList<EventType>()
private var mStoredCalendars = ArrayList<CalendarEntity>()
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<EventType>
mStoredCalendars =
calendarsDB.getCalendars().toMutableList() as ArrayList<CalendarEntity>
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<ArrayList<Attendee>>(getString(ATTENDEES), token) ?: ArrayList()
mOriginalAttendees =
Gson().fromJson<ArrayList<Attendee>>(getString(ORIGINAL_ATTENDEES), token) ?: ArrayList()
Gson().fromJson<ArrayList<Attendee>>(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,

View File

@@ -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<Int>): 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<Int>, initEventsFound: Int, initEventsAdded: Int, callback: (Int) -> Unit) {
private fun addContactEvents(
birthdays: Boolean,
reminders: ArrayList<Int>,
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<String>()
@@ -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<String, Long>()
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<String>()
@@ -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
}

View File

@@ -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<CalendarEntity>,
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
}
}

View File

@@ -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<EventType>, 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
}
}

View File

@@ -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<Long>()
private var calendarsToExport = listOf<Long>()
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<String>
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<RadioItem>()
(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<RadioItem>()
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<Long>, outputStream: OutputStream?) {
private fun exportEventsTo(calendars: List<Long>, 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 {

View File

@@ -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<EventType>
val localEventType = storedEventTypes.firstOrNull { it.id == config.lastUsedLocalEventTypeId }
val storedCalendars =
calendarsDB.getCalendars().toMutableList() as ArrayList<CalendarEntity>
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<Reminder>
reminders = reminders.filter { it.minutes != REMINDER_OFF }.sortedBy { it.minutes }
.toMutableList() as ArrayList<Reminder>
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<RadioItem> {
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<RadioItem> {
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()

View File

@@ -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<CalendarEntity>,
val displayCalendars: Set<String>
) :
RecyclerView.Adapter<FilterCalendarAdapter.CalendarViewHolder>() {
private val selectedKeys = HashSet<Long>()
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<Long>
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)
}
}
}

View File

@@ -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<EventType>, val displayEventTypes: Set<String>) :
RecyclerView.Adapter<FilterEventTypeAdapter.EventTypeViewHolder>() {
private val selectedKeys = HashSet<Long>()
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<Long>
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)
}
}
}

View File

@@ -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<CalendarEntity>,
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<CalendarEntity>
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<Long>
activity.eventsHelper.doCalendarsContainEventsOrTasks(calendarIds) {
activity.runOnUiThread {
if (it) {
val res = activity.resources
val items = ArrayList<RadioItem>().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)
}
}
}

View File

@@ -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<EventType>, 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<EventType>
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<Long>
activity.eventsHelper.doEventTypesContainEventsOrTasks(eventTypes) {
activity.runOnUiThread {
if (it) {
val res = activity.resources
val items = ArrayList<RadioItem>().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)
}
}
}

View File

@@ -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<EventType>,
private val quickFilterEventTypeIds: Set<String>,
private val allCalendars: List<CalendarEntity>,
private val quickFilterCalendarIds: Set<String>,
val callback: () -> Unit
) : RecyclerView.Adapter<QuickFilterEventTypeAdapter.QuickFilterViewHolder>() {
) : RecyclerView.Adapter<QuickFilterCalendarAdapter.QuickFilterViewHolder>() {
private val activeKeys = HashSet<Long>()
private val quickFilterEventTypes = ArrayList<EventType>()
private val displayEventTypes = activity.config.displayEventTypes
private val quickFilterCalendars = ArrayList<CalendarEntity>()
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<Long>()
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)
}
}
}

View File

@@ -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())
}
}

View File

@@ -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)
}
}
}

View File

@@ -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)
}
}
}

View File

@@ -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<Long>) -> Unit
val activity: SimpleActivity,
val path: String,
val hidePath: Boolean,
val callback: (file: File, calendars: ArrayList<Long>) -> 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<String>()
it.mapTo(eventTypes) { it.id.toString() }
activity.eventsHelper.getCalendars(activity, false) {
val calendars = HashSet<String>()
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()
}
}

View File

@@ -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()
)
}
}
}

View File

@@ -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
}
}

View File

@@ -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<Int>()
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()
}
}

View File

@@ -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
}

View File

@@ -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<CalendarEntity>()
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()
}
}
}

View File

@@ -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<String>,
val callback: (HashSet<String>) -> 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<Int>()
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()
}
}

View File

@@ -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<CalDAVCalendar>, val currCalendarId: Int, val callback: (id: Int) -> Unit) {
class SelectEventCalendarDialog(
val activity: Activity,
val calendars: List<CalDAVCalendar>,
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<CalD
ensureBackgroundThread {
calendars.forEach {
val localEventType = activity.eventsHelper.getEventTypeWithCalDAVCalendarId(it.id)
if (localEventType != null) {
it.color = localEventType.color
val localCalendar = activity.eventsHelper.getCalendarWithCalDAVCalendarId(it.id)
if (localCalendar != null) {
it.color = localCalendar.color
}
}
@@ -35,7 +45,11 @@ class SelectEventCalendarDialog(val activity: Activity, val calendars: List<CalD
calendars.forEach {
addRadioButton(it.getFullTitle(), it.id, it.color)
}
addRadioButton(activity.getString(R.string.store_locally_only), STORED_LOCALLY_ONLY, Color.TRANSPARENT)
addRadioButton(
activity.getString(R.string.store_locally_only),
STORED_LOCALLY_ONLY,
Color.TRANSPARENT
)
wasInit = true
activity.updateTextColors(binding.dialogRadioHolder)
}
@@ -58,11 +72,20 @@ class SelectEventCalendarDialog(val activity: Activity, val calendars: List<CalD
}
if (typeId != STORED_LOCALLY_ONLY) {
radioBinding.dialogRadioColor.setFillWithStroke(color, activity.getProperBackgroundColor())
radioBinding.dialogRadioColor.setFillWithStroke(
color,
activity.getProperBackgroundColor()
)
}
radioBinding.root.setOnClickListener { viewClicked(typeId) }
radioGroup.addView(radioBinding.root, RadioGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
radioGroup.addView(
radioBinding.root,
RadioGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
)
}
private fun viewClicked(typeId: Int) {

View File

@@ -1,102 +0,0 @@
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.ManageEventTypesActivity
import org.fossify.calendar.databinding.DialogSelectEventTypeBinding
import org.fossify.calendar.databinding.RadioButtonWithColorBinding
import org.fossify.calendar.extensions.eventsHelper
import org.fossify.calendar.models.EventType
import org.fossify.commons.extensions.*
class 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
) {
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<EventType>()
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()
}
}
}

View File

@@ -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<String>, val callback: (HashSet<String>) -> 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()
}
}

View File

@@ -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<Int>) -> Unit) {
class SetRemindersDialog(
val activity: SimpleActivity,
val eventType: Int,
val callback: (reminders: ArrayList<Int>) -> 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,

View File

@@ -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<Long>,
calendars = config.autoBackupCalendars.map { it.toLong() } as ArrayList<Long>,
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<Event> {
if (it.getIsAllDay()) {
@@ -707,7 +831,11 @@ fun Context.addDayEvents(day: DayMonthly, linearLayout: LinearLayout, res: Resou
}
}
fun Context.getEventListItems(events: List<Event>, addSectionDays: Boolean = true, addSectionMonths: Boolean = true): ArrayList<ListItem> {
fun Context.getEventListItems(
events: List<Event>,
addSectionDays: Boolean = true,
addSectionMonths: Boolean = true
): ArrayList<ListItem> {
val listItems = ArrayList<ListItem>(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 ->

View File

@@ -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<Event>, updateStatus: Int, forceRecreation: Boolean = false) {
private fun receivedEvents(
events: ArrayList<Event>,
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()

View File

@@ -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<Event, Int>()
private var currEvents = ArrayList<Event>()
private var dayColumns = ArrayList<RelativeLayout>()
private var eventTypeColors = LongSparseArray<Int>()
private var calendarColors = LongSparseArray<Int>()
private var eventTimeRanges = LinkedHashMap<String, LinkedHashMap<Long, EventWeeklyView>>()
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<Event> { it.startTS }.thenBy { it.endTS }.thenBy { it.title }.thenBy { if (replaceDescription) it.location else it.description }
compareBy<Event> { it.startTS }.thenBy { it.endTS }.thenBy { it.title }
.thenBy { if (replaceDescription) it.location else it.description }
).toMutableList() as ArrayList<Event>
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
}

View File

@@ -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<Int, String> {
val colors = mutableMapOf<Int, String>()
val uri = Colors.CONTENT_URI
val projection = arrayOf(Colors.COLOR, Colors.COLOR_KEY)
val selection = "${Colors.COLOR_TYPE} = ? AND ${Colors.ACCOUNT_NAME} = ?"
val selectionArgs = arrayOf(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])
}

View File

@@ -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<String>
get() = prefs.getStringSet(DISPLAY_EVENT_TYPES, HashSet())!!
set(displayEventTypes) = prefs.edit().remove(DISPLAY_EVENT_TYPES).putStringSet(DISPLAY_EVENT_TYPES, displayEventTypes).apply()
var displayCalendars: Set<String>
get() = prefs.getStringSet(DISPLAY_CALENDARS, HashSet())!!
set(displayCalendars) = prefs.edit().remove(DISPLAY_CALENDARS)
.putStringSet(DISPLAY_CALENDARS, displayCalendars).apply()
var quickFilterEventTypes: Set<String>
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<String>
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<Int>
caldavSyncedCalendarIds.split(",").filter { it.trim().isNotEmpty() }
.map { Integer.parseInt(it) }.toMutableList() as ArrayList<Int>
fun getDisplayEventTypessAsList() = displayEventTypes.map { it.toLong() }.toMutableList() as ArrayList<Long>
fun getDisplayCalendarsAsList() =
displayCalendars.map { it.toLong() }.toMutableList() as ArrayList<Long>
fun addDisplayEventType(type: String) {
addDisplayEventTypes(HashSet(Arrays.asList(type)))
fun addDisplayCalendar(type: String) {
addDisplayCalendars(HashSet(listOf(type)))
}
private fun addDisplayEventTypes(types: Set<String>) {
val currDisplayEventTypes = HashSet(displayEventTypes)
currDisplayEventTypes.addAll(types)
displayEventTypes = currDisplayEventTypes
private fun addDisplayCalendars(types: Set<String>) {
val currDisplayCalendars = HashSet(displayCalendars)
currDisplayCalendars.addAll(types)
displayCalendars = currDisplayCalendars
}
fun removeDisplayEventTypes(types: Set<String>) {
val currDisplayEventTypes = HashSet(displayEventTypes)
currDisplayEventTypes.removeAll(types)
displayEventTypes = currDisplayEventTypes
fun removeDisplayCalendars(types: Set<String>) {
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<Int>
get() = prefs.getString(BIRTHDAY_REMINDERS, REMINDER_DEFAULT_VALUE)!!.split(",").map { it.toInt() }.toMutableList() as ArrayList<Int>
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<Int>
set(birthdayReminders) = prefs.edit()
.putString(BIRTHDAY_REMINDERS, birthdayReminders.joinToString(",")).apply()
var anniversaryReminders: ArrayList<Int>
get() = prefs.getString(ANNIVERSARY_REMINDERS, REMINDER_DEFAULT_VALUE)!!.split(",").map { it.toInt() }.toMutableList() as ArrayList<Int>
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<Int>
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<String>
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<String>
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()
}

View File

@@ -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"

View File

@@ -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<EventType>) -> Unit) {
fun getCalendars(
activity: Activity,
showWritableOnly: Boolean,
callback: (calendars: ArrayList<CalendarEntity>) -> Unit
) {
ensureBackgroundThread {
var eventTypes = ArrayList<EventType>()
var calendars = ArrayList<CalendarEntity>()
try {
eventTypes = eventTypesDB.getEventTypes().toMutableList() as ArrayList<EventType>
calendars = calendarsDB.getCalendars().toMutableList() as ArrayList<CalendarEntity>
} 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<EventType>
calendars = calendars.filter {
val calendar = it
it.caldavCalendarId == 0 || caldavCalendars.firstOrNull { it.id == calendar.caldavCalendarId }
?.canWrite() == true
}.toMutableList() as ArrayList<CalendarEntity>
}
activity.runOnUiThread {
callback(eventTypes)
callback(calendars)
}
}
}
fun getEventTypesSync() = eventTypesDB.getEventTypes().toMutableList() as ArrayList<EventType>
fun getCalendarsSync() = calendarsDB.getCalendars().toMutableList() as ArrayList<CalendarEntity>
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<EventType>, deleteEvents: Boolean) {
val typesToDelete = eventTypes
fun deleteCalendars(calendars: ArrayList<CalendarEntity>, 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<Long>, callback: (contain: Boolean) -> Unit) {
fun doCalendarsContainEventsOrTasks(
calendarIds: ArrayList<Long>,
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<Event>) -> Unit
) {
val birthDayEventId = getLocalBirthdaysEventTypeId(createIfNotExists = false)
val anniversaryEventId = getAnniversariesEventTypeId(createIfNotExists = false)
val birthDayEventId = getLocalBirthdaysCalendarId(createIfNotExists = false)
val anniversaryEventId = getAnniversariesCalendarId(createIfNotExists = false)
var events = ArrayList<Event>()
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<Event>)
events.addAll(
eventsDB.getOneTimeEventsFromToWithCalendarIds(
toTS,
fromTS,
typesList
).toMutableList() as ArrayList<Event>
)
} else {
events.addAll(
eventsDB.getOneTimeEventsFromToWithTypesForSearch(toTS, fromTS, typesList, "%$searchQuery%").toMutableList() as ArrayList<Event>
eventsDB.getOneTimeEventsFromToWithTypesForSearch(
toTS,
fromTS,
typesList,
"%$searchQuery%"
).toMutableList() as ArrayList<Event>
)
}
} catch (e: Exception) {
@@ -421,9 +500,11 @@ class EventsHelper(val context: Context) {
events.addAll(
if (eventId == -1L) {
eventsDB.getOneTimeEventsOrTasksFromTo(toTS, fromTS).toMutableList() as ArrayList<Event>
eventsDB.getOneTimeEventsOrTasksFromTo(toTS, fromTS)
.toMutableList() as ArrayList<Event>
} else {
eventsDB.getOneTimeEventFromToWithId(eventId, toTS, fromTS).toMutableList() as ArrayList<Event>
eventsDB.getOneTimeEventFromToWithId(eventId, toTS, fromTS)
.toMutableList() as ArrayList<Event>
}
)
}
@@ -436,7 +517,7 @@ class EventsHelper(val context: Context) {
.filterNot { it.repetitionExceptions.contains(Formatter.getDayCodeFromTS(it.startTS)) }
.toMutableList() as ArrayList<Event>
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<Event> {
fun getRepeatableEventsFor(
fromTS: Long,
toTS: Long,
eventId: Long = -1L,
applyTypeFilter: Boolean = false,
searchQuery: String = ""
): List<Event> {
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<Event>
eventsDB.getRepeatableEventsOrTasksWithCalendarIds(
toTS,
context.config.getDisplayCalendarsAsList()
).toMutableList() as ArrayList<Event>
} else {
eventsDB.getRepeatableEventsOrTasksWithTypesForSearch(toTS, context.config.getDisplayEventTypessAsList(), "%$searchQuery%")
eventsDB.getRepeatableEventsOrTasksWithTypesForSearch(
toTS,
context.config.getDisplayCalendarsAsList(),
"%$searchQuery%"
)
.toMutableList() as ArrayList<Event>
}
} else {
if (eventId == -1L) {
eventsDB.getRepeatableEventsOrTasksWithTypes(toTS).toMutableList() as ArrayList<Event>
eventsDB.getRepeatableEventsOrTasksWithCalendarIds(toTS)
.toMutableList() as ArrayList<Event>
} else {
eventsDB.getRepeatableEventsOrTasksWithId(eventId, toTS).toMutableList() as ArrayList<Event>
eventsDB.getRepeatableEventsOrTasksWithId(eventId, toTS)
.toMutableList() as ArrayList<Event>
}
}
@@ -534,7 +642,12 @@ class EventsHelper(val context: Context) {
return newEvents
}
private fun getEventsRepeatingXTimes(fromTS: Long, toTS: Long, startTimes: LongSparseArray<Long>, event: Event): ArrayList<Event> {
private fun getEventsRepeatingXTimes(
fromTS: Long,
toTS: Long,
startTimes: LongSparseArray<Long>,
event: Event
): ArrayList<Event> {
val original = event.copy()
val events = ArrayList<Event>()
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<Long>, event: Event): ArrayList<Event> {
private fun getEventsRepeatingTillDateOrForever(
fromTS: Long,
toTS: Long,
startTimes: LongSparseArray<Long>,
event: Event
): ArrayList<Event> {
val original = event.copy()
val events = ArrayList<Event>()
while (event.startTS <= toTS && (event.repeatLimit == 0L || event.repeatLimit >= event.startTS)) {
@@ -635,7 +753,8 @@ class EventsHelper(val context: Context) {
fun getRunningEventsOrTasks(): List<Event> {
val ts = getNowSeconds()
val events = eventsDB.getOneTimeEventsOrTasksFromTo(ts, ts).toMutableList() as ArrayList<Event>
val events =
eventsDB.getOneTimeEventsOrTasksFromTo(ts, ts).toMutableList() as ArrayList<Event>
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<Long>, exportEvents: Boolean, exportTasks: Boolean, exportPastEntries: Boolean): MutableList<Event> {
fun getEventsToExport(
calendars: List<Long>,
exportEvents: Boolean,
exportTasks: Boolean,
exportPastEntries: Boolean
): MutableList<Event> {
val currTS = getNowSeconds()
var events = mutableListOf<Event>()
val tasks = mutableListOf<Event>()
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<Int> {
val eventTypeColors = LongSparseArray<Int>()
context.eventTypesDB.getEventTypes().forEach {
eventTypeColors.put(it.id!!, it.color)
fun getCalendarColors(): LongSparseArray<Int> {
val calendarColors = LongSparseArray<Int>()
context.calendarsDB.getCalendars().forEach {
calendarColors.put(it.id!!, it.color)
}
return eventTypeColors
return calendarColors
}
}

View File

@@ -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") }

View File

@@ -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<Int>? = null,
loadFromAssets: Boolean = false,
): ImportResult {
try {
val eventTypes = eventsHelper.getEventTypesSync()
val existingEvents = activity.eventsDB.getEventsOrTasksWithImportIds().toMutableList() as ArrayList<Event>
val calendars = eventsHelper.getCalendarsSync()
val existingEvents = activity.eventsDB.getEventsOrTasksWithImportIds()
.toMutableList() as ArrayList<Event>
val eventsToInsert = ArrayList<Event>()
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<Reminder>
reminders = reminders.sortedBy { it.minutes }
.sortedBy { it.minutes == REMINDER_OFF }
.toMutableList() as ArrayList<Reminder>
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

View File

@@ -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<CalendarEntity>
@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<Int>)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertOrUpdate(calendar: CalendarEntity): Long
@Delete
fun deleteCalendars(calendars: List<CalendarEntity>)
}

View File

@@ -0,0 +1,7 @@
package org.fossify.calendar.interfaces
import org.fossify.calendar.models.CalendarEntity
interface DeleteCalendarsListener {
fun deleteCalendars(calendars: ArrayList<CalendarEntity>, deleteEvents: Boolean): Boolean
}

View File

@@ -1,7 +0,0 @@
package org.fossify.calendar.interfaces
import org.fossify.calendar.models.EventType
interface DeleteEventTypesListener {
fun deleteEventTypes(eventTypes: ArrayList<EventType>, deleteEvents: Boolean): Boolean
}

View File

@@ -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<EventType>
@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<Int>)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertOrUpdate(eventType: EventType): Long
@Delete
fun deleteEventTypes(eventTypes: List<EventType>)
}

View File

@@ -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<Event>
@Query("SELECT * FROM events WHERE event_type IN (:eventTypeIds) AND type = $TYPE_EVENT")
fun getAllEventsWithTypes(eventTypeIds: List<Long>): List<Event>
@Query("SELECT * FROM events WHERE event_type IN (:calendarIds) AND type = $TYPE_EVENT")
fun getAllEventsWithCalendarIds(calendarIds: List<Long>): List<Event>
@Query("SELECT * FROM events WHERE event_type IN (:eventTypeIds) AND type = $TYPE_TASK")
fun getAllTasksWithTypes(eventTypeIds: List<Long>): List<Event>
@Query("SELECT * FROM events WHERE event_type IN (:calendarIds) AND type = $TYPE_TASK")
fun getAllTasksWithCalendarIds(calendarIds: List<Long>): List<Event>
@Query("SELECT * FROM events WHERE end_ts > :currTS AND event_type IN (:eventTypeIds) AND type = $TYPE_EVENT")
fun getAllFutureEventsWithTypes(currTS: Long, eventTypeIds: List<Long>): List<Event>
@Query("SELECT * FROM events WHERE end_ts > :currTS AND event_type IN (:calendarIds) AND type = $TYPE_EVENT")
fun getAllFutureEventsWithCalendarIds(currTS: Long, calendarIds: List<Long>): List<Event>
@Query("SELECT * FROM events WHERE end_ts > :currTS AND event_type IN (:eventTypeIds) AND type = $TYPE_TASK")
fun getAllFutureTasksWithTypes(currTS: Long, eventTypeIds: List<Long>): List<Event>
@Query("SELECT * FROM events WHERE end_ts > :currTS AND event_type IN (:calendarIds) AND type = $TYPE_TASK")
fun getAllFutureTasksWithCalendarIds(currTS: Long, calendarIds: List<Long>): List<Event>
@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<Event>
@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<Long>): List<Event>
@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<Long>): List<Event>
@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<Event>
@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<Long>): List<Event>
@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<Long>
): List<Event>
@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<Long>, searchQuery: String): List<Event>
@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<Long>,
searchQuery: String
): List<Event>
@Query("SELECT * FROM events WHERE start_ts <= :toTS AND repeat_interval != 0")
fun getRepeatableEventsOrTasksWithTypes(toTS: Long): List<Event>
fun getRepeatableEventsOrTasksWithCalendarIds(toTS: Long): List<Event>
@Query("SELECT * FROM events WHERE id = :id AND start_ts <= :toTS AND repeat_interval != 0")
fun getRepeatableEventsOrTasksWithId(id: Long, toTS: Long): List<Event>
@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<Long>): List<Event>
@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<Long>): List<Event>
@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<Long>, searchQuery: String): List<Event>
@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<Long>,
searchQuery: String
): List<Event>
@Query("SELECT * FROM events WHERE id IN (:ids) AND import_id != \"\" AND type = $TYPE_EVENT")
fun getEventsByIdsWithImportIds(ids: List<Long>): List<Event>
@@ -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<Long>
@Query("SELECT id FROM events WHERE event_type = :calendarId")
fun getEventAndTasksIdsByCalendar(calendarId: Long): List<Long>
@Query("SELECT id FROM events WHERE event_type IN (:eventTypeIds)")
fun getEventAndTasksIdsByEventType(eventTypeIds: List<Long>): List<Long>
@Query("SELECT id FROM events WHERE event_type IN (:calendarIds)")
fun getEventAndTasksIdsByCalendar(calendarIds: List<Long>): List<Long>
@Query("SELECT id FROM events WHERE parent_id IN (:parentIds)")
fun getEventIdsWithParentIds(parentIds: List<Long>): List<Long>
@@ -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<Long>
@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)

View File

@@ -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

View File

@@ -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
}

View File

@@ -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<Long>): 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<String>
newRepetitionExceptions =
newRepetitionExceptions.distinct().toMutableList() as ArrayList<String>
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

View File

@@ -640,28 +640,28 @@
android:visibility="gone" />
<ImageView
android:id="@+id/event_type_image"
android:id="@+id/calendar_image"
android:layout_width="@dimen/smaller_icon_size"
android:layout_height="@dimen/smaller_icon_size"
android:layout_below="@+id/event_caldav_calendar_divider"
android:layout_alignTop="@+id/event_type_holder"
android:layout_alignBottom="@+id/event_type_holder"
android:layout_alignTop="@+id/calendar_holder"
android:layout_alignBottom="@+id/calendar_holder"
android:layout_marginStart="@dimen/normal_margin"
android:padding="@dimen/medium_margin"
android:src="@drawable/ic_category_outline_vector" />
<RelativeLayout
android:id="@+id/event_type_holder"
android:id="@+id/calendar_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/event_caldav_calendar_divider"
android:layout_marginTop="@dimen/medium_margin"
android:layout_marginBottom="@dimen/medium_margin"
android:layout_toEndOf="@+id/event_type_image"
android:layout_toEndOf="@+id/calendar_image"
android:background="?attr/selectableItemBackground">
<org.fossify.commons.views.MyTextView
android:id="@+id/event_type"
android:id="@+id/calendar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/small_margin"
@@ -673,10 +673,10 @@
</RelativeLayout>
<ImageView
android:id="@+id/event_type_divider"
android:id="@+id/calendar_divider"
android:layout_width="match_parent"
android:layout_height="@dimen/divider_height"
android:layout_below="@+id/event_type_holder"
android:layout_below="@+id/calendar_holder"
android:background="@color/divider_grey"
android:importantForAccessibility="no" />
@@ -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"

View File

@@ -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">
<FrameLayout
@@ -96,12 +96,12 @@
android:contentDescription="@string/new_event"
android:src="@drawable/ic_plus_vector"
app:backgroundTint="@color/color_primary"
app:layout_constraintBottom_toTopOf="@+id/quick_event_type_filter"
app:layout_constraintBottom_toTopOf="@+id/quick_calendar_filter"
app:layout_constraintEnd_toEndOf="parent"
app:rippleColor="@color/pressed_item_foreground" />
<org.fossify.commons.views.MyRecyclerView
android:id="@+id/quick_event_type_filter"
android:id="@+id/quick_calendar_filter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"

View File

@@ -6,23 +6,23 @@
android:layout_height="match_parent">
<org.fossify.commons.views.MyAppBarLayout
android:id="@+id/manage_event_types_appbar"
android:id="@+id/manage_calendars_appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/manage_event_types_toolbar"
android:id="@+id/manage_calendars_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/color_primary"
app:menu="@menu/menu_event_types"
app:menu="@menu/menu_calendars"
app:title="@string/manage_event_types"
app:titleTextAppearance="@style/AppTheme.ActionBar.TitleTextStyle" />
</org.fossify.commons.views.MyAppBarLayout>
<org.fossify.commons.views.MyRecyclerView
android:id="@+id/manage_event_types_list"
android:id="@+id/manage_calendars_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"

View File

@@ -90,7 +90,7 @@
<org.fossify.commons.views.PurchaseThankYouItem
android:id="@+id/settings_purchase_thank_you_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
android:layout_height="wrap_content" />
<RelativeLayout
android:id="@+id/settings_use_english_holder"
@@ -131,7 +131,7 @@
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_manage_event_types_holder"
android:id="@+id/settings_manage_calendars_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -146,7 +146,7 @@
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_manage_quick_filter_event_types_holder"
android:id="@+id/settings_manage_quick_filter_calendars_holder"
style="@style/SettingsHolderTextViewOneLinerStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -493,7 +493,7 @@
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_default_event_type_holder"
android:id="@+id/settings_default_calendar_holder"
style="@style/SettingsHolderTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
@@ -506,7 +506,7 @@
android:text="@string/default_event_type" />
<org.fossify.commons.views.MyTextView
android:id="@+id/settings_default_event_type"
android:id="@+id/settings_default_calendar"
style="@style/SettingsTextValueStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/event_type_dialog_holder"
android:id="@+id/calendar_dialog_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<org.fossify.commons.views.MyRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/filter_event_types_list"
android:id="@+id/filter_calendars_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"

View File

@@ -7,19 +7,19 @@
android:paddingTop="@dimen/activity_margin">
<org.fossify.commons.views.MyTextInputLayout
android:id="@+id/import_event_type_hint"
android:id="@+id/import_calendar_hint"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/activity_margin"
android:layout_marginEnd="@dimen/activity_margin"
android:layout_toStartOf="@+id/import_event_type_color"
android:layout_toStartOf="@+id/import_calendar_color"
android:hint="@string/default_event_type"
app:layout_constraintEnd_toStartOf="@+id/import_event_type_color"
app:layout_constraintEnd_toStartOf="@+id/import_calendar_color"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/import_event_type_title"
android:id="@+id/import_calendar_title"
style="@style/UnclickableEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
@@ -27,15 +27,15 @@
</org.fossify.commons.views.MyTextInputLayout>
<ImageView
android:id="@+id/import_event_type_color"
android:id="@+id/import_calendar_color"
android:layout_width="@dimen/color_sample_size"
android:layout_height="@dimen/color_sample_size"
android:layout_marginEnd="@dimen/activity_margin"
android:clickable="false"
android:scaleType="fitCenter"
app:layout_constraintBottom_toBottomOf="@+id/import_event_type_hint"
app:layout_constraintBottom_toBottomOf="@+id/import_calendar_hint"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/import_event_type_hint" />
app:layout_constraintTop_toTopOf="@+id/import_calendar_hint" />
<RelativeLayout
android:id="@+id/import_events_checkbox_holder"
@@ -46,7 +46,7 @@
android:paddingTop="@dimen/normal_margin"
android:paddingEnd="@dimen/activity_margin"
android:paddingBottom="@dimen/normal_margin"
app:layout_constraintTop_toBottomOf="@+id/import_event_type_hint">
app:layout_constraintTop_toBottomOf="@+id/import_calendar_hint">
<org.fossify.commons.views.MyAppCompatCheckbox
android:id="@+id/import_events_checkbox"

View File

@@ -133,7 +133,7 @@
android:importantForAccessibility="no" />
<RelativeLayout
android:id="@+id/manage_event_types_holder"
android:id="@+id/manage_calendars_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"

View File

@@ -27,7 +27,7 @@
android:importantForAccessibility="no" />
<org.fossify.commons.views.MyTextView
android:id="@+id/dialog_manage_event_types"
android:id="@+id/dialog_manage_calendars"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/ripple_background"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/filter_event_type_holder"
android:id="@+id/filter_calendar_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
@@ -10,17 +10,17 @@
android:paddingBottom="@dimen/small_margin">
<org.fossify.commons.views.MyAppCompatCheckbox
android:id="@+id/filter_event_type_checkbox"
android:id="@+id/filter_calendar_checkbox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/medium_margin"
android:layout_toStartOf="@+id/filter_event_type_color"
android:layout_toStartOf="@+id/filter_calendar_color"
android:background="@null"
android:clickable="false"
android:paddingStart="@dimen/small_margin" />
<ImageView
android:id="@+id/filter_event_type_color"
android:id="@+id/filter_calendar_color"
android:layout_width="@dimen/color_sample_size"
android:layout_height="@dimen/color_sample_size"
android:layout_alignParentEnd="true"

View File

@@ -10,24 +10,24 @@
android:foreground="@drawable/selector">
<RelativeLayout
android:id="@+id/event_type_holder"
android:id="@+id/calendar_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:paddingStart="@dimen/activity_margin">
<org.fossify.commons.views.MyTextView
android:id="@+id/event_type_title"
android:id="@+id/calendar_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toStartOf="@+id/event_type_color"
android:layout_toStartOf="@+id/calendar_color"
android:paddingStart="@dimen/medium_margin"
android:paddingEnd="@dimen/medium_margin"
tools:text="Event type" />
<ImageView
android:id="@+id/event_type_color"
android:id="@+id/calendar_color"
android:layout_width="@dimen/color_sample_size"
android:layout_height="@dimen/color_sample_size"
android:layout_centerVertical="true"

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/quick_filter_event_type_holder"
android:id="@+id/quick_filter_calendar_holder"
android:layout_width="match_parent"
android:layout_height="@dimen/quick_filter_height"
android:minWidth="@dimen/quick_filter_min_width">
<org.fossify.commons.views.MyButton
android:id="@+id/quick_filter_event_type"
android:id="@+id/quick_filter_calendar"
android:layout_width="match_parent"
android:layout_height="@dimen/quick_filter_height"
android:layout_alignParentTop="true"
@@ -21,10 +21,10 @@
android:textAllCaps="false" />
<ImageView
android:id="@+id/quick_filter_event_type_color"
android:id="@+id/quick_filter_calendar_color"
android:layout_width="match_parent"
android:layout_height="@dimen/quick_filter_inactive_line_size"
android:layout_above="@id/quick_filter_event_type"
android:layout_above="@id/quick_filter_calendar"
android:layout_alignParentBottom="true"
android:background="@color/color_primary"
android:clickable="false" />

View File

@@ -2,7 +2,7 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/add_event_type"
android:id="@+id/add_calendar"
android:icon="@drawable/ic_plus_vector"
android:title="@string/add_new_type"
app:showAsAction="always" />