commit
56a74d80be
67 changed files with 554 additions and 605 deletions
|
@ -64,12 +64,12 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.simplemobiletools:commons:5.23.10'
|
||||
implementation 'com.simplemobiletools:commons:5.25.22'
|
||||
implementation 'joda-time:joda-time:2.10.1'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
|
||||
|
||||
kapt 'androidx.room:room-compiler:2.2.4'
|
||||
implementation 'androidx.room:room-runtime:2.2.4'
|
||||
annotationProcessor 'androidx.room:room-compiler:2.2.4'
|
||||
kapt 'androidx.room:room-compiler:2.2.5'
|
||||
implementation 'androidx.room:room-runtime:2.2.5'
|
||||
annotationProcessor 'androidx.room:room-compiler:2.2.5'
|
||||
}
|
||||
|
|
|
@ -10,12 +10,19 @@ END:VEVENT
|
|||
BEGIN:VEVENT
|
||||
SUMMARY:Early May Bank Holiday
|
||||
UID:21626542-636f-43d7-8fa9-bad05bb82dca
|
||||
DTSTART;VALUE=DATE:20100503
|
||||
DTEND;VALUE=DATE:20100504
|
||||
DTSTART;VALUE=DATE:20210503
|
||||
DTEND;VALUE=DATE:20210504
|
||||
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=5;BYDAY=1MO
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Early May Bank Holiday
|
||||
UID:21626542-636f-43d7-8fa9-bad05bbsds
|
||||
DTSTART;VALUE=DATE:20200508
|
||||
DTEND;VALUE=DATE:20200509
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Summer Bank Holiday
|
||||
UID:5dac6a63-e519-4ad1-a687-2fd5fccb4656
|
||||
DTSTART;VALUE=DATE:20130826
|
||||
|
@ -47,13 +54,40 @@ UID:ca6af7456b0088abad9a69f9f620f5ac-59@gov.uk
|
|||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTEND;VALUE=DATE:20190420
|
||||
DTSTART;VALUE=DATE:20190419
|
||||
DTEND;VALUE=DATE:20190420
|
||||
SUMMARY:Good Friday
|
||||
UID:ca6af7456b0088abad9a69f9f620f5ac-58@gov.uk
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200410
|
||||
DTEND;VALUE=DATE:20200411
|
||||
SUMMARY:Good Friday
|
||||
UID:ca6af7456b0088abad9a69f9f620f5ac-2020-04-10-GoodFriday@gov.uk
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20200413
|
||||
DTEND;VALUE=DATE:20200414
|
||||
SUMMARY:Easter Monday
|
||||
UID:ca6af7456b0088abad9a69f9f620f5ac-2020-04-13-EasterMonday@gov.uk
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20210402
|
||||
DTEND;VALUE=DATE:20210403
|
||||
SUMMARY:Good Friday
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;VALUE=DATE:20210405
|
||||
DTEND;VALUE=DATE:20210406
|
||||
SUMMARY:Easter Monday
|
||||
UID:ca6af7456b0088abad9a69f9f620f5ac-2021-04-05-EasterMonday@gov.uk
|
||||
STATUS:CONFIRMED
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
SUMMARY:Spring Bank Holiday
|
||||
UID:5dac6a63-e519-4ad1-a687-2fd5fccb4
|
||||
DTSTART;VALUE=DATE:20130527
|
||||
|
|
|
@ -4,13 +4,15 @@ import android.app.Activity
|
|||
import android.app.DatePickerDialog
|
||||
import android.app.TimePickerDialog
|
||||
import android.content.Intent
|
||||
import android.database.Cursor
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.CalendarContract
|
||||
import android.provider.ContactsContract
|
||||
import android.provider.CalendarContract.Attendees
|
||||
import android.provider.ContactsContract.CommonDataKinds
|
||||
import android.provider.ContactsContract.CommonDataKinds.StructuredName
|
||||
import android.provider.ContactsContract.Data
|
||||
import android.text.TextUtils
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.view.Menu
|
||||
|
@ -86,7 +88,6 @@ class EventActivity : SimpleActivity() {
|
|||
private var mStoredEventTypes = ArrayList<EventType>()
|
||||
private var mOriginalTimeZone = DateTimeZone.getDefault().id
|
||||
|
||||
private lateinit var mAttendeePlaceholder: Drawable
|
||||
private lateinit var mEventStartDateTime: DateTime
|
||||
private lateinit var mEventEndDateTime: DateTime
|
||||
private lateinit var mEvent: Event
|
||||
|
@ -103,8 +104,6 @@ class EventActivity : SimpleActivity() {
|
|||
val intent = intent ?: return
|
||||
mDialogTheme = getDialogTheme()
|
||||
mWasContactsPermissionChecked = hasPermission(PERMISSION_READ_CONTACTS)
|
||||
mAttendeePlaceholder = resources.getDrawable(R.drawable.attendee_circular_background)
|
||||
(mAttendeePlaceholder as LayerDrawable).findDrawableByLayerId(R.id.attendee_circular_background).applyColorFilter(config.primaryColor)
|
||||
|
||||
val eventId = intent.getLongExtra(EVENT_ID, 0L)
|
||||
ensureBackgroundThread {
|
||||
|
@ -1259,9 +1258,9 @@ class EventActivity : SimpleActivity() {
|
|||
|
||||
mAttendees.sortWith(compareBy<Attendee>
|
||||
{ it.isMe }.thenBy
|
||||
{ it.status == CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED }.thenBy
|
||||
{ it.status == CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED }.thenBy
|
||||
{ it.status == CalendarContract.Attendees.ATTENDEE_STATUS_TENTATIVE }.thenBy
|
||||
{ it.status == Attendees.ATTENDEE_STATUS_ACCEPTED }.thenBy
|
||||
{ it.status == Attendees.ATTENDEE_STATUS_DECLINED }.thenBy
|
||||
{ it.status == Attendees.ATTENDEE_STATUS_TENTATIVE }.thenBy
|
||||
{ it.status })
|
||||
mAttendees.reverse()
|
||||
|
||||
|
@ -1347,8 +1346,14 @@ class EventActivity : SimpleActivity() {
|
|||
beVisibleIf(attendee.showStatusImage())
|
||||
}
|
||||
|
||||
event_contact_name.text = if (attendee.isMe) getString(R.string.my_status) else attendee.getPublicName()
|
||||
if (attendee.isMe) {
|
||||
(event_contact_name.layoutParams as RelativeLayout.LayoutParams).addRule(RelativeLayout.START_OF, event_contact_me_status.id)
|
||||
}
|
||||
|
||||
val placeholder = BitmapDrawable(resources, context.getContactLetterIcon(event_contact_name.value))
|
||||
event_contact_image.apply {
|
||||
attendee.updateImage(applicationContext, this, mAttendeePlaceholder)
|
||||
attendee.updateImage(applicationContext, this, placeholder)
|
||||
beVisible()
|
||||
}
|
||||
|
||||
|
@ -1357,11 +1362,6 @@ class EventActivity : SimpleActivity() {
|
|||
beGoneIf(attendee.isMe)
|
||||
}
|
||||
|
||||
event_contact_name.text = if (attendee.isMe) getString(R.string.my_status) else attendee.getPublicName()
|
||||
if (attendee.isMe) {
|
||||
(event_contact_name.layoutParams as RelativeLayout.LayoutParams).addRule(RelativeLayout.START_OF, event_contact_me_status.id)
|
||||
}
|
||||
|
||||
if (attendee.isMe) {
|
||||
updateAttendeeMe(this, attendee)
|
||||
}
|
||||
|
@ -1373,9 +1373,9 @@ class EventActivity : SimpleActivity() {
|
|||
if (attendee.isMe) {
|
||||
event_contact_attendee.setOnClickListener {
|
||||
val items = arrayListOf(
|
||||
RadioItem(CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED, getString(R.string.going)),
|
||||
RadioItem(CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED, getString(R.string.not_going)),
|
||||
RadioItem(CalendarContract.Attendees.ATTENDEE_STATUS_TENTATIVE, getString(R.string.maybe_going))
|
||||
RadioItem(Attendees.ATTENDEE_STATUS_ACCEPTED, getString(R.string.going)),
|
||||
RadioItem(Attendees.ATTENDEE_STATUS_DECLINED, getString(R.string.not_going)),
|
||||
RadioItem(Attendees.ATTENDEE_STATUS_TENTATIVE, getString(R.string.maybe_going))
|
||||
)
|
||||
|
||||
RadioGroupDialog(this@EventActivity, items, attendee.status) {
|
||||
|
@ -1389,8 +1389,8 @@ class EventActivity : SimpleActivity() {
|
|||
|
||||
private fun getAttendeeStatusImage(attendee: Attendee): Drawable {
|
||||
return resources.getDrawable(when (attendee.status) {
|
||||
CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED -> R.drawable.ic_check_green
|
||||
CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED -> R.drawable.ic_cross_red
|
||||
Attendees.ATTENDEE_STATUS_ACCEPTED -> R.drawable.ic_check_green
|
||||
Attendees.ATTENDEE_STATUS_DECLINED -> R.drawable.ic_cross_red
|
||||
else -> R.drawable.ic_question_yellow
|
||||
})
|
||||
}
|
||||
|
@ -1398,9 +1398,9 @@ class EventActivity : SimpleActivity() {
|
|||
private fun updateAttendeeMe(holder: RelativeLayout, attendee: Attendee) {
|
||||
holder.apply {
|
||||
event_contact_me_status.text = getString(when (attendee.status) {
|
||||
CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED -> R.string.going
|
||||
CalendarContract.Attendees.ATTENDEE_STATUS_DECLINED -> R.string.not_going
|
||||
CalendarContract.Attendees.ATTENDEE_STATUS_TENTATIVE -> R.string.maybe_going
|
||||
Attendees.ATTENDEE_STATUS_ACCEPTED -> R.string.going
|
||||
Attendees.ATTENDEE_STATUS_DECLINED -> R.string.not_going
|
||||
Attendees.ATTENDEE_STATUS_TENTATIVE -> R.string.maybe_going
|
||||
else -> R.string.invited
|
||||
})
|
||||
|
||||
|
@ -1427,7 +1427,7 @@ class EventActivity : SimpleActivity() {
|
|||
|
||||
val customEmails = mAttendeeAutoCompleteViews.filter { it.isVisible() }.map { it.value }.filter { it.isNotEmpty() }.toMutableList() as ArrayList<String>
|
||||
customEmails.mapTo(attendees) {
|
||||
Attendee(0, "", it, CalendarContract.Attendees.ATTENDEE_STATUS_INVITED, "", false, CalendarContract.Attendees.RELATIONSHIP_NONE)
|
||||
Attendee(0, "", it, Attendees.ATTENDEE_STATUS_INVITED, "", false, Attendees.RELATIONSHIP_NONE)
|
||||
}
|
||||
attendees = attendees.distinctBy { it.email }.toMutableList() as ArrayList<Attendee>
|
||||
|
||||
|
@ -1435,8 +1435,8 @@ class EventActivity : SimpleActivity() {
|
|||
val currentCalendar = calDAVHelper.getCalDAVCalendars("", true).firstOrNull { it.id == mEventCalendarId }
|
||||
mAvailableContacts.firstOrNull { it.email == currentCalendar?.accountName }?.apply {
|
||||
attendees = attendees.filter { it.email != currentCalendar?.accountName }.toMutableList() as ArrayList<Attendee>
|
||||
status = CalendarContract.Attendees.ATTENDEE_STATUS_ACCEPTED
|
||||
relationship = CalendarContract.Attendees.RELATIONSHIP_ORGANIZER
|
||||
status = Attendees.ATTENDEE_STATUS_ACCEPTED
|
||||
relationship = Attendees.RELATIONSHIP_ORGANIZER
|
||||
attendees.add(this)
|
||||
}
|
||||
}
|
||||
|
@ -1446,85 +1446,62 @@ class EventActivity : SimpleActivity() {
|
|||
|
||||
private fun getNames(): List<Attendee> {
|
||||
val contacts = ArrayList<Attendee>()
|
||||
val uri = ContactsContract.Data.CONTENT_URI
|
||||
val uri = Data.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
ContactsContract.Data.CONTACT_ID,
|
||||
ContactsContract.CommonDataKinds.StructuredName.PREFIX,
|
||||
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
|
||||
ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME,
|
||||
ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,
|
||||
ContactsContract.CommonDataKinds.StructuredName.SUFFIX,
|
||||
ContactsContract.CommonDataKinds.StructuredName.PHOTO_THUMBNAIL_URI)
|
||||
Data.CONTACT_ID,
|
||||
StructuredName.PREFIX,
|
||||
StructuredName.GIVEN_NAME,
|
||||
StructuredName.MIDDLE_NAME,
|
||||
StructuredName.FAMILY_NAME,
|
||||
StructuredName.SUFFIX,
|
||||
StructuredName.PHOTO_THUMBNAIL_URI)
|
||||
|
||||
val selection = "${ContactsContract.Data.MIMETYPE} = ?"
|
||||
val selectionArgs = arrayOf(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
|
||||
val selection = "${Data.MIMETYPE} = ?"
|
||||
val selectionArgs = arrayOf(StructuredName.CONTENT_ITEM_TYPE)
|
||||
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val id = cursor.getIntValue(ContactsContract.Data.CONTACT_ID)
|
||||
val prefix = cursor.getStringValue(ContactsContract.CommonDataKinds.StructuredName.PREFIX) ?: ""
|
||||
val firstName = cursor.getStringValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME) ?: ""
|
||||
val middleName = cursor.getStringValue(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME) ?: ""
|
||||
val surname = cursor.getStringValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME) ?: ""
|
||||
val suffix = cursor.getStringValue(ContactsContract.CommonDataKinds.StructuredName.SUFFIX) ?: ""
|
||||
val photoUri = cursor.getStringValue(ContactsContract.CommonDataKinds.StructuredName.PHOTO_THUMBNAIL_URI) ?: ""
|
||||
queryCursor(uri, projection, selection, selectionArgs) { cursor ->
|
||||
val id = cursor.getIntValue(Data.CONTACT_ID)
|
||||
val prefix = cursor.getStringValue(StructuredName.PREFIX) ?: ""
|
||||
val firstName = cursor.getStringValue(StructuredName.GIVEN_NAME) ?: ""
|
||||
val middleName = cursor.getStringValue(StructuredName.MIDDLE_NAME) ?: ""
|
||||
val surname = cursor.getStringValue(StructuredName.FAMILY_NAME) ?: ""
|
||||
val suffix = cursor.getStringValue(StructuredName.SUFFIX) ?: ""
|
||||
val photoUri = cursor.getStringValue(StructuredName.PHOTO_THUMBNAIL_URI) ?: ""
|
||||
|
||||
val names = arrayListOf(prefix, firstName, middleName, surname, suffix).filter { it.trim().isNotEmpty() }
|
||||
val fullName = TextUtils.join("", names)
|
||||
if (fullName.isNotEmpty() || photoUri.isNotEmpty()) {
|
||||
val contact = Attendee(id, fullName, "", CalendarContract.Attendees.ATTENDEE_STATUS_NONE, photoUri, false, CalendarContract.Attendees.RELATIONSHIP_NONE)
|
||||
contacts.add(contact)
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
val names = arrayListOf(prefix, firstName, middleName, surname, suffix).filter { it.trim().isNotEmpty() }
|
||||
val fullName = TextUtils.join(" ", names).trim()
|
||||
if (fullName.isNotEmpty() || photoUri.isNotEmpty()) {
|
||||
val contact = Attendee(id, fullName, "", Attendees.ATTENDEE_STATUS_NONE, photoUri, false, Attendees.RELATIONSHIP_NONE)
|
||||
contacts.add(contact)
|
||||
}
|
||||
} catch (ignored: Exception) {
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
return contacts
|
||||
}
|
||||
|
||||
private fun getEmails(): ArrayList<Attendee> {
|
||||
val contacts = ArrayList<Attendee>()
|
||||
val uri = ContactsContract.CommonDataKinds.Email.CONTENT_URI
|
||||
val uri = CommonDataKinds.Email.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
ContactsContract.Data.CONTACT_ID,
|
||||
ContactsContract.CommonDataKinds.Email.DATA
|
||||
Data.CONTACT_ID,
|
||||
CommonDataKinds.Email.DATA
|
||||
)
|
||||
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = contentResolver.query(uri, projection, null, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val id = cursor.getIntValue(ContactsContract.Data.CONTACT_ID)
|
||||
val email = cursor.getStringValue(ContactsContract.CommonDataKinds.Email.DATA) ?: continue
|
||||
val contact = Attendee(id, "", email, CalendarContract.Attendees.ATTENDEE_STATUS_NONE, "", false, CalendarContract.Attendees.RELATIONSHIP_NONE)
|
||||
contacts.add(contact)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} catch (ignored: Exception) {
|
||||
} finally {
|
||||
cursor?.close()
|
||||
queryCursor(uri, projection) { cursor ->
|
||||
val id = cursor.getIntValue(Data.CONTACT_ID)
|
||||
val email = cursor.getStringValue(CommonDataKinds.Email.DATA) ?: return@queryCursor
|
||||
val contact = Attendee(id, "", email, Attendees.ATTENDEE_STATUS_NONE, "", false, Attendees.RELATIONSHIP_NONE)
|
||||
contacts.add(contact)
|
||||
}
|
||||
|
||||
return contacts
|
||||
}
|
||||
|
||||
private fun updateIconColors() {
|
||||
val textColor = config.textColor
|
||||
event_time_image.applyColorFilter(textColor)
|
||||
event_time_zone_image.applyColorFilter(textColor)
|
||||
event_repetition_image.applyColorFilter(textColor)
|
||||
event_reminder_image.applyColorFilter(textColor)
|
||||
event_type_image.applyColorFilter(textColor)
|
||||
event_caldav_calendar_image.applyColorFilter(textColor)
|
||||
event_show_on_map.applyColorFilter(getAdjustedPrimaryColor())
|
||||
event_reminder_1_type.applyColorFilter(textColor)
|
||||
event_reminder_2_type.applyColorFilter(textColor)
|
||||
event_reminder_3_type.applyColorFilter(textColor)
|
||||
event_attendees_image.applyColorFilter(textColor)
|
||||
val textColor = config.textColor
|
||||
arrayOf(event_time_image, event_time_zone_image, event_repetition_image, event_reminder_image, event_type_image, event_caldav_calendar_image,
|
||||
event_reminder_1_type, event_reminder_2_type, event_reminder_3_type, event_attendees_image).forEach {
|
||||
it.applyColorFilter(textColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,13 +8,12 @@ import android.content.Intent
|
|||
import android.content.pm.ActivityInfo
|
||||
import android.content.pm.ShortcutInfo
|
||||
import android.content.pm.ShortcutManager
|
||||
import android.database.Cursor
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.Icon
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.ContactsContract
|
||||
import android.provider.ContactsContract.*
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.widget.Toast
|
||||
|
@ -32,6 +31,8 @@ import com.simplemobiletools.calendar.pro.extensions.*
|
|||
import com.simplemobiletools.calendar.pro.fragments.*
|
||||
import com.simplemobiletools.calendar.pro.helpers.*
|
||||
import com.simplemobiletools.calendar.pro.helpers.Formatter
|
||||
import com.simplemobiletools.calendar.pro.helpers.IcsExporter.ExportResult
|
||||
import com.simplemobiletools.calendar.pro.helpers.IcsImporter.ImportResult
|
||||
import com.simplemobiletools.calendar.pro.jobs.CalDAVUpdateListener
|
||||
import com.simplemobiletools.calendar.pro.models.Event
|
||||
import com.simplemobiletools.calendar.pro.models.EventType
|
||||
|
@ -144,12 +145,8 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
|||
|
||||
storeStateVariables()
|
||||
updateWidgets()
|
||||
if (config.storedView != EVENTS_LIST_VIEW) {
|
||||
updateTextColors(calendar_coordinator)
|
||||
}
|
||||
search_placeholder.setTextColor(config.textColor)
|
||||
search_placeholder_2.setTextColor(config.textColor)
|
||||
calendar_fab.setColors(config.textColor, getAdjustedPrimaryColor(), config.backgroundColor)
|
||||
updateTextColors(calendar_coordinator)
|
||||
|
||||
search_holder.background = ColorDrawable(config.backgroundColor)
|
||||
checkSwipeRefreshAvailability()
|
||||
checkShortcuts()
|
||||
|
@ -179,7 +176,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
|||
menu.apply {
|
||||
goToTodayButton = findItem(R.id.go_to_today)
|
||||
findItem(R.id.filter).isVisible = mShouldFilterBeVisible
|
||||
findItem(R.id.go_to_today).isVisible = shouldGoToTodayBeVisible || config.storedView == EVENTS_LIST_VIEW
|
||||
findItem(R.id.go_to_today).isVisible = (shouldGoToTodayBeVisible || config.storedView == EVENTS_LIST_VIEW) && !mIsSearchOpen
|
||||
findItem(R.id.go_to_date).isVisible = config.storedView != EVENTS_LIST_VIEW
|
||||
}
|
||||
|
||||
|
@ -188,8 +185,8 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
|||
return true
|
||||
}
|
||||
|
||||
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
|
||||
menu!!.apply {
|
||||
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
|
||||
menu.apply {
|
||||
findItem(R.id.refresh_caldav_calendars).isVisible = config.caldavSync
|
||||
}
|
||||
|
||||
|
@ -279,6 +276,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
|||
search_holder.beVisible()
|
||||
calendar_fab.beGone()
|
||||
searchQueryChanged("")
|
||||
invalidateOptionsMenu()
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -286,6 +284,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
|||
mIsSearchOpen = false
|
||||
search_holder.beGone()
|
||||
calendar_fab.beVisibleIf(currentFragments.last() !is YearFragmentsHolder)
|
||||
invalidateOptionsMenu()
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
@ -488,7 +487,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
|||
|
||||
val result = IcsImporter(this).importEvents(it as String, eventTypeId, 0, false)
|
||||
handleParseResult(result)
|
||||
if (result != IcsImporter.ImportResult.IMPORT_FAIL) {
|
||||
if (result != ImportResult.IMPORT_FAIL) {
|
||||
runOnUiThread {
|
||||
updateViewPager()
|
||||
}
|
||||
|
@ -545,11 +544,11 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleParseResult(result: IcsImporter.ImportResult) {
|
||||
private fun handleParseResult(result: ImportResult) {
|
||||
toast(when (result) {
|
||||
IcsImporter.ImportResult.IMPORT_NOTHING_NEW -> R.string.no_new_items
|
||||
IcsImporter.ImportResult.IMPORT_OK -> R.string.holidays_imported_successfully
|
||||
IcsImporter.ImportResult.IMPORT_PARTIAL -> R.string.importing_some_holidays_failed
|
||||
ImportResult.IMPORT_NOTHING_NEW -> R.string.no_new_items
|
||||
ImportResult.IMPORT_OK -> R.string.holidays_imported_successfully
|
||||
ImportResult.IMPORT_PARTIAL -> R.string.importing_some_holidays_failed
|
||||
else -> R.string.importing_holidays_failed
|
||||
}, Toast.LENGTH_LONG)
|
||||
}
|
||||
|
@ -557,78 +556,69 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
|||
private fun addContactEvents(birthdays: Boolean, reminders: ArrayList<Int>, callback: (Int) -> Unit) {
|
||||
var eventsAdded = 0
|
||||
var eventsFound = 0
|
||||
val uri = ContactsContract.Data.CONTENT_URI
|
||||
val projection = arrayOf(ContactsContract.Contacts.DISPLAY_NAME,
|
||||
ContactsContract.CommonDataKinds.Event.CONTACT_ID,
|
||||
ContactsContract.CommonDataKinds.Event.CONTACT_LAST_UPDATED_TIMESTAMP,
|
||||
ContactsContract.CommonDataKinds.Event.START_DATE)
|
||||
val uri = Data.CONTENT_URI
|
||||
val projection = arrayOf(Contacts.DISPLAY_NAME,
|
||||
CommonDataKinds.Event.CONTACT_ID,
|
||||
CommonDataKinds.Event.CONTACT_LAST_UPDATED_TIMESTAMP,
|
||||
CommonDataKinds.Event.START_DATE)
|
||||
|
||||
val selection = "${ContactsContract.Data.MIMETYPE} = ? AND ${ContactsContract.CommonDataKinds.Event.TYPE} = ?"
|
||||
val type = if (birthdays) ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY else ContactsContract.CommonDataKinds.Event.TYPE_ANNIVERSARY
|
||||
val selectionArgs = arrayOf(ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE, type.toString())
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
val dateFormats = getDateFormats()
|
||||
val existingEvents = if (birthdays) eventsDB.getBirthdays() else eventsDB.getAnniversaries()
|
||||
val importIDs = HashMap<String, Long>()
|
||||
existingEvents.forEach {
|
||||
importIDs[it.importId] = it.startTS
|
||||
}
|
||||
val selection = "${Data.MIMETYPE} = ? AND ${CommonDataKinds.Event.TYPE} = ?"
|
||||
val type = if (birthdays) CommonDataKinds.Event.TYPE_BIRTHDAY else CommonDataKinds.Event.TYPE_ANNIVERSARY
|
||||
val selectionArgs = arrayOf(CommonDataKinds.Event.CONTENT_ITEM_TYPE, type.toString())
|
||||
|
||||
val eventTypeId = if (birthdays) getBirthdaysEventTypeId() else getAnniversariesEventTypeId()
|
||||
val dateFormats = getDateFormats()
|
||||
val existingEvents = if (birthdays) eventsDB.getBirthdays() else eventsDB.getAnniversaries()
|
||||
val importIDs = HashMap<String, Long>()
|
||||
existingEvents.forEach {
|
||||
importIDs[it.importId] = it.startTS
|
||||
}
|
||||
|
||||
do {
|
||||
val contactId = cursor.getIntValue(ContactsContract.CommonDataKinds.Event.CONTACT_ID).toString()
|
||||
val name = cursor.getStringValue(ContactsContract.Contacts.DISPLAY_NAME)
|
||||
val startDate = cursor.getStringValue(ContactsContract.CommonDataKinds.Event.START_DATE)
|
||||
val eventTypeId = if (birthdays) getBirthdaysEventTypeId() else getAnniversariesEventTypeId()
|
||||
|
||||
for (format in dateFormats) {
|
||||
try {
|
||||
val formatter = SimpleDateFormat(format, Locale.getDefault())
|
||||
val date = formatter.parse(startDate)
|
||||
if (date.year < 70) {
|
||||
date.year = 70
|
||||
queryCursor(uri, projection, selection, 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)
|
||||
|
||||
for (format in dateFormats) {
|
||||
try {
|
||||
val formatter = SimpleDateFormat(format, Locale.getDefault())
|
||||
val date = formatter.parse(startDate)
|
||||
if (date.year < 70) {
|
||||
date.year = 70
|
||||
}
|
||||
|
||||
val timestamp = date.time / 1000L
|
||||
val source = if (birthdays) SOURCE_CONTACT_BIRTHDAY else SOURCE_CONTACT_ANNIVERSARY
|
||||
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 = FLAG_ALL_DAY,
|
||||
repeatInterval = YEAR, repeatRule = REPEAT_SAME_DAY, eventType = eventTypeId, source = source, lastUpdated = lastUpdated)
|
||||
|
||||
val importIDsToDelete = ArrayList<String>()
|
||||
for ((key, value) in importIDs) {
|
||||
if (key == contactId && value != timestamp) {
|
||||
val deleted = eventsDB.deleteBirthdayAnniversary(source, key)
|
||||
if (deleted == 1) {
|
||||
importIDsToDelete.add(key)
|
||||
}
|
||||
|
||||
val timestamp = date.time / 1000L
|
||||
val source = if (birthdays) SOURCE_CONTACT_BIRTHDAY else SOURCE_CONTACT_ANNIVERSARY
|
||||
val lastUpdated = cursor.getLongValue(ContactsContract.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 = FLAG_ALL_DAY,
|
||||
repeatInterval = YEAR, repeatRule = REPEAT_SAME_DAY, eventType = eventTypeId, source = source, lastUpdated = lastUpdated)
|
||||
|
||||
val importIDsToDelete = ArrayList<String>()
|
||||
for ((key, value) in importIDs) {
|
||||
if (key == contactId && value != timestamp) {
|
||||
val deleted = eventsDB.deleteBirthdayAnniversary(source, key)
|
||||
if (deleted == 1) {
|
||||
importIDsToDelete.add(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
importIDsToDelete.forEach {
|
||||
importIDs.remove(it)
|
||||
}
|
||||
|
||||
eventsFound++
|
||||
if (!importIDs.containsKey(contactId)) {
|
||||
eventsHelper.insertEvent(event, false, false) {
|
||||
eventsAdded++
|
||||
}
|
||||
}
|
||||
break
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
|
||||
importIDsToDelete.forEach {
|
||||
importIDs.remove(it)
|
||||
}
|
||||
|
||||
eventsFound++
|
||||
if (!importIDs.containsKey(contactId)) {
|
||||
eventsHelper.insertEvent(event, false, false) {
|
||||
eventsAdded++
|
||||
}
|
||||
}
|
||||
break
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
showErrorToast(e)
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
runOnUiThread {
|
||||
|
@ -839,8 +829,8 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
|
|||
} else {
|
||||
IcsExporter().exportEvents(this, outputStream, events, true) {
|
||||
toast(when (it) {
|
||||
IcsExporter.ExportResult.EXPORT_OK -> R.string.exporting_successful
|
||||
IcsExporter.ExportResult.EXPORT_PARTIAL -> R.string.exporting_some_entries_failed
|
||||
ExportResult.EXPORT_OK -> R.string.exporting_successful
|
||||
ExportResult.EXPORT_PARTIAL -> R.string.exporting_some_entries_failed
|
||||
else -> R.string.exporting_failed
|
||||
})
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.simplemobiletools.calendar.pro.activities
|
|||
import android.app.Activity
|
||||
import android.app.TimePickerDialog
|
||||
import android.content.Intent
|
||||
import android.content.res.Resources
|
||||
import android.media.AudioManager
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
|
@ -28,13 +27,11 @@ class SettingsActivity : SimpleActivity() {
|
|||
private val GET_RINGTONE_URI = 1
|
||||
private val PICK_IMPORT_SOURCE_INTENT = 2
|
||||
|
||||
lateinit var res: Resources
|
||||
private var mStoredPrimaryColor = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_settings)
|
||||
res = resources
|
||||
mStoredPrimaryColor = config.primaryColor
|
||||
}
|
||||
|
||||
|
@ -351,10 +348,10 @@ class SettingsActivity : SimpleActivity() {
|
|||
settings_reminder_audio_stream.text = getAudioStreamText()
|
||||
settings_reminder_audio_stream_holder.setOnClickListener {
|
||||
val items = arrayListOf(
|
||||
RadioItem(AudioManager.STREAM_ALARM, res.getString(R.string.alarm_stream)),
|
||||
RadioItem(AudioManager.STREAM_SYSTEM, res.getString(R.string.system_stream)),
|
||||
RadioItem(AudioManager.STREAM_NOTIFICATION, res.getString(R.string.notification_stream)),
|
||||
RadioItem(AudioManager.STREAM_RING, res.getString(R.string.ring_stream)))
|
||||
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_RING, getString(R.string.ring_stream)))
|
||||
|
||||
RadioGroupDialog(this@SettingsActivity, items, config.reminderAudioStream) {
|
||||
config.reminderAudioStream = it as Int
|
||||
|
@ -487,10 +484,10 @@ class SettingsActivity : SimpleActivity() {
|
|||
settings_font_size.text = getFontSizeText()
|
||||
settings_font_size_holder.setOnClickListener {
|
||||
val items = arrayListOf(
|
||||
RadioItem(FONT_SIZE_SMALL, res.getString(R.string.small)),
|
||||
RadioItem(FONT_SIZE_MEDIUM, res.getString(R.string.medium)),
|
||||
RadioItem(FONT_SIZE_LARGE, res.getString(R.string.large)),
|
||||
RadioItem(FONT_SIZE_EXTRA_LARGE, res.getString(R.string.extra_large)))
|
||||
RadioItem(FONT_SIZE_SMALL, getString(R.string.small)),
|
||||
RadioItem(FONT_SIZE_MEDIUM, getString(R.string.medium)),
|
||||
RadioItem(FONT_SIZE_LARGE, getString(R.string.large)),
|
||||
RadioItem(FONT_SIZE_EXTRA_LARGE, getString(R.string.extra_large)))
|
||||
|
||||
RadioGroupDialog(this@SettingsActivity, items, config.fontSize) {
|
||||
config.fontSize = it as Int
|
||||
|
@ -513,12 +510,12 @@ class SettingsActivity : SimpleActivity() {
|
|||
settings_list_widget_view_to_open.text = getDefaultViewText()
|
||||
settings_list_widget_view_to_open_holder.setOnClickListener {
|
||||
val items = arrayListOf(
|
||||
RadioItem(DAILY_VIEW, res.getString(R.string.daily_view)),
|
||||
RadioItem(WEEKLY_VIEW, res.getString(R.string.weekly_view)),
|
||||
RadioItem(MONTHLY_VIEW, res.getString(R.string.monthly_view)),
|
||||
RadioItem(YEARLY_VIEW, res.getString(R.string.yearly_view)),
|
||||
RadioItem(EVENTS_LIST_VIEW, res.getString(R.string.simple_event_list)),
|
||||
RadioItem(LAST_VIEW, res.getString(R.string.last_view)))
|
||||
RadioItem(DAILY_VIEW, getString(R.string.daily_view)),
|
||||
RadioItem(WEEKLY_VIEW, getString(R.string.weekly_view)),
|
||||
RadioItem(MONTHLY_VIEW, getString(R.string.monthly_view)),
|
||||
RadioItem(YEARLY_VIEW, getString(R.string.yearly_view)),
|
||||
RadioItem(EVENTS_LIST_VIEW, getString(R.string.simple_event_list)),
|
||||
RadioItem(LAST_VIEW, getString(R.string.last_view)))
|
||||
|
||||
RadioGroupDialog(this@SettingsActivity, items, config.listWidgetViewToOpen) {
|
||||
config.listWidgetViewToOpen = it as Int
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.simplemobiletools.calendar.pro.adapters
|
||||
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
|
@ -8,19 +8,13 @@ import android.widget.ArrayAdapter
|
|||
import android.widget.Filter
|
||||
import com.simplemobiletools.calendar.pro.R
|
||||
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.pro.extensions.config
|
||||
import com.simplemobiletools.calendar.pro.models.Attendee
|
||||
import com.simplemobiletools.commons.extensions.applyColorFilter
|
||||
import com.simplemobiletools.commons.extensions.getContactLetterIcon
|
||||
import com.simplemobiletools.commons.extensions.normalizeString
|
||||
import kotlinx.android.synthetic.main.item_autocomplete_email_name.view.*
|
||||
|
||||
class AutoCompleteTextViewAdapter(val activity: SimpleActivity, val contacts: ArrayList<Attendee>) : ArrayAdapter<Attendee>(activity, 0, contacts) {
|
||||
var resultList = ArrayList<Attendee>()
|
||||
private var placeholder = activity.resources.getDrawable(R.drawable.attendee_circular_background)
|
||||
|
||||
init {
|
||||
(placeholder as LayerDrawable).findDrawableByLayerId(R.id.attendee_circular_background).applyColorFilter(activity.config.primaryColor)
|
||||
}
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val contact = resultList[position]
|
||||
|
@ -30,6 +24,13 @@ class AutoCompleteTextViewAdapter(val activity: SimpleActivity, val contacts: Ar
|
|||
listItem = LayoutInflater.from(activity).inflate(layout, parent, false)
|
||||
}
|
||||
|
||||
val nameToUse = when {
|
||||
contact.name.isNotEmpty() -> contact.name
|
||||
contact.email.isNotEmpty() -> contact.email
|
||||
else -> "S"
|
||||
}
|
||||
|
||||
val placeholder = BitmapDrawable(activity.resources, context.getContactLetterIcon(nameToUse))
|
||||
listItem!!.apply {
|
||||
tag = contact.name.isNotEmpty()
|
||||
item_autocomplete_name?.text = contact.name
|
||||
|
|
|
@ -9,19 +9,25 @@ import com.simplemobiletools.calendar.pro.R
|
|||
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.pro.extensions.calDAVHelper
|
||||
import com.simplemobiletools.calendar.pro.extensions.config
|
||||
import com.simplemobiletools.commons.extensions.beVisibleIf
|
||||
import com.simplemobiletools.commons.extensions.setupDialogStuff
|
||||
import kotlinx.android.synthetic.main.calendar_item_account.view.*
|
||||
import kotlinx.android.synthetic.main.calendar_item_calendar.view.*
|
||||
import kotlinx.android.synthetic.main.dialog_select_calendars.view.*
|
||||
|
||||
class SelectCalendarsDialog(val activity: SimpleActivity, val callback: () -> Unit) {
|
||||
var prevAccount = ""
|
||||
var dialog: AlertDialog
|
||||
var view = (activity.layoutInflater.inflate(R.layout.dialog_select_calendars, null) as ViewGroup)
|
||||
private var prevAccount = ""
|
||||
private var dialog: AlertDialog
|
||||
private var view = (activity.layoutInflater.inflate(R.layout.dialog_select_calendars, null) as ViewGroup)
|
||||
|
||||
init {
|
||||
val ids = activity.config.getSyncedCalendarIdsAsList()
|
||||
val calendars = activity.calDAVHelper.getCalDAVCalendars("", true)
|
||||
view.apply {
|
||||
dialog_select_calendars_placeholder.beVisibleIf(calendars.isEmpty())
|
||||
dialog_select_calendars_holder.beVisibleIf(calendars.isNotEmpty())
|
||||
}
|
||||
|
||||
val sorted = calendars.sortedWith(compareBy({ it.accountName }, { it.displayName }))
|
||||
sorted.forEach {
|
||||
if (prevAccount != it.accountName) {
|
||||
|
@ -41,8 +47,8 @@ class SelectCalendarsDialog(val activity: SimpleActivity, val callback: () -> Un
|
|||
}
|
||||
|
||||
private fun addCalendarItem(isEvent: Boolean, text: String, tag: Int = 0, shouldCheck: Boolean = false) {
|
||||
val calendarItem = activity.layoutInflater.inflate(if (isEvent) R.layout.calendar_item_calendar else R.layout.calendar_item_account,
|
||||
view.dialog_select_calendars_holder, false)
|
||||
val layout = if (isEvent) R.layout.calendar_item_calendar else R.layout.calendar_item_account
|
||||
val calendarItem = activity.layoutInflater.inflate(layout, view.dialog_select_calendars_holder, false)
|
||||
|
||||
if (isEvent) {
|
||||
calendarItem.calendar_item_calendar_switch.apply {
|
||||
|
|
|
@ -262,7 +262,7 @@ fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content:
|
|||
val builder = NotificationCompat.Builder(this, channelId)
|
||||
.setContentTitle(contentTitle)
|
||||
.setContentText(contentText)
|
||||
.setSmallIcon(R.drawable.ic_calendar)
|
||||
.setSmallIcon(R.drawable.ic_calendar_vector)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setPriority(NotificationCompat.PRIORITY_MAX)
|
||||
.setDefaults(Notification.DEFAULT_LIGHTS)
|
||||
|
|
|
@ -4,9 +4,7 @@ import android.annotation.SuppressLint
|
|||
import android.content.ContentUris
|
||||
import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.provider.CalendarContract
|
||||
import android.provider.CalendarContract.Reminders
|
||||
import android.provider.CalendarContract.*
|
||||
import android.util.SparseIntArray
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
|
@ -22,6 +20,7 @@ import org.joda.time.format.DateTimeFormat
|
|||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
class CalDAVHelper(val context: Context) {
|
||||
private val eventsHelper = context.eventsHelper
|
||||
|
||||
|
@ -58,45 +57,34 @@ class CalDAVHelper(val context: Context) {
|
|||
return calendars
|
||||
}
|
||||
|
||||
val uri = CalendarContract.Calendars.CONTENT_URI
|
||||
val uri = Calendars.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
CalendarContract.Calendars._ID,
|
||||
CalendarContract.Calendars.CALENDAR_DISPLAY_NAME,
|
||||
CalendarContract.Calendars.ACCOUNT_NAME,
|
||||
CalendarContract.Calendars.ACCOUNT_TYPE,
|
||||
CalendarContract.Calendars.OWNER_ACCOUNT,
|
||||
CalendarContract.Calendars.CALENDAR_COLOR,
|
||||
CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL)
|
||||
Calendars._ID,
|
||||
Calendars.CALENDAR_DISPLAY_NAME,
|
||||
Calendars.ACCOUNT_NAME,
|
||||
Calendars.ACCOUNT_TYPE,
|
||||
Calendars.OWNER_ACCOUNT,
|
||||
Calendars.CALENDAR_COLOR,
|
||||
Calendars.CALENDAR_ACCESS_LEVEL)
|
||||
|
||||
val selection = if (ids.trim().isNotEmpty()) "${CalendarContract.Calendars._ID} IN ($ids)" else null
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = context.contentResolver.query(uri, projection, selection, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val id = cursor.getIntValue(CalendarContract.Calendars._ID)
|
||||
val displayName = cursor.getStringValue(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME)
|
||||
val accountName = cursor.getStringValue(CalendarContract.Calendars.ACCOUNT_NAME)
|
||||
val accountType = cursor.getStringValue(CalendarContract.Calendars.ACCOUNT_TYPE)
|
||||
val ownerName = cursor.getStringValue(CalendarContract.Calendars.OWNER_ACCOUNT) ?: ""
|
||||
val color = cursor.getIntValue(CalendarContract.Calendars.CALENDAR_COLOR)
|
||||
val accessLevel = cursor.getIntValue(CalendarContract.Calendars.CALENDAR_ACCESS_LEVEL)
|
||||
val calendar = CalDAVCalendar(id, displayName, accountName, accountType, ownerName, color, accessLevel)
|
||||
calendars.add(calendar)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (showToasts) {
|
||||
context.showErrorToast(e)
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
val selection = if (ids.trim().isNotEmpty()) "${Calendars._ID} IN ($ids)" else null
|
||||
context.queryCursor(uri, projection, selection, showErrors = showToasts) { cursor ->
|
||||
val id = cursor.getIntValue(Calendars._ID)
|
||||
val displayName = cursor.getStringValue(Calendars.CALENDAR_DISPLAY_NAME)
|
||||
val accountName = cursor.getStringValue(Calendars.ACCOUNT_NAME)
|
||||
val accountType = cursor.getStringValue(Calendars.ACCOUNT_TYPE)
|
||||
val ownerName = cursor.getStringValue(Calendars.OWNER_ACCOUNT) ?: ""
|
||||
val color = cursor.getIntValue(Calendars.CALENDAR_COLOR)
|
||||
val accessLevel = cursor.getIntValue(Calendars.CALENDAR_ACCESS_LEVEL)
|
||||
val calendar = CalDAVCalendar(id, displayName, accountName, accountType, ownerName, color, accessLevel)
|
||||
calendars.add(calendar)
|
||||
}
|
||||
|
||||
return calendars
|
||||
}
|
||||
|
||||
fun updateCalDAVCalendar(eventType: EventType) {
|
||||
val uri = CalendarContract.Calendars.CONTENT_URI
|
||||
val uri = Calendars.CONTENT_URI
|
||||
val values = fillCalendarContentValues(eventType)
|
||||
val newUri = ContentUris.withAppendedId(uri, eventType.caldavCalendarId.toLong())
|
||||
try {
|
||||
|
@ -108,26 +96,23 @@ class CalDAVHelper(val context: Context) {
|
|||
private fun fillCalendarContentValues(eventType: EventType): ContentValues {
|
||||
val colorKey = getEventTypeColorKey(eventType)
|
||||
return ContentValues().apply {
|
||||
put(CalendarContract.Calendars.CALENDAR_COLOR_KEY, colorKey)
|
||||
put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, eventType.title)
|
||||
put(Calendars.CALENDAR_COLOR_KEY, colorKey)
|
||||
put(Calendars.CALENDAR_DISPLAY_NAME, eventType.title)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private fun getEventTypeColorKey(eventType: EventType): Int {
|
||||
val uri = CalendarContract.Colors.CONTENT_URI
|
||||
val projection = arrayOf(CalendarContract.Colors.COLOR_KEY)
|
||||
val selection = "${CalendarContract.Colors.COLOR_TYPE} = ? AND ${CalendarContract.Colors.COLOR} = ? AND ${CalendarContract.Colors.ACCOUNT_NAME} = ?"
|
||||
val selectionArgs = arrayOf(CalendarContract.Colors.TYPE_CALENDAR.toString(), eventType.color.toString(), eventType.caldavEmail)
|
||||
val uri = Colors.CONTENT_URI
|
||||
val projection = arrayOf(Colors.COLOR_KEY)
|
||||
val selection = "${Colors.COLOR_TYPE} = ? AND ${Colors.COLOR} = ? AND ${Colors.ACCOUNT_NAME} = ?"
|
||||
val selectionArgs = arrayOf(Colors.TYPE_CALENDAR.toString(), eventType.color.toString(), eventType.caldavEmail)
|
||||
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
return cursor.getStringValue(CalendarContract.Colors.COLOR_KEY).toInt()
|
||||
val cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
cursor?.use {
|
||||
if (cursor.moveToFirst()) {
|
||||
return cursor.getStringValue(Colors.COLOR_KEY).toInt()
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
return -1
|
||||
|
@ -136,23 +121,15 @@ class CalDAVHelper(val context: Context) {
|
|||
@SuppressLint("MissingPermission")
|
||||
fun getAvailableCalDAVCalendarColors(eventType: EventType): ArrayList<Int> {
|
||||
val colors = SparseIntArray()
|
||||
val uri = CalendarContract.Colors.CONTENT_URI
|
||||
val projection = arrayOf(CalendarContract.Colors.COLOR, CalendarContract.Colors.COLOR_KEY)
|
||||
val selection = "${CalendarContract.Colors.COLOR_TYPE} = ? AND ${CalendarContract.Colors.ACCOUNT_NAME} = ?"
|
||||
val selectionArgs = arrayOf(CalendarContract.Colors.TYPE_CALENDAR.toString(), eventType.caldavEmail)
|
||||
val uri = Colors.CONTENT_URI
|
||||
val projection = arrayOf(Colors.COLOR, Colors.COLOR_KEY)
|
||||
val selection = "${Colors.COLOR_TYPE} = ? AND ${Colors.ACCOUNT_NAME} = ?"
|
||||
val selectionArgs = arrayOf(Colors.TYPE_CALENDAR.toString(), eventType.caldavEmail)
|
||||
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val colorKey = cursor.getIntValue(CalendarContract.Colors.COLOR_KEY)
|
||||
val color = cursor.getIntValue(CalendarContract.Colors.COLOR)
|
||||
colors.put(colorKey, color)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
context.queryCursor(uri, projection, selection, selectionArgs) { cursor ->
|
||||
val colorKey = cursor.getIntValue(Colors.COLOR_KEY)
|
||||
val color = cursor.getIntValue(Colors.COLOR)
|
||||
colors.put(colorKey, color)
|
||||
}
|
||||
|
||||
var sortedColors = ArrayList<Int>(colors.size())
|
||||
|
@ -173,151 +150,139 @@ class CalDAVHelper(val context: Context) {
|
|||
importIdsMap[it.importId] = it
|
||||
}
|
||||
|
||||
val uri = CalendarContract.Events.CONTENT_URI
|
||||
val uri = Events.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
CalendarContract.Events._ID,
|
||||
CalendarContract.Events.TITLE,
|
||||
CalendarContract.Events.DESCRIPTION,
|
||||
CalendarContract.Events.DTSTART,
|
||||
CalendarContract.Events.DTEND,
|
||||
CalendarContract.Events.DURATION,
|
||||
CalendarContract.Events.EXDATE,
|
||||
CalendarContract.Events.ALL_DAY,
|
||||
CalendarContract.Events.RRULE,
|
||||
CalendarContract.Events.ORIGINAL_ID,
|
||||
CalendarContract.Events.ORIGINAL_INSTANCE_TIME,
|
||||
CalendarContract.Events.EVENT_LOCATION,
|
||||
CalendarContract.Events.EVENT_TIMEZONE,
|
||||
CalendarContract.Events.CALENDAR_TIME_ZONE,
|
||||
CalendarContract.Events.DELETED)
|
||||
Events._ID,
|
||||
Events.TITLE,
|
||||
Events.DESCRIPTION,
|
||||
Events.DTSTART,
|
||||
Events.DTEND,
|
||||
Events.DURATION,
|
||||
Events.EXDATE,
|
||||
Events.ALL_DAY,
|
||||
Events.RRULE,
|
||||
Events.ORIGINAL_ID,
|
||||
Events.ORIGINAL_INSTANCE_TIME,
|
||||
Events.EVENT_LOCATION,
|
||||
Events.EVENT_TIMEZONE,
|
||||
Events.CALENDAR_TIME_ZONE,
|
||||
Events.DELETED)
|
||||
|
||||
val selection = "${CalendarContract.Events.CALENDAR_ID} = $calendarId"
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = context.contentResolver.query(uri, projection, selection, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val deleted = cursor.getIntValue(CalendarContract.Events.DELETED)
|
||||
if (deleted == 1) {
|
||||
continue
|
||||
}
|
||||
val selection = "${Events.CALENDAR_ID} = $calendarId"
|
||||
context.queryCursor(uri, projection, selection, showErrors = showToasts) { cursor ->
|
||||
val deleted = cursor.getIntValue(Events.DELETED)
|
||||
if (deleted == 1) {
|
||||
return@queryCursor
|
||||
}
|
||||
|
||||
val id = cursor.getLongValue(CalendarContract.Events._ID)
|
||||
val title = cursor.getStringValue(CalendarContract.Events.TITLE) ?: ""
|
||||
val description = cursor.getStringValue(CalendarContract.Events.DESCRIPTION) ?: ""
|
||||
val startTS = cursor.getLongValue(CalendarContract.Events.DTSTART) / 1000L
|
||||
var endTS = cursor.getLongValue(CalendarContract.Events.DTEND) / 1000L
|
||||
val allDay = cursor.getIntValue(CalendarContract.Events.ALL_DAY)
|
||||
val rrule = cursor.getStringValue(CalendarContract.Events.RRULE) ?: ""
|
||||
val location = cursor.getStringValue(CalendarContract.Events.EVENT_LOCATION) ?: ""
|
||||
val originalId = cursor.getStringValue(CalendarContract.Events.ORIGINAL_ID)
|
||||
val originalInstanceTime = cursor.getLongValue(CalendarContract.Events.ORIGINAL_INSTANCE_TIME)
|
||||
val reminders = getCalDAVEventReminders(id)
|
||||
val attendees = Gson().toJson(getCalDAVEventAttendees(id))
|
||||
val id = cursor.getLongValue(Events._ID)
|
||||
val title = cursor.getStringValue(Events.TITLE) ?: ""
|
||||
val description = cursor.getStringValue(Events.DESCRIPTION) ?: ""
|
||||
val startTS = cursor.getLongValue(Events.DTSTART) / 1000L
|
||||
var endTS = cursor.getLongValue(Events.DTEND) / 1000L
|
||||
val allDay = cursor.getIntValue(Events.ALL_DAY)
|
||||
val rrule = cursor.getStringValue(Events.RRULE) ?: ""
|
||||
val location = cursor.getStringValue(Events.EVENT_LOCATION) ?: ""
|
||||
val originalId = cursor.getStringValue(Events.ORIGINAL_ID)
|
||||
val originalInstanceTime = cursor.getLongValue(Events.ORIGINAL_INSTANCE_TIME)
|
||||
val reminders = getCalDAVEventReminders(id)
|
||||
val attendees = Gson().toJson(getCalDAVEventAttendees(id))
|
||||
|
||||
if (endTS == 0L) {
|
||||
val duration = cursor.getStringValue(CalendarContract.Events.DURATION) ?: ""
|
||||
endTS = startTS + Parser().parseDurationSeconds(duration)
|
||||
}
|
||||
if (endTS == 0L) {
|
||||
val duration = cursor.getStringValue(Events.DURATION) ?: ""
|
||||
endTS = startTS + Parser().parseDurationSeconds(duration)
|
||||
}
|
||||
|
||||
val reminder1 = reminders.getOrNull(0)
|
||||
val reminder2 = reminders.getOrNull(1)
|
||||
val reminder3 = reminders.getOrNull(2)
|
||||
val importId = getCalDAVEventImportId(calendarId, id)
|
||||
val eventTimeZone = cursor.getStringValue(CalendarContract.Events.EVENT_TIMEZONE)
|
||||
?: cursor.getStringValue(CalendarContract.Events.CALENDAR_TIME_ZONE) ?: DateTimeZone.getDefault().id
|
||||
val reminder1 = reminders.getOrNull(0)
|
||||
val reminder2 = reminders.getOrNull(1)
|
||||
val reminder3 = reminders.getOrNull(2)
|
||||
val importId = getCalDAVEventImportId(calendarId, id)
|
||||
val eventTimeZone = cursor.getStringValue(Events.EVENT_TIMEZONE)
|
||||
?: cursor.getStringValue(Events.CALENDAR_TIME_ZONE) ?: DateTimeZone.getDefault().id
|
||||
|
||||
val source = "$CALDAV-$calendarId"
|
||||
val repeatRule = Parser().parseRepeatInterval(rrule, startTS)
|
||||
val event = Event(null, startTS, endTS, title, location, description, reminder1?.minutes ?: REMINDER_OFF,
|
||||
reminder2?.minutes ?: REMINDER_OFF, reminder3?.minutes ?: REMINDER_OFF, reminder1?.type
|
||||
?: REMINDER_NOTIFICATION, reminder2?.type ?: REMINDER_NOTIFICATION, reminder3?.type
|
||||
?: REMINDER_NOTIFICATION, repeatRule.repeatInterval, repeatRule.repeatRule,
|
||||
repeatRule.repeatLimit, ArrayList(), attendees, importId, eventTimeZone, allDay, eventTypeId, source = source)
|
||||
val source = "$CALDAV-$calendarId"
|
||||
val repeatRule = Parser().parseRepeatInterval(rrule, startTS)
|
||||
val event = Event(null, startTS, endTS, title, location, description, reminder1?.minutes ?: REMINDER_OFF,
|
||||
reminder2?.minutes ?: REMINDER_OFF, reminder3?.minutes ?: REMINDER_OFF, reminder1?.type
|
||||
?: REMINDER_NOTIFICATION, reminder2?.type ?: REMINDER_NOTIFICATION, reminder3?.type
|
||||
?: REMINDER_NOTIFICATION, repeatRule.repeatInterval, repeatRule.repeatRule,
|
||||
repeatRule.repeatLimit, ArrayList(), attendees, importId, eventTimeZone, allDay, eventTypeId, source = source)
|
||||
|
||||
if (event.getIsAllDay()) {
|
||||
event.startTS = Formatter.getShiftedImportTimestamp(event.startTS)
|
||||
event.endTS = Formatter.getShiftedImportTimestamp(event.endTS)
|
||||
if (event.endTS > event.startTS) {
|
||||
event.endTS -= DAY
|
||||
}
|
||||
}
|
||||
if (event.getIsAllDay()) {
|
||||
event.startTS = Formatter.getShiftedImportTimestamp(event.startTS)
|
||||
event.endTS = Formatter.getShiftedImportTimestamp(event.endTS)
|
||||
if (event.endTS > event.startTS) {
|
||||
event.endTS -= DAY
|
||||
}
|
||||
}
|
||||
|
||||
fetchedEventIds.add(importId)
|
||||
fetchedEventIds.add(importId)
|
||||
|
||||
// if the event is an exception from another events repeat rule, find the original parent event
|
||||
if (originalInstanceTime != 0L) {
|
||||
val parentImportId = "$source-$originalId"
|
||||
val parentEvent = context.eventsDB.getEventWithImportId(parentImportId)
|
||||
val originalDayCode = Formatter.getDayCodeFromTS(originalInstanceTime / 1000L)
|
||||
if (parentEvent != null && !parentEvent.repetitionExceptions.contains(originalDayCode)) {
|
||||
event.parentId = parentEvent.id!!
|
||||
parentEvent.addRepetitionException(originalDayCode)
|
||||
eventsHelper.insertEvent(parentEvent, false, false)
|
||||
// if the event is an exception from another events repeat rule, find the original parent event
|
||||
if (originalInstanceTime != 0L) {
|
||||
val parentImportId = "$source-$originalId"
|
||||
val parentEvent = context.eventsDB.getEventWithImportId(parentImportId)
|
||||
val originalDayCode = Formatter.getDayCodeFromTS(originalInstanceTime / 1000L)
|
||||
if (parentEvent != null && !parentEvent.repetitionExceptions.contains(originalDayCode)) {
|
||||
event.parentId = parentEvent.id!!
|
||||
parentEvent.addRepetitionException(originalDayCode)
|
||||
eventsHelper.insertEvent(parentEvent, false, false)
|
||||
|
||||
event.parentId = parentEvent.id!!
|
||||
event.addRepetitionException(originalDayCode)
|
||||
eventsHelper.insertEvent(event, false, false)
|
||||
continue
|
||||
}
|
||||
}
|
||||
event.parentId = parentEvent.id!!
|
||||
event.addRepetitionException(originalDayCode)
|
||||
eventsHelper.insertEvent(event, false, false)
|
||||
return@queryCursor
|
||||
}
|
||||
}
|
||||
|
||||
// some calendars add repeatable event exceptions with using the "exdate" field, not by creating a child event that is an exception
|
||||
val exdate = cursor.getStringValue(CalendarContract.Events.EXDATE) ?: ""
|
||||
if (exdate.length > 8) {
|
||||
val lines = exdate.split("\n")
|
||||
for (line in lines) {
|
||||
val dates = line.split(",")
|
||||
dates.forEach {
|
||||
if (it.endsWith("Z")) {
|
||||
// convert for example "20190216T230000Z" to "20190217000000" in Slovakia in a weird way
|
||||
val formatter = DateTimeFormat.forPattern("yyyyMMdd'T'HHmmss'Z'")
|
||||
val offset = DateTimeZone.getDefault().getOffset(System.currentTimeMillis())
|
||||
val dt = formatter.parseDateTime(it).plusMillis(offset)
|
||||
val daycode = Formatter.getDayCodeFromDateTime(dt)
|
||||
event.repetitionExceptions.add(daycode)
|
||||
} else {
|
||||
var potentialTS = it.substring(0, 8)
|
||||
if (potentialTS.areDigitsOnly()) {
|
||||
event.repetitionExceptions.add(potentialTS)
|
||||
} else if (it.contains(";")) {
|
||||
potentialTS = it.substringAfter(";").substring(0, 8)
|
||||
event.repetitionExceptions.add(potentialTS)
|
||||
}
|
||||
}
|
||||
// some calendars add repeatable event exceptions with using the "exdate" field, not by creating a child event that is an exception
|
||||
val exdate = cursor.getStringValue(Events.EXDATE) ?: ""
|
||||
if (exdate.length > 8) {
|
||||
val lines = exdate.split("\n")
|
||||
for (line in lines) {
|
||||
val dates = line.split(",")
|
||||
dates.forEach {
|
||||
if (it.endsWith("Z")) {
|
||||
// convert for example "20190216T230000Z" to "20190217000000" in Slovakia in a weird way
|
||||
val formatter = DateTimeFormat.forPattern("yyyyMMdd'T'HHmmss'Z'")
|
||||
val offset = DateTimeZone.getDefault().getOffset(System.currentTimeMillis())
|
||||
val dt = formatter.parseDateTime(it).plusMillis(offset)
|
||||
val daycode = Formatter.getDayCodeFromDateTime(dt)
|
||||
event.repetitionExceptions.add(daycode)
|
||||
} else {
|
||||
var potentialTS = it.substring(0, 8)
|
||||
if (potentialTS.areDigitsOnly()) {
|
||||
event.repetitionExceptions.add(potentialTS)
|
||||
} else if (it.contains(";")) {
|
||||
potentialTS = it.substringAfter(";").substring(0, 8)
|
||||
event.repetitionExceptions.add(potentialTS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (importIdsMap.containsKey(event.importId)) {
|
||||
val existingEvent = importIdsMap[importId]
|
||||
val originalEventId = existingEvent!!.id
|
||||
|
||||
existingEvent.apply {
|
||||
this.id = null
|
||||
color = 0
|
||||
lastUpdated = 0L
|
||||
repetitionExceptions = ArrayList()
|
||||
}
|
||||
|
||||
if (existingEvent.hashCode() != event.hashCode() && title.isNotEmpty()) {
|
||||
event.id = originalEventId
|
||||
eventsHelper.updateEvent(event, false, false)
|
||||
}
|
||||
} else {
|
||||
if (title.isNotEmpty()) {
|
||||
importIdsMap[event.importId] = event
|
||||
eventsHelper.insertEvent(event, false, false)
|
||||
}
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (showToasts) {
|
||||
context.showErrorToast(e)
|
||||
|
||||
if (importIdsMap.containsKey(event.importId)) {
|
||||
val existingEvent = importIdsMap[importId]
|
||||
val originalEventId = existingEvent!!.id
|
||||
|
||||
existingEvent.apply {
|
||||
this.id = null
|
||||
color = 0
|
||||
lastUpdated = 0L
|
||||
repetitionExceptions = ArrayList()
|
||||
}
|
||||
|
||||
if (existingEvent.hashCode() != event.hashCode() && title.isNotEmpty()) {
|
||||
event.id = originalEventId
|
||||
eventsHelper.updateEvent(event, false, false)
|
||||
}
|
||||
} else {
|
||||
if (title.isNotEmpty()) {
|
||||
importIdsMap[event.importId] = event
|
||||
eventsHelper.insertEvent(event, false, false)
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
val eventIdsToDelete = ArrayList<Long>()
|
||||
|
@ -335,7 +300,7 @@ class CalDAVHelper(val context: Context) {
|
|||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun insertCalDAVEvent(event: Event) {
|
||||
val uri = CalendarContract.Events.CONTENT_URI
|
||||
val uri = Events.CONTENT_URI
|
||||
val values = fillEventContentValues(event)
|
||||
val newUri = context.contentResolver.insert(uri, values)
|
||||
|
||||
|
@ -350,7 +315,7 @@ class CalDAVHelper(val context: Context) {
|
|||
}
|
||||
|
||||
fun updateCalDAVEvent(event: Event) {
|
||||
val uri = CalendarContract.Events.CONTENT_URI
|
||||
val uri = Events.CONTENT_URI
|
||||
val values = fillEventContentValues(event)
|
||||
val eventRemoteID = event.getCalDAVEventId()
|
||||
event.importId = getCalDAVEventImportId(event.getCalDAVCalendarId(), eventRemoteID)
|
||||
|
@ -386,15 +351,15 @@ class CalDAVHelper(val context: Context) {
|
|||
val attendees = Gson().fromJson<ArrayList<Attendee>>(event.attendees, object : TypeToken<List<Attendee>>() {}.type) ?: ArrayList()
|
||||
attendees.forEach {
|
||||
val contentValues = ContentValues().apply {
|
||||
put(CalendarContract.Attendees.ATTENDEE_NAME, it.name)
|
||||
put(CalendarContract.Attendees.ATTENDEE_EMAIL, it.email)
|
||||
put(CalendarContract.Attendees.ATTENDEE_STATUS, it.status)
|
||||
put(CalendarContract.Attendees.ATTENDEE_RELATIONSHIP, it.relationship)
|
||||
put(CalendarContract.Attendees.EVENT_ID, event.getCalDAVEventId())
|
||||
put(Attendees.ATTENDEE_NAME, it.name)
|
||||
put(Attendees.ATTENDEE_EMAIL, it.email)
|
||||
put(Attendees.ATTENDEE_STATUS, it.status)
|
||||
put(Attendees.ATTENDEE_RELATIONSHIP, it.relationship)
|
||||
put(Attendees.EVENT_ID, event.getCalDAVEventId())
|
||||
}
|
||||
|
||||
try {
|
||||
context.contentResolver.insert(CalendarContract.Attendees.CONTENT_URI, contentValues)
|
||||
context.contentResolver.insert(Attendees.CONTENT_URI, contentValues)
|
||||
} catch (e: Exception) {
|
||||
context.toast(R.string.unknown_error_occurred)
|
||||
}
|
||||
|
@ -407,31 +372,31 @@ class CalDAVHelper(val context: Context) {
|
|||
|
||||
private fun fillEventContentValues(event: Event): ContentValues {
|
||||
return ContentValues().apply {
|
||||
put(CalendarContract.Events.CALENDAR_ID, event.getCalDAVCalendarId())
|
||||
put(CalendarContract.Events.TITLE, event.title)
|
||||
put(CalendarContract.Events.DESCRIPTION, event.description)
|
||||
put(CalendarContract.Events.DTSTART, event.startTS * 1000L)
|
||||
put(CalendarContract.Events.ALL_DAY, if (event.getIsAllDay()) 1 else 0)
|
||||
put(CalendarContract.Events.EVENT_TIMEZONE, event.getTimeZoneString())
|
||||
put(CalendarContract.Events.EVENT_LOCATION, event.location)
|
||||
put(CalendarContract.Events.STATUS, CalendarContract.Events.STATUS_CONFIRMED)
|
||||
put(Events.CALENDAR_ID, event.getCalDAVCalendarId())
|
||||
put(Events.TITLE, event.title)
|
||||
put(Events.DESCRIPTION, event.description)
|
||||
put(Events.DTSTART, event.startTS * 1000L)
|
||||
put(Events.ALL_DAY, if (event.getIsAllDay()) 1 else 0)
|
||||
put(Events.EVENT_TIMEZONE, event.getTimeZoneString())
|
||||
put(Events.EVENT_LOCATION, event.location)
|
||||
put(Events.STATUS, Events.STATUS_CONFIRMED)
|
||||
|
||||
val repeatRule = Parser().getRepeatCode(event)
|
||||
if (repeatRule.isEmpty()) {
|
||||
putNull(CalendarContract.Events.RRULE)
|
||||
putNull(Events.RRULE)
|
||||
} else {
|
||||
put(CalendarContract.Events.RRULE, repeatRule)
|
||||
put(Events.RRULE, repeatRule)
|
||||
}
|
||||
|
||||
if (event.getIsAllDay() && event.endTS >= event.startTS)
|
||||
event.endTS += DAY
|
||||
|
||||
if (event.repeatInterval > 0) {
|
||||
put(CalendarContract.Events.DURATION, getDurationCode(event))
|
||||
putNull(CalendarContract.Events.DTEND)
|
||||
put(Events.DURATION, getDurationCode(event))
|
||||
putNull(Events.DTEND)
|
||||
} else {
|
||||
put(CalendarContract.Events.DTEND, event.endTS * 1000L)
|
||||
putNull(CalendarContract.Events.DURATION)
|
||||
put(Events.DTEND, event.endTS * 1000L)
|
||||
putNull(Events.DURATION)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -443,9 +408,9 @@ class CalDAVHelper(val context: Context) {
|
|||
}
|
||||
|
||||
private fun clearEventAttendees(event: Event) {
|
||||
val selection = "${CalendarContract.Attendees.EVENT_ID} = ?"
|
||||
val selection = "${Attendees.EVENT_ID} = ?"
|
||||
val selectionArgs = arrayOf(event.getCalDAVEventId().toString())
|
||||
context.contentResolver.delete(CalendarContract.Attendees.CONTENT_URI, selection, selectionArgs)
|
||||
context.contentResolver.delete(Attendees.CONTENT_URI, selection, selectionArgs)
|
||||
}
|
||||
|
||||
private fun getDurationCode(event: Event): String {
|
||||
|
@ -463,7 +428,7 @@ class CalDAVHelper(val context: Context) {
|
|||
}
|
||||
|
||||
fun deleteCalDAVEvent(event: Event) {
|
||||
val uri = CalendarContract.Events.CONTENT_URI
|
||||
val uri = Events.CONTENT_URI
|
||||
val contentUri = ContentUris.withAppendedId(uri, event.getCalDAVEventId())
|
||||
try {
|
||||
context.contentResolver.delete(contentUri, null, null)
|
||||
|
@ -473,7 +438,7 @@ class CalDAVHelper(val context: Context) {
|
|||
}
|
||||
|
||||
fun insertEventRepeatException(event: Event, occurrenceTS: Long) {
|
||||
val uri = CalendarContract.Events.CONTENT_URI
|
||||
val uri = Events.CONTENT_URI
|
||||
val values = fillEventRepeatExceptionValues(event, occurrenceTS)
|
||||
try {
|
||||
context.contentResolver.insert(uri, values)
|
||||
|
@ -485,13 +450,13 @@ class CalDAVHelper(val context: Context) {
|
|||
|
||||
private fun fillEventRepeatExceptionValues(event: Event, occurrenceTS: Long): ContentValues {
|
||||
return ContentValues().apply {
|
||||
put(CalendarContract.Events.CALENDAR_ID, event.getCalDAVCalendarId())
|
||||
put(CalendarContract.Events.DTSTART, occurrenceTS)
|
||||
put(CalendarContract.Events.DTEND, occurrenceTS + (event.endTS - event.startTS))
|
||||
put(CalendarContract.Events.ORIGINAL_ID, event.getCalDAVEventId())
|
||||
put(CalendarContract.Events.EVENT_TIMEZONE, TimeZone.getDefault().id.toString())
|
||||
put(CalendarContract.Events.ORIGINAL_INSTANCE_TIME, occurrenceTS * 1000L)
|
||||
put(CalendarContract.Events.EXDATE, Formatter.getDayCodeFromTS(occurrenceTS))
|
||||
put(Events.CALENDAR_ID, event.getCalDAVCalendarId())
|
||||
put(Events.DTSTART, occurrenceTS)
|
||||
put(Events.DTEND, occurrenceTS + (event.endTS - event.startTS))
|
||||
put(Events.ORIGINAL_ID, event.getCalDAVEventId())
|
||||
put(Events.EVENT_TIMEZONE, TimeZone.getDefault().id.toString())
|
||||
put(Events.ORIGINAL_INSTANCE_TIME, occurrenceTS * 1000L)
|
||||
put(Events.EXDATE, Formatter.getDayCodeFromTS(occurrenceTS))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -502,51 +467,38 @@ class CalDAVHelper(val context: Context) {
|
|||
Reminders.MINUTES,
|
||||
Reminders.METHOD)
|
||||
val selection = "${Reminders.EVENT_ID} = $eventId"
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = context.contentResolver.query(uri, projection, selection, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val minutes = cursor.getIntValue(Reminders.MINUTES)
|
||||
val method = cursor.getIntValue(Reminders.METHOD)
|
||||
if (method == Reminders.METHOD_ALERT || method == Reminders.METHOD_EMAIL) {
|
||||
val type = if (method == Reminders.METHOD_EMAIL) REMINDER_EMAIL else REMINDER_NOTIFICATION
|
||||
val reminder = Reminder(minutes, type)
|
||||
reminders.add(reminder)
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
|
||||
context.queryCursor(uri, projection, selection) { cursor ->
|
||||
val minutes = cursor.getIntValue(Reminders.MINUTES)
|
||||
val method = cursor.getIntValue(Reminders.METHOD)
|
||||
if (method == Reminders.METHOD_ALERT || method == Reminders.METHOD_EMAIL) {
|
||||
val type = if (method == Reminders.METHOD_EMAIL) REMINDER_EMAIL else REMINDER_NOTIFICATION
|
||||
val reminder = Reminder(minutes, type)
|
||||
reminders.add(reminder)
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
}
|
||||
|
||||
return reminders.sortedBy { it.minutes }
|
||||
}
|
||||
|
||||
private fun getCalDAVEventAttendees(eventId: Long): List<Attendee> {
|
||||
val attendees = ArrayList<Attendee>()
|
||||
val uri = CalendarContract.Attendees.CONTENT_URI
|
||||
val uri = Attendees.CONTENT_URI
|
||||
val projection = arrayOf(
|
||||
CalendarContract.Attendees.ATTENDEE_NAME,
|
||||
CalendarContract.Attendees.ATTENDEE_EMAIL,
|
||||
CalendarContract.Attendees.ATTENDEE_STATUS,
|
||||
CalendarContract.Attendees.ATTENDEE_RELATIONSHIP)
|
||||
val selection = "${CalendarContract.Attendees.EVENT_ID} = $eventId"
|
||||
var cursor: Cursor? = null
|
||||
try {
|
||||
cursor = context.contentResolver.query(uri, projection, selection, null, null)
|
||||
if (cursor?.moveToFirst() == true) {
|
||||
do {
|
||||
val name = cursor.getStringValue(CalendarContract.Attendees.ATTENDEE_NAME) ?: ""
|
||||
val email = cursor.getStringValue(CalendarContract.Attendees.ATTENDEE_EMAIL) ?: ""
|
||||
val status = cursor.getIntValue(CalendarContract.Attendees.ATTENDEE_STATUS)
|
||||
val relationship = cursor.getIntValue(CalendarContract.Attendees.ATTENDEE_RELATIONSHIP)
|
||||
val attendee = Attendee(0, name, email, status, "", false, relationship)
|
||||
attendees.add(attendee)
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
} finally {
|
||||
cursor?.close()
|
||||
Attendees.ATTENDEE_NAME,
|
||||
Attendees.ATTENDEE_EMAIL,
|
||||
Attendees.ATTENDEE_STATUS,
|
||||
Attendees.ATTENDEE_RELATIONSHIP)
|
||||
val selection = "${Attendees.EVENT_ID} = $eventId"
|
||||
context.queryCursor(uri, projection, selection) { cursor ->
|
||||
val name = cursor.getStringValue(Attendees.ATTENDEE_NAME) ?: ""
|
||||
val email = cursor.getStringValue(Attendees.ATTENDEE_EMAIL) ?: ""
|
||||
val status = cursor.getIntValue(Attendees.ATTENDEE_STATUS)
|
||||
val relationship = cursor.getIntValue(Attendees.ATTENDEE_RELATIONSHIP)
|
||||
val attendee = Attendee(0, name, email, status, "", false, relationship)
|
||||
attendees.add(attendee)
|
||||
}
|
||||
|
||||
return attendees
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.simplemobiletools.calendar.pro.helpers
|
|||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import androidx.collection.LongSparseArray
|
||||
import com.simplemobiletools.calendar.pro.R
|
||||
import com.simplemobiletools.calendar.pro.extensions.*
|
||||
import com.simplemobiletools.calendar.pro.models.Event
|
||||
import com.simplemobiletools.calendar.pro.models.EventType
|
||||
|
@ -203,6 +202,17 @@ class EventsHelper(val context: Context) {
|
|||
val events = eventsDB.getEventsForSearch(searchQuery)
|
||||
val displayEventTypes = config.displayEventTypes
|
||||
val filteredEvents = events.filter { displayEventTypes.contains(it.eventType.toString()) }
|
||||
|
||||
val eventTypeColors = LongSparseArray<Int>()
|
||||
eventTypesDB.getEventTypes().forEach {
|
||||
eventTypeColors.put(it.id!!, it.color)
|
||||
}
|
||||
|
||||
filteredEvents.forEach {
|
||||
it.updateIsPastEvent()
|
||||
it.color = eventTypeColors.get(it.eventType) ?: config.primaryColor
|
||||
}
|
||||
|
||||
activity.runOnUiThread {
|
||||
callback(text, filteredEvents)
|
||||
}
|
||||
|
@ -261,10 +271,9 @@ class EventsHelper(val context: Context) {
|
|||
eventTypeColors.put(it.id!!, it.color)
|
||||
}
|
||||
|
||||
val primaryColor = context.resources.getColor(R.color.color_primary)
|
||||
events.forEach {
|
||||
it.updateIsPastEvent()
|
||||
it.color = eventTypeColors.get(it.eventType) ?: primaryColor
|
||||
it.color = eventTypeColors.get(it.eventType) ?: config.primaryColor
|
||||
}
|
||||
|
||||
callback(events)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.simplemobiletools.calendar.pro.helpers
|
||||
|
||||
import android.widget.Toast
|
||||
import com.simplemobiletools.calendar.pro.R
|
||||
import com.simplemobiletools.calendar.pro.activities.SimpleActivity
|
||||
import com.simplemobiletools.calendar.pro.extensions.eventsDB
|
||||
|
@ -110,7 +109,7 @@ class IcsImporter(val activity: SimpleActivity) {
|
|||
curImportId = line.substring(UID.length).trim()
|
||||
} else if (line.startsWith(RRULE)) {
|
||||
curRrule = line.substring(RRULE.length)
|
||||
// some RRULRs need to know the events start datetime. If it's yet unknown, postpone RRULE parsing
|
||||
// some RRULEs need to know the events start datetime. If it's yet unknown, postpone RRULE parsing
|
||||
if (curStart != -1L) {
|
||||
parseRepeatRule()
|
||||
}
|
||||
|
@ -227,7 +226,7 @@ class IcsImporter(val activity: SimpleActivity) {
|
|||
|
||||
eventsHelper.insertEvents(eventsToInsert, true)
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e, Toast.LENGTH_LONG)
|
||||
activity.showErrorToast(e)
|
||||
eventsFailed++
|
||||
}
|
||||
|
||||
|
@ -248,7 +247,9 @@ class IcsImporter(val activity: SimpleActivity) {
|
|||
return try {
|
||||
if (fullString.startsWith(';')) {
|
||||
val value = fullString.substring(fullString.lastIndexOf(':') + 1).replace(" ", "")
|
||||
if (!value.contains("T")) {
|
||||
if (value.isEmpty()) {
|
||||
return 0
|
||||
} else if (!value.contains("T")) {
|
||||
curFlags = curFlags or FLAG_ALL_DAY
|
||||
}
|
||||
|
||||
|
@ -257,7 +258,7 @@ class IcsImporter(val activity: SimpleActivity) {
|
|||
Parser().parseDateTimeValue(fullString.substring(1))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
activity.showErrorToast(e, Toast.LENGTH_LONG)
|
||||
activity.showErrorToast(e)
|
||||
eventsFailed++
|
||||
-1
|
||||
}
|
||||
|
|
|
@ -40,6 +40,12 @@ class Parser {
|
|||
if (interval.areDigitsOnly() && interval.toInt() % 7 == 0) {
|
||||
val dateTime = Formatter.getDateTimeFromTS(startTS)
|
||||
repeatRule = Math.pow(2.0, (dateTime.dayOfWeek - 1).toDouble()).toInt()
|
||||
} else if (fullString.contains("BYDAY")) {
|
||||
// some services use weekly repetition for repeating on specific week days, some use daily
|
||||
// make these produce the same result
|
||||
// RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR
|
||||
// RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR
|
||||
repeatInterval = WEEK_SECONDS
|
||||
}
|
||||
}
|
||||
} else if (key == COUNT) {
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 698 B |
Binary file not shown.
Before Width: | Height: | Size: 782 B |
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.5 KiB |
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/attendee_circular_background">
|
||||
<shape android:shape="oval">
|
||||
<solid android:color="@color/color_primary"/>
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:bottom="@dimen/medium_margin"
|
||||
android:drawable="@drawable/ic_person_vector"
|
||||
android:left="@dimen/medium_margin"
|
||||
android:right="@dimen/medium_margin"
|
||||
android:top="@dimen/medium_margin"/>
|
||||
|
||||
</layer-list>
|
9
app/src/main/res/drawable/ic_calendar_vector.xml
Normal file
9
app/src/main/res/drawable/ic_calendar_vector.xml
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,9 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M16,11c1.66,0 2.99,-1.34 2.99,-3S17.66,5 16,5c-1.66,0 -3,1.34 -3,3s1.34,3 3,3zM8,11c1.66,0 2.99,-1.34 2.99,-3S9.66,5 8,5C6.34,5 5,6.34 5,8s1.34,3 3,3zM8,13c-2.33,0 -7,1.17 -7,3.5L1,19h14v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5zM16,13c-0.29,0 -0.62,0.02 -0.97,0.05 1.16,0.84 1.97,1.97 1.97,3.45L17,19h6v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5z"/>
|
||||
</vector>
|
|
@ -408,7 +408,7 @@
|
|||
android:layout_marginStart="@dimen/normal_margin"
|
||||
android:layout_marginTop="@dimen/small_margin"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_group_vector"/>
|
||||
android:src="@drawable/ic_people_vector"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/event_attendees_holder"
|
||||
|
@ -435,9 +435,10 @@
|
|||
android:layout_below="@+id/event_attendees_divider"
|
||||
android:layout_alignTop="@+id/event_caldav_calendar_holder"
|
||||
android:layout_alignBottom="@+id/event_caldav_calendar_holder"
|
||||
android:layout_alignEnd="@+id/event_time_image"
|
||||
android:layout_marginStart="@dimen/normal_margin"
|
||||
android:padding="@dimen/medium_margin"
|
||||
android:src="@drawable/ic_calendar"
|
||||
android:src="@drawable/ic_calendar_vector"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<RelativeLayout
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/calendar_coordinator"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -14,7 +13,7 @@
|
|||
<FrameLayout
|
||||
android:id="@+id/fragments_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
|
@ -27,7 +26,7 @@
|
|||
android:contentDescription="@string/new_event"
|
||||
android:src="@drawable/ic_plus_vector"
|
||||
app:backgroundTint="@color/color_primary"
|
||||
app:rippleColor="@color/pressed_item_foreground"/>
|
||||
app:rippleColor="@color/pressed_item_foreground" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/search_holder"
|
||||
|
@ -43,11 +42,13 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="@dimen/activity_margin"
|
||||
android:alpha="0.8"
|
||||
android:gravity="center"
|
||||
android:paddingStart="@dimen/activity_margin"
|
||||
android:paddingEnd="@dimen/activity_margin"
|
||||
android:text="@string/no_items_found"
|
||||
android:textSize="@dimen/bigger_text_size"/>
|
||||
android:textSize="@dimen/bigger_text_size"
|
||||
android:textStyle="italic" />
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/search_placeholder_2"
|
||||
|
@ -55,13 +56,15 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/search_placeholder"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:alpha="0.8"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:paddingStart="@dimen/activity_margin"
|
||||
android:paddingEnd="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/medium_margin"
|
||||
android:paddingEnd="@dimen/activity_margin"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:text="@string/type_2_characters"
|
||||
android:textSize="@dimen/bigger_text_size"/>
|
||||
android:textSize="@dimen/bigger_text_size"
|
||||
android:textStyle="italic" />
|
||||
|
||||
<com.simplemobiletools.commons.views.MyRecyclerView
|
||||
android:id="@+id/search_results_list"
|
||||
|
@ -69,7 +72,7 @@
|
|||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:scrollbars="vertical"
|
||||
app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager"/>
|
||||
app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager" />
|
||||
|
||||
</RelativeLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
|
@ -120,13 +120,6 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/reminders_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/reminders_label"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -298,13 +291,6 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/caldav_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/caldav_label"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -381,13 +367,6 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/new_events_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/new_events_label"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -612,13 +591,6 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/weekly_view_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/weekly_view_label"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -661,13 +633,6 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/monthly_view_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/monthly_view_label"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -721,13 +686,6 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/events_list_view_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/simple_event_list_label"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -791,13 +749,6 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/widgets_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/widgets_label"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -890,13 +841,6 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/events_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/events_label"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -971,13 +915,6 @@
|
|||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/migrating_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:background="@color/divider_grey"
|
||||
android:importantForAccessibility="no"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/migrating_label"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<com.simplemobiletools.commons.views.MyTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/calendar_item_account"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/activity_margin"
|
||||
android:layout_marginLeft="@dimen/big_margin"
|
||||
android:layout_marginStart="@dimen/big_margin"
|
||||
android:layout_marginTop="@dimen/activity_margin"
|
||||
android:alpha="0.6"
|
||||
android:layout_marginBottom="@dimen/activity_margin"
|
||||
android:alpha="0.8"
|
||||
android:textAllCaps="true"
|
||||
android:textColor="@color/divider_grey"
|
||||
android:textSize="@dimen/small_text_size"
|
||||
tools:text="Account"/>
|
||||
android:textSize="@dimen/normal_text_size"
|
||||
tools:text="Account" />
|
||||
|
|
|
@ -1,16 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/dialog_select_calendars_scrollview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/activity_margin">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/dialog_select_calendars_holder"
|
||||
<RelativeLayout
|
||||
android:id="@+id/dialog_select_calendars_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
</LinearLayout>
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/dialog_select_calendars_placeholder"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:alpha="0.8"
|
||||
android:text="@string/no_synchronized_calendars"
|
||||
android:textStyle="italic" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/dialog_select_calendars_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</RelativeLayout>
|
||||
</ScrollView>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/calendar_events_list_holder"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -15,7 +14,7 @@
|
|||
android:paddingTop="@dimen/medium_margin"
|
||||
android:scrollbars="vertical"
|
||||
android:visibility="gone"
|
||||
app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager"/>
|
||||
app:layoutManager="com.simplemobiletools.commons.views.MyLinearLayoutManager" />
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/calendar_empty_list_placeholder"
|
||||
|
@ -23,24 +22,26 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="@dimen/activity_margin"
|
||||
android:alpha="0.8"
|
||||
android:gravity="center"
|
||||
android:paddingStart="@dimen/activity_margin"
|
||||
android:paddingEnd="@dimen/activity_margin"
|
||||
android:text="@string/no_upcoming_events"
|
||||
android:textSize="@dimen/bigger_text_size"
|
||||
android:visibility="gone"/>
|
||||
android:textStyle="italic"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/calendar_empty_list_placeholder_2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/calendar_empty_list_placeholder"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:paddingTop="@dimen/medium_margin"
|
||||
android:padding="@dimen/activity_margin"
|
||||
android:text="@string/create_new_event"
|
||||
android:textSize="@dimen/bigger_text_size"
|
||||
android:visibility="gone"/>
|
||||
android:visibility="gone" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingEnd="@dimen/medium_margin"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/bigger_text_size"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/item_autocomplete_holder"
|
||||
|
@ -17,7 +16,7 @@
|
|||
android:layout_height="@dimen/avatar_size"
|
||||
android:layout_margin="@dimen/tiny_margin"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_autocomplete_name"
|
||||
|
@ -26,6 +25,7 @@
|
|||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingEnd="@dimen/medium_margin"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/bigger_text_size"
|
||||
app:layout_constraintBottom_toTopOf="@+id/item_autocomplete_email"
|
||||
|
@ -33,7 +33,7 @@
|
|||
app:layout_constraintStart_toEndOf="@+id/item_autocomplete_image"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Simple Mobile"/>
|
||||
tools:text="Simple Mobile" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/item_autocomplete_email"
|
||||
|
@ -45,12 +45,13 @@
|
|||
android:lines="1"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="@dimen/medium_margin"
|
||||
android:paddingEnd="@dimen/medium_margin"
|
||||
android:singleLine="true"
|
||||
android:textSize="@dimen/normal_text_size"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/item_autocomplete_image"
|
||||
app:layout_constraintTop_toBottomOf="@+id/item_autocomplete_name"
|
||||
tools:text="hello@simplemobiletools.com"/>
|
||||
tools:text="hello@simplemobiletools.com" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">اختر لون مختلف (يمكن تطبيقه محليا فقط)</string>
|
||||
<string name="insufficient_permissions">لا يمكنك التعديل في هذا التقويم</string>
|
||||
<string name="caldav_event_not_found">مناسبة غير موجودة. من فضلك فَعّل مُزامنة CalDAV للحصول على التقويم المناسب من الإعدادات.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Select a different color (might be applied locally only)</string>
|
||||
<string name="insufficient_permissions">You are not allowed to write in the selected calendar</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -211,6 +211,7 @@
|
|||
<string name="select_a_different_caldav_color">একটি আলাদা রঙ সিলেক্ট করুন(কেবল স্থানীয়ভাবে প্রয়োগ করা যেতে পারে)</string>
|
||||
<string name="insufficient_permissions">আপনার সিলেক্টেড ক্যালেন্ডারে লেখার অনুমতি নেই</string>
|
||||
<string name="caldav_event_not_found">ইভেন্ট পাওয়া যায় নি। অ্যাপ্লিকেশন সেটিংসে উপযুক্ত ক্যালেন্ডারের জন্য দয়া করে CalDAV সিঙ্ক সক্ষম করুন।</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Select a different color (might be applied locally only)</string>
|
||||
<string name="insufficient_permissions">You are not allowed to write in the selected calendar</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Zvolit jinou barvu (možná bude nastavena pouze lokálně)</string>
|
||||
<string name="insufficient_permissions">Nemáte oprávnění pro zápis do zvoleného kalendáře</string>
|
||||
<string name="caldav_event_not_found">Událost nenalezena. Prosím, povolte CalDAV synchronizaci příslušného kalendáře v nastavení aplikace.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Vælg en anden farve (den kan være tilføjet lokalt)</string>
|
||||
<string name="insufficient_permissions">Du har ikke tilladelse til at skrive i den valgte kalender</string>
|
||||
<string name="caldav_event_not_found">Begivenheden blev ikke fundet. Aktiver CalDAV-synkronisering med den relevante kalender i app-indstillingerne.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Wähle eine andere Farbe (wird möglicherweise nur lokal angewendet)</string>
|
||||
<string name="insufficient_permissions">Dir fehlt die Berechtigung zum Ändern des gewählten Kalenders</string>
|
||||
<string name="caldav_event_not_found">Der Termin wurde nicht gefunden. Bitte aktiviere die Synchronisierung für den Kalender in den Einstellungen.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Επιλέξτε διαφορετικό χρώμα (μπορεί να εφαρμοστεί μόνο τοπικά)</string>
|
||||
<string name="insufficient_permissions">Δεν επιτρέπεται η εγγραφή στο επιλεγμένο ημερολόγιο</string>
|
||||
<string name="caldav_event_not_found">Δεν βρέθηκε Εκδήλωση. Παρακαλώ ενεργοποιήστε το συγχρονισμό CalDAV του Ημερολογίου από τις ρυθμίσεις της εφαρμογής.</string>
|
||||
<string name="no_synchronized_calendars">Δεν μπόρεσαν να βρεθούν συγχρονισμένα Ημερολόγια</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Seleccionar un color diferente (localmente)</string>
|
||||
<string name="insufficient_permissions">No tiene permiso para modificar el calendario</string>
|
||||
<string name="caldav_event_not_found">Evento no encontrado. Habilite la sincronización de CalDAV para los calendarios en la configuración.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -208,6 +208,7 @@
|
|||
<string name="select_a_different_caldav_color">Sélectionnez une couleur différente (peut être appliqué localement uniquement)</string>
|
||||
<string name="insufficient_permissions">Vous n\’êtes pas autorisé à écrire dans l\’agenda sélectionné</string>
|
||||
<string name="caldav_event_not_found">Événement introuvable. Veuillez activer la synchronisation CalDAV pour le calendrier approprié dans les paramètres de l’application.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Escolle un color diferente (pode que só se aplique localmente)</string>
|
||||
<string name="insufficient_permissions">Non tes permiso para escribir no calendario seleccionado</string>
|
||||
<string name="caldav_event_not_found">Evento non atopado. Activa a sincronización de CalDAV para o calendario apropiado nos axustes da aplicación.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">בחירת צבע שונה (ייתכן שיישמר מקומית בלבד)</string>
|
||||
<string name="insufficient_permissions">לא קיימת הרשאת כתיבה ליומנים הנבחרים</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Select a different color (might be applied locally only)</string>
|
||||
<string name="insufficient_permissions">You are not allowed to write in the selected calendar</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Odaberite drugu boju (može se primijeniti samo lokalno)</string>
|
||||
<string name="insufficient_permissions">Nije vam dopušteno pisati u odabranom kalendaru</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Select a different color (might be applied locally only)</string>
|
||||
<string name="insufficient_permissions">You are not allowed to write in the selected calendar</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Pilih warna yang berbeda (mungkin hanya diterapkan secara lokal)</string>
|
||||
<string name="insufficient_permissions">Anda tidak diizinkan untuk membuat/mengubah acara pada kalender yang dipilih</string>
|
||||
<string name="caldav_event_not_found">Acara tidak ditemukan. Silakan aktifkan sinkronisasi CalDAV untuk kalender terkait di dalam pengaturan aplikasi.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Pilih warna yang berbeda (mungkin hanya diterapkan secara lokal)</string>
|
||||
<string name="insufficient_permissions">Anda tidak diizinkan untuk membuat/mengubah acara pada kalender yang dipilih</string>
|
||||
<string name="caldav_event_not_found">Acara tidak ditemukan. Silakan aktifkan sinkronisasi CalDAV untuk kalender terkait di dalam pengaturan aplikasi.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Seleziona un colore differente (potrebbe essere applicato solamente in locale)</string>
|
||||
<string name="insufficient_permissions">Non si hanno i permessi per scrivere nel calendario selezionato</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">בחירת צבע שונה (ייתכן שיישמר מקומית בלבד)</string>
|
||||
<string name="insufficient_permissions">לא קיימת הרשאת כתיבה ליומנים הנבחרים</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Select a different color (might be applied locally only)</string>
|
||||
<string name="insufficient_permissions">You are not allowed to write in the selected calendar</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">다른 색상을 선택해주세요(로컬에만 적용 가능)</string>
|
||||
<string name="insufficient_permissions">선택한 캘린더에 작성할 수 없습니다.</string>
|
||||
<string name="caldav_event_not_found">일정을 찾을 수 없습니다. 앱 설정에서 해당 캘린더에 대해 CalDAV 동기화를 활성화해주세요.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Select a different color (might be applied locally only)</string>
|
||||
<string name="insufficient_permissions">You are not allowed to write in the selected calendar</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Izvēlieties citu krāsu (var tikt izmantota tikai lokāli)</string>
|
||||
<string name="insufficient_permissions">Jums izvēlētajā kalendārā rakstīt nav ļauts</string>
|
||||
<string name="caldav_event_not_found">Notikums nav atrasts. Lūdzu, lietotnes iestatījumos iespējojiet CalDAV sinhronizāciju attiecīgajam kalendāram.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Select a different color (might be applied locally only)</string>
|
||||
<string name="insufficient_permissions">You are not allowed to write in the selected calendar</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Kies een andere kleur (mogelijk alleen voor dit apparaat)</string>
|
||||
<string name="insufficient_permissions">Kan geen wijzigingen aanbrengen in deze agenda</string>
|
||||
<string name="caldav_event_not_found">Afspraak niet gevonden. Schakel via Instellingen de CalDAV-synchronisatie in voor deze agenda.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Select a different color (might be applied locally only)</string>
|
||||
<string name="insufficient_permissions">You are not allowed to write in the selected calendar</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Select a different color (might be applied locally only)</string>
|
||||
<string name="insufficient_permissions">You are not allowed to write in the selected calendar</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Select a different color (might be applied locally only)</string>
|
||||
<string name="insufficient_permissions">You are not allowed to write in the selected calendar</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Selecione uma cor diferente (pode ser aplicada apenas localmente)</string>
|
||||
<string name="insufficient_permissions">Não tem permissão para escrever no calendário selecionado</string>
|
||||
<string name="caldav_event_not_found">Evento não encontrado. Ative a sincronização CalDAV para os calendários apropriados nas definições.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Выберите другой цвет (применяется локально)</string>
|
||||
<string name="insufficient_permissions">Запись в выбранный календарь запрещена</string>
|
||||
<string name="caldav_event_not_found">Событие не найдено. Пожалуйста, включите CalDAV-синхронизацию для соответствующего календаря в настройках приложения.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Zvoliť inú farbu (možno bude aplikovaná iba lokálne)</string>
|
||||
<string name="insufficient_permissions">Nemáte dostatočné oprávnenie na písanie do zvoleného kalendára</string>
|
||||
<string name="caldav_event_not_found">Udalosť nebola nájdená. Prosím povoľte CalDAV synchronizáciu príslušného kalendára v nastaveniach aplikácie.</string>
|
||||
<string name="no_synchronized_calendars">Nenašli sa žiadne synchronizovateľné kalendáre</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Välj en annan färg (tillämpas kanske bara lokalt)</string>
|
||||
<string name="insufficient_permissions">Du har inte behörighet att redigera den valda kalendern</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Farklı bir renk seçin (yalnızca yerel olarak uygulanabilir)</string>
|
||||
<string name="insufficient_permissions">Seçili takvime yazmanıza izin verilmiyor</string>
|
||||
<string name="caldav_event_not_found">Etkinlik bulunamadı. Lütfen uygulama ayarlarından uygun takvim için CalDAV senkronizasyonunu etkinleştirin.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Обрати інший колір (можна застосувати лише локально)</string>
|
||||
<string name="insufficient_permissions">Ви не можете редагувати обраний календар</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">选择不同的颜色 (只能被添加于本机端)</string>
|
||||
<string name="insufficient_permissions">你不被允许对选择的行事历写入</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">選擇不同的顏色 (只能被添加於本機端)</string>
|
||||
<string name="insufficient_permissions">你不被允許對選擇的行事曆寫入</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">選擇不同的顏色 (只能被添加於本機端)</string>
|
||||
<string name="insufficient_permissions">你不被允許對選擇的行事曆寫入</string>
|
||||
<string name="caldav_event_not_found">未發現活動。請在程式設定中為合適的行事曆啟用CalDAV同步。</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -207,6 +207,7 @@
|
|||
<string name="select_a_different_caldav_color">Select a different color (might be applied locally only)</string>
|
||||
<string name="insufficient_permissions">You are not allowed to write in the selected calendar</string>
|
||||
<string name="caldav_event_not_found">Event not found. Please enable CalDAV sync for the appropriate calendar in the app settings.</string>
|
||||
<string name="no_synchronized_calendars">No synchronizable calendars have been found</string>
|
||||
|
||||
<!-- alternative versions for some languages, use the same translations if you are not sure what this means -->
|
||||
<!-- used in repetition, like "Every last Sunday" -->
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.70'
|
||||
ext.kotlin_version = '1.3.72'
|
||||
|
||||
repositories {
|
||||
google()
|
||||
|
@ -10,7 +10,7 @@ buildscript {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.6.1'
|
||||
classpath 'com.android.tools.build:gradle:3.6.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "de.timfreiheit.resourceplaceholders:placeholders:0.3"
|
||||
|
||||
|
|
BIN
fastlane/metadata/android/en-US/images/app_icon.png
Normal file
BIN
fastlane/metadata/android/en-US/images/app_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
Loading…
Reference in a new issue