diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f8a6abfa..9cfbdb1c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,38 @@ Changelog ========== +Version 4.1.0 *(2018-06-13)* +---------------------------- + + * Make reminders on Android Oreo more reliable + * Allow deleting only future occurrences of repeating events + * Fixed some visual glitches at the weekly view + * Multiple CalDAV event related improvements + +Version 4.0.4 *(2018-05-27)* +---------------------------- + + * Make sure the alarm rings properly at DND mode + * Improved the UK holidays and added Singapore ones + * Make Event list items more compact when possible + * Couple other UX improvements and bugfixes + +Version 4.0.3 *(2018-05-15)* +---------------------------- + + * Fixing some widget related crashes + +Version 4.0.2 *(2018-05-14)* +---------------------------- + + * Make sure we store the proper calendar ID at events + +Version 4.0.1 *(2018-05-14)* +---------------------------- + + * Fix app not opening at clicking widgets + * Couple stability improvements + Version 4.0.0 *(2018-05-10)* ---------------------------- diff --git a/app/build.gradle b/app/build.gradle index dd3b75d15..2da62d372 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "com.simplemobiletools.calendar" minSdkVersion 16 targetSdkVersion 27 - versionCode 119 - versionName "4.0.0" + versionCode 124 + versionName "4.1.0" multiDexEnabled true setProperty("archivesBaseName", "calendar") } @@ -46,7 +46,7 @@ ext { } dependencies { - implementation 'com.simplemobiletools:commons:4.0.3' + implementation 'com.simplemobiletools:commons:4.1.7' implementation 'joda-time:joda-time:2.9.9' implementation 'com.facebook.stetho:stetho:1.5.0' implementation 'com.android.support:multidex:1.0.3' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f065f2fac..eb59ce5f7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -29,6 +29,8 @@ android:launchMode="singleTask" android:theme="@style/SplashTheme"> + + diff --git a/app/src/main/assets/singapore.ics b/app/src/main/assets/singapore.ics new file mode 100755 index 000000000..cddb5cb13 --- /dev/null +++ b/app/src/main/assets/singapore.ics @@ -0,0 +1,125 @@ +BEGIN:VCALENDAR +BEGIN:VEVENT +DTSTART;VALUE=DATE:20181225 +DTEND;VALUE=DATE:20181226 +UID:20181225-christmas-day@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Christmas Day +RRULE:FREQ=YEARLY;INTERVAL=1 +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20181106 +DTEND;VALUE=DATE:20181107 +UID:20181106-deepavali@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Deepavali +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20191027 +DTEND;VALUE=DATE:20191028 +UID:20191027-deepavali@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Deepavali +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20180822 +DTEND;VALUE=DATE:20180823 +UID:20180822-hari-raya-haji@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Hari Raya Haji +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20190811 +DTEND;VALUE=DATE:20190812 +UID:20190811-hari-raya-haji@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Hari Raya Haji +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20180809 +DTEND;VALUE=DATE:20180810 +UID:20180809-national-day@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:National Day +RRULE:FREQ=YEARLY;INTERVAL=1 +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20180615 +DTEND;VALUE=DATE:20180616 +UID:20180615-hari-raya-puasa@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Hari Raya Puasa +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20190605 +DTEND;VALUE=DATE:20190606 +UID:20190605-hari-raya-puasa@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Hari Raya Puasa +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20180529 +DTEND;VALUE=DATE:20180530 +UID:20180529-vesak-day@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Vesak Day +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20190519 +DTEND;VALUE=DATE:20190520 +UID:20190519-vesak-day@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Vesak Day +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20180501 +DTEND;VALUE=DATE:20180502 +UID:20180501-labour-day@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Labour Day +RRULE:FREQ=YEARLY;INTERVAL=1 +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20180330 +DTEND;VALUE=DATE:20180331 +UID:20180330-good-friday@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Good Friday +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20190419 +DTEND;VALUE=DATE:20190420 +UID:20190419-good-friday@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Good Friday +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20180217 +DTEND;VALUE=DATE:20180218 +UID:20180217-chinese-new-year@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Chinese New Year +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20180216 +DTEND;VALUE=DATE:20180217 +UID:20180216-chinese-new-year@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Chinese New Year +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20180101 +DTEND;VALUE=DATE:20180102 +UID:20180101-new-years-day@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:New Year's Day +RRULE:FREQ=YEARLY;INTERVAL=1 +END:VEVENT +BEGIN:VEVENT +DTSTART;VALUE=DATE:20190205 +DTEND;VALUE=DATE:20190206 +UID:20190205-chinese-new-year@www.mom.gov.sg +STATUS:CONFIRMED +SUMMARY:Chinese New Year +END:VEVENT +END:VCALENDAR diff --git a/app/src/main/assets/unitedkingdom.ics b/app/src/main/assets/unitedkingdom.ics index c66c6a5e2..eabf3e227 100755 --- a/app/src/main/assets/unitedkingdom.ics +++ b/app/src/main/assets/unitedkingdom.ics @@ -8,52 +8,20 @@ STATUS:CONFIRMED RRULE:FREQ=YEARLY;INTERVAL=1 END:VEVENT BEGIN:VEVENT -SUMMARY:St. David's Day -UID:a08053d8-530b-4025-8edf-81c88d05fe84 -DTSTART;VALUE=DATE:20100301 -DTEND;VALUE=DATE:20100302 -STATUS:CONFIRMED -RRULE:FREQ=YEARLY;INTERVAL=1 -END:VEVENT -BEGIN:VEVENT -SUMMARY:St. George's Day -UID:b58227e2-7f9d-4571-afa5-0ae93192d10e -DTSTART;VALUE=DATE:20100423 -DTEND;VALUE=DATE:20100424 -STATUS:CONFIRMED -RRULE:FREQ=YEARLY;INTERVAL=1 -END:VEVENT -BEGIN:VEVENT SUMMARY:Early May Bank Holiday UID:21626542-636f-43d7-8fa9-bad05bb82dca DTSTART;VALUE=DATE:20100503 DTEND;VALUE=DATE:20100504 +RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=5;BYDAY=1MO STATUS:CONFIRMED -RRULE:FREQ=YEARLY;INTERVAL=1 END:VEVENT BEGIN:VEVENT SUMMARY:Summer Bank Holiday UID:5dac6a63-e519-4ad1-a687-2fd5fccb4656 DTSTART;VALUE=DATE:20100802 DTEND;VALUE=DATE:20100803 +RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=8;BYDAY=-1MO STATUS:CONFIRMED -RRULE:FREQ=YEARLY;INTERVAL=1 -END:VEVENT -BEGIN:VEVENT -SUMMARY:Summer Bank Holiday -UID:3d37b115-f0fa-4456-98c9-3b18cfffb47d -DTSTART;VALUE=DATE:20170828 -DTEND;VALUE=DATE:20170829 -STATUS:CONFIRMED -RRULE:FREQ=YEARLY;INTERVAL=1 -END:VEVENT -BEGIN:VEVENT -SUMMARY:BST ends -UID:8eb163f3-6d42-494e-9e7c-747619cf965f -DTSTART:20101031T000000Z -DTEND:20101031T020000Z -STATUS:CONFIRMED -RRULE:FREQ=YEARLY;INTERVAL=1 END:VEVENT BEGIN:VEVENT SUMMARY:Christmas Day @@ -71,4 +39,26 @@ DTEND;VALUE=DATE:20101227 STATUS:CONFIRMED RRULE:FREQ=YEARLY;INTERVAL=1 END:VEVENT +BEGIN:VEVENT +DTEND;VALUE=DATE:20190423 +DTSTART;VALUE=DATE:20190422 +SUMMARY:Easter Monday +UID:ca6af7456b0088abad9a69f9f620f5ac-59@gov.uk +STATUS:CONFIRMED +END:VEVENT +BEGIN:VEVENT +DTEND;VALUE=DATE:20190420 +DTSTART;VALUE=DATE:20190419 +SUMMARY:Good Friday +UID:ca6af7456b0088abad9a69f9f620f5ac-58@gov.uk +STATUS:CONFIRMED +END:VEVENT +BEGIN:VEVENT +SUMMARY:Spring Bank Holiday +UID:5dac6a63-e519-4ad1-a687-2fd5fccb4 +DTSTART;VALUE=DATE:20100802 +DTEND;VALUE=DATE:20100803 +RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=5;BYDAY=-1MO +STATUS:CONFIRMED +END:VEVENT END:VCALENDAR diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/activities/EventActivity.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/activities/EventActivity.kt index 85ead0720..42eef0c2d 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/activities/EventActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/activities/EventActivity.kt @@ -528,6 +528,7 @@ class EventActivity : SimpleActivity() { event_caldav_calendar_email.beGoneIf(currentCalendar == null) if (currentCalendar == null) { + mEventCalendarId = STORED_LOCALLY_ONLY val mediumMargin = resources.getDimension(R.dimen.medium_margin).toInt() event_caldav_calendar_name.apply { text = getString(R.string.store_locally_only) @@ -561,11 +562,11 @@ class EventActivity : SimpleActivity() { } private fun deleteEvent() { - DeleteEventDialog(this, arrayListOf(mEvent.id)) { - if (it) { - dbHelper.deleteEvents(arrayOf(mEvent.id.toString()), true) - } else { - dbHelper.addEventRepeatException(mEvent.id, mEventOccurrenceTS, true) + DeleteEventDialog(this, arrayListOf(mEvent.id), mEvent.repeatInterval > 0) { + when (it) { + DELETE_SELECTED_OCCURRENCE -> dbHelper.addEventRepeatException(mEvent.id, mEventOccurrenceTS, true) + DELETE_FUTURE_OCCURRENCES -> dbHelper.addEventRepeatLimit(mEvent.id, mEventOccurrenceTS) + DELETE_ALL_OCCURRENCES -> dbHelper.deleteEvents(arrayOf(mEvent.id.toString()), true) } finish() } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/activities/MainActivity.kt index 75374d906..dda371dd2 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/activities/MainActivity.kt @@ -470,8 +470,9 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { try { val formatter = SimpleDateFormat(format, Locale.getDefault()) val date = formatter.parse(startDate) - if (date.year < 70) + if (date.year < 70) { date.year = 70 + } val timestamp = (date.time / 1000).toInt() val source = if (birthdays) SOURCE_CONTACT_BIRTHDAY else SOURCE_CONTACT_ANNIVERSARY @@ -788,6 +789,7 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { put("Россия", "russia.ics") put("România", "romania.ics") put("Schweiz", "switzerland.ics") + put("Singapore", "singapore.ics") put("Srbija", "serbia.ics") put("Slovenija", "slovenia.ics") put("Slovensko", "slovakia.ics") diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/activities/SettingsActivity.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/activities/SettingsActivity.kt index c0ff3ce5f..df198de7a 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/activities/SettingsActivity.kt @@ -8,7 +8,10 @@ import android.text.TextUtils import com.simplemobiletools.calendar.R import com.simplemobiletools.calendar.dialogs.SelectCalendarsDialog import com.simplemobiletools.calendar.extensions.* -import com.simplemobiletools.calendar.helpers.* +import com.simplemobiletools.calendar.helpers.CalDAVHandler +import com.simplemobiletools.calendar.helpers.FONT_SIZE_LARGE +import com.simplemobiletools.calendar.helpers.FONT_SIZE_MEDIUM +import com.simplemobiletools.calendar.helpers.FONT_SIZE_SMALL import com.simplemobiletools.calendar.models.EventType import com.simplemobiletools.commons.dialogs.ConfirmationDialog import com.simplemobiletools.commons.dialogs.CustomIntervalPickerDialog @@ -16,6 +19,7 @@ import com.simplemobiletools.commons.dialogs.RadioGroupDialog import com.simplemobiletools.commons.dialogs.SelectAlarmSoundDialog import com.simplemobiletools.commons.extensions.* import com.simplemobiletools.commons.helpers.ALARM_SOUND_TYPE_NOTIFICATION +import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS import com.simplemobiletools.commons.helpers.PERMISSION_READ_CALENDAR import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_CALENDAR import com.simplemobiletools.commons.models.AlarmSound @@ -85,7 +89,7 @@ class SettingsActivity : SimpleActivity() { private fun setupSectionColors() { val adjustedPrimaryColor = getAdjustedPrimaryColor() - arrayListOf(reminders_label, caldav_label, weekly_view_label, monthly_view_label, simple_event_list_label, simple_font_size_label, events_label).forEach { + arrayListOf(reminders_label, caldav_label, weekly_view_label, monthly_view_label, simple_event_list_label, widgets_label, events_label).forEach { it.setTextColor(adjustedPrimaryColor) } } @@ -291,7 +295,7 @@ class SettingsActivity : SimpleActivity() { settings_reminder_sound.text = config.reminderSoundTitle settings_reminder_sound_holder.setOnClickListener { - SelectAlarmSoundDialog(this, config.reminderSoundUri, AudioManager.STREAM_NOTIFICATION, GET_RINGTONE_URI, ALARM_SOUND_TYPE_NOTIFICATION, false, + SelectAlarmSoundDialog(this, config.reminderSoundUri, AudioManager.STREAM_ALARM, GET_RINGTONE_URI, ALARM_SOUND_TYPE_NOTIFICATION, false, onAlarmPicked = { if (it != null) { updateReminderSound(it) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/activities/WidgetListConfigureActivity.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/activities/WidgetListConfigureActivity.kt index 547b066c3..253d290d4 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/activities/WidgetListConfigureActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/activities/WidgetListConfigureActivity.kt @@ -11,7 +11,6 @@ import com.simplemobiletools.calendar.adapters.EventListAdapter import com.simplemobiletools.calendar.extensions.config import com.simplemobiletools.calendar.extensions.seconds import com.simplemobiletools.calendar.helpers.Formatter -import com.simplemobiletools.calendar.helpers.IS_CUSTOMIZING_COLORS import com.simplemobiletools.calendar.helpers.MyWidgetListProvider import com.simplemobiletools.calendar.models.ListEvent import com.simplemobiletools.calendar.models.ListItem @@ -19,6 +18,7 @@ import com.simplemobiletools.calendar.models.ListSection import com.simplemobiletools.commons.dialogs.ColorPickerDialog import com.simplemobiletools.commons.extensions.adjustAlpha import com.simplemobiletools.commons.extensions.setFillWithStroke +import com.simplemobiletools.commons.helpers.IS_CUSTOMIZING_COLORS import kotlinx.android.synthetic.main.widget_config_list.* import org.joda.time.DateTime import java.util.* @@ -32,7 +32,6 @@ class WidgetListConfigureActivity : SimpleActivity() { private var mTextColor = 0 private var mEventsAdapter: EventListAdapter? = null - private var mIsCustomizingColors = false public override fun onCreate(savedInstanceState: Bundle?) { useDynamicTheme = false @@ -41,10 +40,10 @@ class WidgetListConfigureActivity : SimpleActivity() { setContentView(R.layout.widget_config_list) initVariables() - mIsCustomizingColors = intent.extras?.getBoolean(IS_CUSTOMIZING_COLORS) ?: false + val isCustomizingColors = intent.extras?.getBoolean(IS_CUSTOMIZING_COLORS) ?: false mWidgetId = intent.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID) ?: AppWidgetManager.INVALID_APPWIDGET_ID - if (mWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID && !mIsCustomizingColors) { + if (mWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID && !isCustomizingColors) { finish() } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/adapters/DayEventsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/adapters/DayEventsAdapter.kt index 97e005249..aa949f3ab 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/adapters/DayEventsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/adapters/DayEventsAdapter.kt @@ -8,6 +8,7 @@ import com.simplemobiletools.calendar.activities.SimpleActivity import com.simplemobiletools.calendar.dialogs.DeleteEventDialog import com.simplemobiletools.calendar.extensions.config import com.simplemobiletools.calendar.extensions.dbHelper +import com.simplemobiletools.calendar.extensions.handleEventDeleting import com.simplemobiletools.calendar.extensions.shareEvents import com.simplemobiletools.calendar.helpers.Formatter import com.simplemobiletools.calendar.helpers.LOW_ALPHA @@ -111,26 +112,23 @@ class DayEventsAdapter(activity: SimpleActivity, val events: ArrayList, r private fun askConfirmDelete() { val eventIds = ArrayList(selectedPositions.size) val timestamps = ArrayList(selectedPositions.size) + val eventsToDelete = ArrayList(selectedPositions.size) selectedPositions.forEach { - eventIds.add(events[it].id) - timestamps.add(events[it].startTS) + val event = events[it] + eventsToDelete.add(event) + eventIds.add(event.id) + timestamps.add(event.startTS) } - DeleteEventDialog(activity, eventIds) { - val eventsToDelete = ArrayList(selectedPositions.size) - selectedPositions.sortedDescending().forEach { - eventsToDelete.add(events[it]) - } + val hasRepeatableEvent = eventsToDelete.any { it.repeatInterval > 0 } + DeleteEventDialog(activity, eventIds, hasRepeatableEvent) { events.removeAll(eventsToDelete) - if (it) { - val eventIDs = Array(eventIds.size, { i -> (eventIds[i].toString()) }) - activity.dbHelper.deleteEvents(eventIDs, true) - } else { - eventIds.forEachIndexed { index, value -> - activity.dbHelper.addEventRepeatException(value, timestamps[index], true) - } - } + val nonRepeatingEventIDs = eventsToDelete.filter { it.repeatInterval == 0 }.map { it.id.toString() }.toTypedArray() + activity.dbHelper.deleteEvents(nonRepeatingEventIDs, true) + + val repeatingEventIDs = eventsToDelete.filter { it.repeatInterval != 0 }.map { it.id } + activity.handleEventDeleting(repeatingEventIDs, timestamps, it) removeSelectedItems() } } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/adapters/EventListAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/adapters/EventListAdapter.kt index 026459b96..c9aa81d38 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/adapters/EventListAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/adapters/EventListAdapter.kt @@ -8,6 +8,7 @@ import com.simplemobiletools.calendar.activities.SimpleActivity import com.simplemobiletools.calendar.dialogs.DeleteEventDialog import com.simplemobiletools.calendar.extensions.config import com.simplemobiletools.calendar.extensions.dbHelper +import com.simplemobiletools.calendar.extensions.handleEventDeleting import com.simplemobiletools.calendar.extensions.shareEvents import com.simplemobiletools.calendar.helpers.Formatter import com.simplemobiletools.calendar.helpers.LOW_ALPHA @@ -29,11 +30,12 @@ class EventListAdapter(activity: SimpleActivity, var listItems: ArrayList Unit) : MyRecyclerViewAdapter(activity, recyclerView, null, itemClick) { private val ITEM_EVENT = 0 - private val ITEM_HEADER = 1 + private val ITEM_EVENT_SIMPLE = 1 + private val ITEM_HEADER = 2 private val topDivider = resources.getDrawable(R.drawable.divider_width) private val allDayString = resources.getString(R.string.all_day) - private val replaceDescriptionWithLocation = activity.config.replaceDescription + private val replaceDescription = activity.config.replaceDescription private val dimPastEvents = activity.config.dimPastEvents private val now = getNowSeconds() private var use24HourFormat = activity.config.use24HourFormat @@ -76,7 +78,11 @@ class EventListAdapter(activity: SimpleActivity, var listItems: ArrayList R.layout.event_list_item + ITEM_EVENT_SIMPLE -> R.layout.event_list_item_simple + else -> R.layout.event_list_section + } return createViewHolder(layoutId, parent) } @@ -94,7 +100,17 @@ class EventListAdapter(activity: SimpleActivity, var listItems: ArrayList(selectedPositions.size) val timestamps = ArrayList(selectedPositions.size) + val eventsToDelete = ArrayList(selectedPositions.size) - selectedPositions.forEach { + selectedPositions.sortedDescending().forEach { val item = listItems[it] if (item is ListEvent) { eventIds.add(item.id) timestamps.add(item.startTS) + eventsToDelete.add(item) } } - DeleteEventDialog(activity, eventIds) { - val listItemsToDelete = ArrayList(selectedPositions.size) - selectedPositions.sortedDescending().forEach { - val listItem = listItems[it] - listItemsToDelete.add(listItem) - } - listItems.removeAll(listItemsToDelete) + val hasRepeatableEvent = eventsToDelete.any { it.isRepeatable } + DeleteEventDialog(activity, eventIds, hasRepeatableEvent) { + listItems.removeAll(eventsToDelete) - if (it) { - val eventIDs = Array(eventIds.size, { i -> (eventIds[i].toString()) }) - activity.dbHelper.deleteEvents(eventIDs, true) - } else { - eventIds.forEachIndexed { index, value -> - activity.dbHelper.addEventRepeatException(value, timestamps[index], true) - } - } + val nonRepeatingEventIDs = eventsToDelete.filter { !it.isRepeatable }.map { it.id.toString() }.toTypedArray() + activity.dbHelper.deleteEvents(nonRepeatingEventIDs, true) + + val repeatingEventIDs = eventsToDelete.filter { it.isRepeatable }.map { it.id } + activity.handleEventDeleting(repeatingEventIDs, timestamps, it) listener?.refreshItems() finishActMode() } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/adapters/EventListWidgetAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/adapters/EventListWidgetAdapter.kt index 3da3eeceb..3984eb07a 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/adapters/EventListWidgetAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/adapters/EventListWidgetAdapter.kt @@ -40,8 +40,11 @@ class EventListWidgetAdapter(val context: Context) : RemoteViewsService.RemoteVi val remoteView: RemoteViews if (type == ITEM_EVENT) { - remoteView = RemoteViews(context.packageName, R.layout.event_list_item_widget) - setupListEvent(remoteView, events[position] as ListEvent) + val event = events[position] as ListEvent + val detailField = if (replaceDescription) event.location else event.description + val layout = if (event.startTS == event.endTS && detailField.isEmpty()) R.layout.event_list_item_widget_simple else R.layout.event_list_item_widget + remoteView = RemoteViews(context.packageName, layout) + setupListEvent(remoteView, event) } else { remoteView = RemoteViews(context.packageName, R.layout.event_list_section_widget) setupListSection(remoteView, events[position] as ListSection) @@ -122,7 +125,7 @@ class EventListWidgetAdapter(val context: Context) : RemoteViewsService.RemoteVi override fun getLoadingView() = null - override fun getViewTypeCount() = 2 + override fun getViewTypeCount() = 3 override fun onCreate() {} @@ -150,7 +153,7 @@ class EventListWidgetAdapter(val context: Context) : RemoteViewsService.RemoteVi prevCode = code } - val listEvent = ListEvent(it.id, it.startTS, it.endTS, it.title, it.description, it.getIsAllDay(), it.color, it.location, it.isPastEvent) + val listEvent = ListEvent(it.id, it.startTS, it.endTS, it.title, it.description, it.getIsAllDay(), it.color, it.location, it.isPastEvent, it.repeatInterval > 0) listItems.add(listEvent) } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/dialogs/DeleteEventDialog.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/dialogs/DeleteEventDialog.kt index 5c88fc256..dde07d6d7 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/dialogs/DeleteEventDialog.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/dialogs/DeleteEventDialog.kt @@ -4,21 +4,23 @@ import android.app.Activity import android.support.v7.app.AlertDialog import android.view.ViewGroup import com.simplemobiletools.calendar.R -import com.simplemobiletools.calendar.extensions.dbHelper +import com.simplemobiletools.calendar.helpers.DELETE_ALL_OCCURRENCES +import com.simplemobiletools.calendar.helpers.DELETE_FUTURE_OCCURRENCES +import com.simplemobiletools.calendar.helpers.DELETE_SELECTED_OCCURRENCE import com.simplemobiletools.commons.extensions.beVisibleIf import com.simplemobiletools.commons.extensions.setupDialogStuff import kotlinx.android.synthetic.main.dialog_delete_event.view.* -class DeleteEventDialog(val activity: Activity, eventIds: List, val callback: (allOccurrences: Boolean) -> Unit) { +class DeleteEventDialog(val activity: Activity, eventIds: List, hasRepeatableEvent: Boolean, val callback: (deleteRule: Int) -> Unit) { val dialog: AlertDialog? init { - val events = activity.dbHelper.getEventsWithIds(eventIds) - val hasRepeatableEvent = events.any { it.repeatInterval > 0 } - val view = activity.layoutInflater.inflate(R.layout.dialog_delete_event, null).apply { delete_event_repeat_description.beVisibleIf(hasRepeatableEvent) delete_event_radio_view.beVisibleIf(hasRepeatableEvent) + if (!hasRepeatableEvent) { + delete_event_radio_view.check(R.id.delete_event_all) + } if (eventIds.size > 1) { delete_event_repeat_description.text = resources.getString(R.string.selection_contains_repetition) @@ -26,16 +28,20 @@ class DeleteEventDialog(val activity: Activity, eventIds: List, val callbac } dialog = AlertDialog.Builder(activity) - .setPositiveButton(R.string.yes, { dialog, which -> dialogConfirmed(view as ViewGroup, hasRepeatableEvent) }) + .setPositiveButton(R.string.yes, { dialog, which -> dialogConfirmed(view as ViewGroup) }) .setNegativeButton(R.string.no, null) .create().apply { activity.setupDialogStuff(view, this) } } - private fun dialogConfirmed(view: ViewGroup, hasRepeatableEvent: Boolean) { - val deleteAllOccurrences = !hasRepeatableEvent || view.delete_event_radio_view.checkedRadioButtonId == R.id.delete_event_all + private fun dialogConfirmed(view: ViewGroup) { + val deleteRule = when (view.delete_event_radio_view.checkedRadioButtonId) { + R.id.delete_event_all -> DELETE_ALL_OCCURRENCES + R.id.delete_event_future -> DELETE_FUTURE_OCCURRENCES + else -> DELETE_SELECTED_OCCURRENCE + } dialog?.dismiss() - callback(deleteAllOccurrences) + callback(deleteRule) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/extensions/Context.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/extensions/Context.kt index fe939f06d..4a0319c3c 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/extensions/Context.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/extensions/Context.kt @@ -154,10 +154,10 @@ fun Context.notifyEvent(originalEvent: Event) { if (event.repeatInterval != 0 && event.startTS - event.reminder1Minutes * 60 < currentSeconds) { val events = dbHelper.getRepeatableEventsFor(currentSeconds - DAY_SECONDS, currentSeconds + YEAR_SECONDS, event.id) for (currEvent in events) { - event = currEvent - if (event.startTS - event.reminder1Minutes * 60 > currentSeconds) { + if (currEvent.startTS - currEvent.reminder1Minutes * 60 > currentSeconds) { break } + event = currEvent } } @@ -189,12 +189,18 @@ fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content: grantReadUriPermission(soundUri) } - val channelId = "my_reminder_channel_$soundUri" + // create a new channel for every new sound uri as the new Android Oreo notification system is fundamentally broken + if (soundUri != config.lastSoundUri) { + config.lastReminderChannel = System.currentTimeMillis() + config.lastSoundUri = soundUri + } + + val channelId = "simple_calendar_${config.lastReminderChannel}" if (isOreoPlus()) { val audioAttributes = AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_NOTIFICATION) + .setUsage(AudioAttributes.USAGE_ALARM) .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .setLegacyStreamType(AudioManager.STREAM_NOTIFICATION) + .setLegacyStreamType(AudioManager.STREAM_ALARM) .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED) .build() @@ -202,6 +208,7 @@ fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content: val name = resources.getString(R.string.event_reminders) val importance = NotificationManager.IMPORTANCE_HIGH NotificationChannel(channelId, name, importance).apply { + setBypassDnd(true) enableLights(true) lightColor = event.color enableVibration(false) @@ -213,15 +220,15 @@ fun Context.getNotification(pendingIntent: PendingIntent, event: Event, content: val contentTitle = if (publicVersion) resources.getString(R.string.app_name) else event.title val contentText = if (publicVersion) resources.getString(R.string.public_event_notification_text) else content - val builder = NotificationCompat.Builder(this) + val builder = NotificationCompat.Builder(this, channelId) .setContentTitle(contentTitle) .setContentText(contentText) .setSmallIcon(R.drawable.ic_calendar) .setContentIntent(pendingIntent) - .setPriority(Notification.PRIORITY_HIGH) + .setPriority(NotificationCompat.PRIORITY_MAX) .setDefaults(Notification.DEFAULT_LIGHTS) .setAutoCancel(true) - .setSound(Uri.parse(soundUri), AudioManager.STREAM_NOTIFICATION) + .setSound(Uri.parse(soundUri), AudioManager.STREAM_ALARM) .setChannelId(channelId) .addAction(R.drawable.ic_snooze, getString(R.string.snooze), getSnoozePendingIntent(this, event)) @@ -304,7 +311,7 @@ fun Context.scheduleCalDAVSync(activate: Boolean) { val alarm = getSystemService(Context.ALARM_SERVICE) as AlarmManager if (activate) { - val syncCheckInterval = 4 * AlarmManager.INTERVAL_HOUR + val syncCheckInterval = 2 * AlarmManager.INTERVAL_HOUR try { alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + syncCheckInterval, syncCheckInterval, pendingIntent) } catch (ignored: SecurityException) { @@ -319,23 +326,27 @@ fun Context.syncCalDAVCalendars(activity: SimpleActivity?, calDAVSyncObserver: C val uri = CalendarContract.Calendars.CONTENT_URI contentResolver.unregisterContentObserver(calDAVSyncObserver) contentResolver.registerContentObserver(uri, false, calDAVSyncObserver) - - val accounts = HashSet() - val calendars = CalDAVHandler(applicationContext).getCalDAVCalendars(activity, config.caldavSyncedCalendarIDs) - calendars.forEach { - accounts.add(Account(it.accountName, it.accountType)) - } - - Bundle().apply { - putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true) - putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true) - accounts.forEach { - ContentResolver.requestSync(it, uri.authority, this) - } - } + refreshCalDAVCalendars(activity, config.caldavSyncedCalendarIDs) }.start() } +fun Context.refreshCalDAVCalendars(activity: SimpleActivity?, ids: String) { + val uri = CalendarContract.Calendars.CONTENT_URI + val accounts = HashSet() + val calendars = CalDAVHandler(applicationContext).getCalDAVCalendars(activity, ids) + calendars.forEach { + accounts.add(Account(it.accountName, it.accountType)) + } + + Bundle().apply { + putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true) + putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true) + accounts.forEach { + ContentResolver.requestSync(it, uri.authority, this) + } + } +} + fun Context.addDayNumber(rawTextColor: Int, day: DayMonthly, linearLayout: LinearLayout, dayLabelHeight: Int, callback: (Int) -> Unit) { var textColor = rawTextColor if (!day.isThisMonth) @@ -410,8 +421,27 @@ fun Context.getEventListItems(events: List): ArrayList { listItems.add(listSection) prevCode = code } - val listEvent = ListEvent(it.id, it.startTS, it.endTS, it.title, it.description, it.getIsAllDay(), it.color, it.location, it.isPastEvent) + val listEvent = ListEvent(it.id, it.startTS, it.endTS, it.title, it.description, it.getIsAllDay(), it.color, it.location, it.isPastEvent, it.repeatInterval > 0) listItems.add(listEvent) } return listItems } + +fun Context.handleEventDeleting(eventIds: List, timestamps: List, action: Int) { + when (action) { + DELETE_SELECTED_OCCURRENCE -> { + eventIds.forEachIndexed { index, value -> + dbHelper.addEventRepeatException(value, timestamps[index], true) + } + } + DELETE_FUTURE_OCCURRENCES -> { + eventIds.forEachIndexed { index, value -> + dbHelper.addEventRepeatLimit(value, timestamps[index]) + } + } + DELETE_ALL_OCCURRENCES -> { + val eventIDs = Array(eventIds.size, { i -> (eventIds[i].toString()) }) + dbHelper.deleteEvents(eventIDs, true) + } + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/fragments/WeekFragment.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/fragments/WeekFragment.kt index 7e52aff26..8105e60f7 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/fragments/WeekFragment.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/fragments/WeekFragment.kt @@ -38,19 +38,19 @@ class WeekFragment : Fragment(), WeeklyCalendar { var mListener: WeekFragmentListener? = null private var mWeekTimestamp = 0 - private var mRowHeight = 0 + private var mRowHeight = 0f private var minScrollY = -1 private var maxScrollY = -1 - private var mWasDestroyed = false + private var todayColumnIndex = -1 + private var clickStartTime = 0L private var primaryColor = 0 private var lastHash = 0 + private var mWasDestroyed = false private var isFragmentVisible = false private var wasFragmentInit = false private var wasExtraHeightAdded = false private var dimPastEvents = true - private var clickStartTime = 0L private var selectedGrid: View? = null - private var todayColumnIndex = -1 private var events = ArrayList() private var allDayHolders = ArrayList() private var allDayRows = ArrayList>() @@ -68,8 +68,8 @@ class WeekFragment : Fragment(), WeeklyCalendar { it.map { eventTypeColors.put(it.id, it.color) } } - mRowHeight = (context!!.resources.getDimension(R.dimen.weekly_view_row_height)).toInt() - minScrollY = mRowHeight * context!!.config.startWeeklyAt + mRowHeight = context!!.resources.getDimension(R.dimen.weekly_view_row_height) + minScrollY = (mRowHeight * context!!.config.startWeeklyAt).toInt() mWeekTimestamp = arguments!!.getInt(WEEK_START_TIMESTAMP) dimPastEvents = context!!.config.dimPastEvents primaryColor = context!!.getAdjustedPrimaryColor() @@ -93,9 +93,6 @@ class WeekFragment : Fragment(), WeeklyCalendar { updateScrollY(Math.max(mListener?.getCurrScrollY() ?: 0, minScrollY)) } - (0..6).map { inflater.inflate(R.layout.stroke_vertical_divider, mView.week_vertical_grid_holder) } - (0..23).map { inflater.inflate(R.layout.stroke_horizontal_divider, mView.week_horizontal_grid_holder) } - wasFragmentInit = true return mView } @@ -115,8 +112,8 @@ class WeekFragment : Fragment(), WeeklyCalendar { return@onGlobalLayout } - minScrollY = mRowHeight * context!!.config.startWeeklyAt - maxScrollY = mRowHeight * context!!.config.endWeeklyAt + minScrollY = (mRowHeight * context!!.config.startWeeklyAt).toInt() + maxScrollY = (mRowHeight * context!!.config.endWeeklyAt).toInt() val bounds = Rect() week_events_holder.getGlobalVisibleRect(bounds) @@ -190,14 +187,14 @@ class WeekFragment : Fragment(), WeeklyCalendar { selectedGrid?.animation?.cancel() selectedGrid?.beGone() - val rowHeight = resources.getDimension(R.dimen.weekly_view_row_height) - val hour = (event.y / rowHeight).toInt() + //val rowHeight = resources.getDimension(R.dimen.weekly_view_row_height) + val hour = (event.y / mRowHeight).toInt() selectedGrid = (inflater.inflate(R.layout.week_grid_item, null, false) as ImageView).apply { view.addView(this) background = ColorDrawable(primaryColor) layoutParams.width = view.width - layoutParams.height = rowHeight.toInt() - y = hour * rowHeight + layoutParams.height = mRowHeight.toInt() + y = hour * mRowHeight applyColorFilter(primaryColor.getContrastColor()) setOnClickListener { @@ -214,19 +211,22 @@ class WeekFragment : Fragment(), WeeklyCalendar { } } } - else -> { - } } } override fun updateWeeklyCalendar(events: ArrayList) { - val newHash = events.hashCode() + if (context == null) { + return + } + + val newEvents = context!!.getFilteredEvents(events) + val newHash = newEvents.hashCode() if (newHash == lastHash) { return } lastHash = newHash - this.events = events + this.events = newEvents updateEvents() } @@ -236,15 +236,13 @@ class WeekFragment : Fragment(), WeeklyCalendar { } activity!!.runOnUiThread { - if (context != null && isAdded) { + if (context != null && activity != null && isAdded) { addEvents() } } } private fun addEvents() { - val filtered = context!!.getFilteredEvents(events) - initGrid() allDayHolders.clear() allDayRows.clear() @@ -259,7 +257,7 @@ class WeekFragment : Fragment(), WeeklyCalendar { var hadAllDayEvent = false val replaceDescription = context!!.config.replaceDescription - val sorted = filtered.sortedWith(compareBy({ it.startTS }, { it.endTS }, { it.title }, { if (replaceDescription) it.location else it.description })) + val sorted = events.sortedWith(compareBy({ it.startTS }, { it.endTS }, { it.title }, { if (replaceDescription) it.location else it.description })) for (event in sorted) { if (event.getIsAllDay() || Formatter.getDayCodeFromTS(event.startTS) != Formatter.getDayCodeFromTS(event.endTS)) { hadAllDayEvent = true @@ -346,9 +344,6 @@ class WeekFragment : Fragment(), WeeklyCalendar { private fun addAllDayEvent(event: Event) { (inflater.inflate(R.layout.week_all_day_event_marker, null, false) as TextView).apply { - if (activity == null) - return - var backgroundColor = eventTypeColors.get(event.eventType, primaryColor) var textColor = backgroundColor.getContrastColor() if (dimPastEvents && event.isPastEvent) { @@ -404,7 +399,6 @@ class WeekFragment : Fragment(), WeeklyCalendar { allDayHolders[drawAtLine].addView(this) (layoutParams as RelativeLayout.LayoutParams).apply { - topMargin = mRes.getDimension(R.dimen.tiny_margin).toInt() leftMargin = getColumnWithId(firstDayIndex).x.toInt() bottomMargin = 1 width = getColumnWithId(Math.min(firstDayIndex + daysCnt, 6)).right - leftMargin - 1 diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/CalDAVHandler.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/CalDAVHandler.kt index 94157f78f..3a12d0cfb 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/CalDAVHandler.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/CalDAVHandler.kt @@ -10,6 +10,7 @@ import android.util.SparseIntArray import com.simplemobiletools.calendar.activities.SimpleActivity import com.simplemobiletools.calendar.extensions.config import com.simplemobiletools.calendar.extensions.dbHelper +import com.simplemobiletools.calendar.extensions.refreshCalDAVCalendars import com.simplemobiletools.calendar.extensions.scheduleCalDAVSync import com.simplemobiletools.calendar.models.CalDAVCalendar import com.simplemobiletools.calendar.models.Event @@ -188,7 +189,9 @@ class CalDAVHandler(val context: Context) { var sortedColors = ArrayList(colors.size()) (0 until colors.size()).mapTo(sortedColors) { colors[it] } - sortedColors = sortedColors.distinct() as ArrayList + if (sortedColors.isNotEmpty()) { + sortedColors = sortedColors.distinct() as ArrayList + } return sortedColors } @@ -322,6 +325,7 @@ class CalDAVHandler(val context: Context) { setupCalDAVEventReminders(event) setupCalDAVEventImportId(event) + refreshCalDAVCalendar(event) } fun updateCalDAVEvent(event: Event) { @@ -335,6 +339,7 @@ class CalDAVHandler(val context: Context) { setupCalDAVEventReminders(event) setupCalDAVEventImportId(event) + refreshCalDAVCalendar(event) } private fun setupCalDAVEventReminders(event: Event) { @@ -412,12 +417,14 @@ class CalDAVHandler(val context: Context) { context.contentResolver.delete(contentUri, null, null) } catch (ignored: Exception) { } + refreshCalDAVCalendar(event) } fun insertEventRepeatException(event: Event, occurrenceTS: Int): Long { val uri = CalendarContract.Events.CONTENT_URI val values = fillEventRepeatExceptionValues(event, occurrenceTS) val newUri = context.contentResolver.insert(uri, values) + refreshCalDAVCalendar(event) return java.lang.Long.parseLong(newUri.lastPathSegment) } @@ -458,4 +465,6 @@ class CalDAVHandler(val context: Context) { } private fun getCalDAVEventImportId(calendarId: Int, eventId: Long) = "$CALDAV-$calendarId-$eventId" + + private fun refreshCalDAVCalendar(event: Event) = context.refreshCalDAVCalendars(null, event.getCalDAVCalendarId().toString()) } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/Config.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/Config.kt index 9d6acaa2a..4e80731a5 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/Config.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/Config.kt @@ -39,6 +39,14 @@ class Config(context: Context) : BaseConfig(context) { get() = prefs.getString(REMINDER_SOUND_TITLE, context.getDefaultAlarmTitle(ALARM_SOUND_TYPE_NOTIFICATION)) set(reminderSoundTitle) = prefs.edit().putString(REMINDER_SOUND_TITLE, reminderSoundTitle).apply() + var lastSoundUri: String + get() = prefs.getString(LAST_SOUND_URI, "") + set(lastSoundUri) = prefs.edit().putString(LAST_SOUND_URI, lastSoundUri).apply() + + var lastReminderChannel: Long + get() = prefs.getLong(LAST_REMINDER_CHANNEL_ID, 0L) + set(lastReminderChannel) = prefs.edit().putLong(LAST_REMINDER_CHANNEL_ID, lastReminderChannel).apply() + var storedView: Int get() = prefs.getInt(VIEW, MONTHLY_VIEW) set(view) = prefs.edit().putInt(VIEW, view).apply() diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/Constants.kt index cce4eb856..cfcf35e2f 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/Constants.kt @@ -49,9 +49,10 @@ const val LAST_USED_LOCAL_EVENT_TYPE_ID = "last_used_local_event_type_id" const val DISPLAY_PAST_EVENTS = "display_past_events" const val REPLACE_DESCRIPTION = "replace_description" const val SHOW_GRID = "show_grid" -const val IS_CUSTOMIZING_COLORS = "is_customizing_colors" const val LOOP_REMINDERS = "loop_reminders" const val DIM_PAST_EVENTS = "dim_past_events" +const val LAST_SOUND_URI = "last_sound_uri" +const val LAST_REMINDER_CHANNEL_ID = "last_reminder_channel_ID" // repeat_rule for monthly and yearly repetition const val REPEAT_SAME_DAY = 1 // i.e. 25th every month, or 3rd june (if yearly repetition) @@ -124,4 +125,8 @@ const val SOURCE_IMPORTED_ICS = "imported-ics" const val SOURCE_CONTACT_BIRTHDAY = "contact-birthday" const val SOURCE_CONTACT_ANNIVERSARY = "contact-anniversary" +const val DELETE_SELECTED_OCCURRENCE = 0 +const val DELETE_FUTURE_OCCURRENCES = 1 +const val DELETE_ALL_OCCURRENCES = 2 + fun getNowSeconds() = (System.currentTimeMillis() / 1000).toInt() diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/DBHelper.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/DBHelper.kt index 4bf65c121..588a27898 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/DBHelper.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/DBHelper.kt @@ -552,6 +552,23 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont } } + fun addEventRepeatLimit(eventId: Int, limitTS: Int) { + val values = ContentValues() + val time = Formatter.getDateTimeFromTS(limitTS) + values.put(COL_REPEAT_LIMIT, limitTS - time.hourOfDay) + + val selection = "$COL_EVENT_ID = ?" + val selectionArgs = arrayOf(eventId.toString()) + mDb.update(META_TABLE_NAME, values, selection, selectionArgs) + + if (context.config.caldavSync) { + val event = getEventWithId(eventId) + if (event?.getCalDAVCalendarId() != 0) { + CalDAVHandler(context).updateCalDAVEvent(event!!) + } + } + } + fun deleteEventTypes(eventTypes: ArrayList, deleteEvents: Boolean, callback: (deletedCnt: Int) -> Unit) { var deleteIds = eventTypes.filter { it.caldavCalendarId == 0 }.map { it.id } deleteIds = deleteIds.filter { it != DBHelper.REGULAR_EVENT_TYPE_ID } as ArrayList @@ -559,8 +576,9 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont val deletedSet = HashSet() deleteIds.map { deletedSet.add(it.toString()) } context.config.removeDisplayEventTypes(deletedSet) - if (deleteIds.isEmpty()) + if (deleteIds.isEmpty()) { return + } for (eventTypeId in deleteIds) { if (deleteEvents) { @@ -756,7 +774,7 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont } } else { if (event.endTS >= fromTS) { - events.add(event.copy()) + events.add(event.copy(isPastEvent = getIsPastEvent(event))) } else if (event.getIsAllDay()) { val dayCode = Formatter.getDayCodeFromTS(fromTS) val endDayCode = Formatter.getDayCodeFromTS(event.endTS) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/MonthlyCalendarImpl.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/MonthlyCalendarImpl.kt index 2c6fa6b5d..7b4613c22 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/MonthlyCalendarImpl.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/MonthlyCalendarImpl.kt @@ -28,7 +28,7 @@ class MonthlyCalendarImpl(val mCallback: MonthlyCalendar, val mContext: Context) val startTS = mTargetDate.minusDays(7).seconds() val endTS = mTargetDate.plusDays(43).seconds() mContext.dbHelper.getEvents(startTS, endTS) { - gotEvents(it as ArrayList) + gotEvents(it) } } @@ -131,7 +131,7 @@ class MonthlyCalendarImpl(val mCallback: MonthlyCalendar, val mContext: Context) private fun gotEvents(events: ArrayList) { mEvents = if (mFilterEventTypes) { - mContext.getFilteredEvents(events) as ArrayList + mContext.getFilteredEvents(events) } else { events } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/MyWidgetListProvider.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/MyWidgetListProvider.kt index fec9e3a0b..2e2903d86 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/MyWidgetListProvider.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/MyWidgetListProvider.kt @@ -13,10 +13,7 @@ import com.simplemobiletools.calendar.activities.SplashActivity import com.simplemobiletools.calendar.extensions.config import com.simplemobiletools.calendar.extensions.launchNewEventIntent import com.simplemobiletools.calendar.services.WidgetService -import com.simplemobiletools.commons.extensions.getColoredBitmap -import com.simplemobiletools.commons.extensions.setBackgroundColor -import com.simplemobiletools.commons.extensions.setText -import com.simplemobiletools.commons.extensions.setTextSize +import com.simplemobiletools.commons.extensions.* import org.joda.time.DateTime class MyWidgetListProvider : AppWidgetProvider() { @@ -54,7 +51,7 @@ class MyWidgetListProvider : AppWidgetProvider() { views.setRemoteAdapter(R.id.widget_event_list, this) } - val startActivityIntent = Intent(context, SplashActivity::class.java) + val startActivityIntent = context.getLaunchIntent() ?: Intent(context, SplashActivity::class.java) val startActivityPendingIntent = PendingIntent.getActivity(context, 0, startActivityIntent, PendingIntent.FLAG_UPDATE_CURRENT) views.setPendingIntentTemplate(R.id.widget_event_list, startActivityPendingIntent) views.setEmptyView(R.id.widget_event_list, R.id.widget_event_list_empty) @@ -83,7 +80,7 @@ class MyWidgetListProvider : AppWidgetProvider() { } private fun launchDayActivity(context: Context) { - Intent(context, SplashActivity::class.java).apply { + (context.getLaunchIntent() ?: Intent(context, SplashActivity::class.java)).apply { putExtra(DAY_CODE, Formatter.getDayCodeFromDateTime(DateTime())) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) context.startActivity(this) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/MyWidgetMonthlyProvider.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/MyWidgetMonthlyProvider.kt index 4e8ae0f6e..672b39dfa 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/MyWidgetMonthlyProvider.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/MyWidgetMonthlyProvider.kt @@ -46,7 +46,7 @@ class MyWidgetMonthlyProvider : AppWidgetProvider() { } private fun setupAppOpenIntent(context: Context, views: RemoteViews, id: Int, dayCode: String) { - Intent(context, SplashActivity::class.java).apply { + (context.getLaunchIntent() ?: Intent(context, SplashActivity::class.java)).apply { putExtra(DAY_CODE, dayCode) putExtra(OPEN_MONTH, true) val pendingIntent = PendingIntent.getActivity(context, Integer.parseInt(dayCode.substring(0, 6)), this, 0) @@ -55,7 +55,7 @@ class MyWidgetMonthlyProvider : AppWidgetProvider() { } private fun setupDayOpenIntent(context: Context, views: RemoteViews, id: Int, dayCode: String) { - Intent(context, SplashActivity::class.java).apply { + (context.getLaunchIntent() ?: Intent(context, SplashActivity::class.java)).apply { putExtra(DAY_CODE, dayCode) val pendingIntent = PendingIntent.getActivity(context, Integer.parseInt(dayCode), this, 0) views.setOnClickPendingIntent(id, pendingIntent) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/WeeklyCalendarImpl.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/WeeklyCalendarImpl.kt index 5984a355c..ef777f8c1 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/WeeklyCalendarImpl.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/helpers/WeeklyCalendarImpl.kt @@ -14,7 +14,7 @@ class WeeklyCalendarImpl(val mCallback: WeeklyCalendar, val mContext: Context) { val startTS = weekStartTS val endTS = startTS + WEEK_SECONDS mContext.dbHelper.getEvents(startTS, endTS) { - mEvents = it as ArrayList + mEvents = it mCallback.updateWeeklyCalendar(it) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/models/DayMonthly.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/models/DayMonthly.kt index 8633d330f..303b1e923 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/models/DayMonthly.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/models/DayMonthly.kt @@ -1,5 +1,4 @@ package com.simplemobiletools.calendar.models data class DayMonthly(val value: Int, val isThisMonth: Boolean, val isToday: Boolean, val code: String, val weekOfYear: Int, var dayEvents: ArrayList, - var indexOnMonthView: Int) { -} + var indexOnMonthView: Int) diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/models/Event.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/models/Event.kt index 6c5de919d..cb59a70fa 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/models/Event.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/models/Event.kt @@ -3,7 +3,6 @@ package com.simplemobiletools.calendar.models import com.simplemobiletools.calendar.extensions.seconds import com.simplemobiletools.calendar.helpers.* import com.simplemobiletools.calendar.helpers.Formatter -import com.simplemobiletools.commons.helpers.DAY_SECONDS import org.joda.time.DateTime import java.io.Serializable import java.util.* @@ -21,14 +20,12 @@ data class Event(var id: Int = 0, var startTS: Int = 0, var endTS: Int = 0, var } fun addIntervalTime(original: Event) { - when (repeatInterval) { - DAY -> { - startTS += DAY_SECONDS - endTS += DAY_SECONDS - } + val currStart = Formatter.getDateTimeFromTS(startTS) + val newStart: DateTime + newStart = when (repeatInterval) { + DAY -> currStart.plusDays(1) else -> { - val currStart = Formatter.getDateTimeFromTS(startTS) - val newStart = when { + when { repeatInterval % YEAR == 0 -> when (repeatRule) { REPEAT_ORDER_WEEKDAY -> addXthDayInterval(currStart, original, false) REPEAT_ORDER_WEEKDAY_USE_LAST -> addXthDayInterval(currStart, original, true) @@ -41,23 +38,17 @@ data class Event(var id: Int = 0, var startTS: Int = 0, var endTS: Int = 0, var else -> currStart.plusMonths(repeatInterval / MONTH).dayOfMonth().withMaximumValue() } repeatInterval % WEEK == 0 -> { - // step through weekly repetition by days, as events can trigger multiple times a week - startTS += DAY_SECONDS - endTS += DAY_SECONDS - return - } - else -> { - startTS += repeatInterval - endTS += repeatInterval - return + // step through weekly repetition by days too, as events can trigger multiple times a week + currStart.plusDays(1) } + else -> currStart.plusSeconds(repeatInterval) } - val newStartTS = newStart.seconds() - val newEndTS = newStartTS + (endTS - startTS) - startTS = newStartTS - endTS = newEndTS } } + val newStartTS = newStart.seconds() + val newEndTS = newStartTS + (endTS - startTS) + startTS = newStartTS + endTS = newEndTS } // if an event should happen on 31st with Same Day monthly repetition, dont show it at all at months with 30 or less days diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/models/ListEvent.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/models/ListEvent.kt index 6b3e7c761..1e60d1571 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/models/ListEvent.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/models/ListEvent.kt @@ -1,4 +1,4 @@ package com.simplemobiletools.calendar.models data class ListEvent(var id: Int = 0, var startTS: Int = 0, var endTS: Int = 0, var title: String = "", var description: String = "", - var isAllDay: Boolean, var color: Int, var location: String = "", var isPastEvent: Boolean = false) : ListItem() + var isAllDay: Boolean, var color: Int, var location: String = "", var isPastEvent: Boolean = false, var isRepeatable: Boolean = false) : ListItem() diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/views/MonthView.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/views/MonthView.kt index 1de5995ac..6cf0494ce 100644 --- a/app/src/main/kotlin/com/simplemobiletools/calendar/views/MonthView.kt +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/views/MonthView.kt @@ -185,10 +185,12 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con weekNumberPaint.textAlign = Paint.Align.RIGHT for (i in 0 until ROW_COUNT) { + val weekDays = days.subList(i * 7, i * 7 + 7) + weekNumberPaint.color = if (weekDays.any { it.isToday }) primaryColor else textColor + // fourth day of the week matters val weekOfYear = days.getOrNull(i * 7 + 3)?.weekOfYear ?: 1 val id = "$weekOfYear:" - val yPos = i * dayHeight + weekDaysLetterHeight canvas.drawText(id, horizontalOffset.toFloat() * 0.9f, yPos + paint.textSize, weekNumberPaint) } diff --git a/app/src/main/kotlin/com/simplemobiletools/calendar/views/WeeklyViewGrid.kt b/app/src/main/kotlin/com/simplemobiletools/calendar/views/WeeklyViewGrid.kt new file mode 100644 index 000000000..df5b8d135 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/calendar/views/WeeklyViewGrid.kt @@ -0,0 +1,35 @@ +package com.simplemobiletools.calendar.views + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.util.AttributeSet +import android.view.View +import com.simplemobiletools.calendar.R + +class WeeklyViewGrid(context: Context, attrs: AttributeSet, defStyle: Int) : View(context, attrs, defStyle) { + private val ROWS_CNT = 24 + private val COLS_CNT = 7 + private var paint = Paint(Paint.ANTI_ALIAS_FLAG) + + constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0) + + init { + paint.color = context.resources.getColor(R.color.divider_grey) + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + val rowHeight = height / ROWS_CNT.toFloat() + for (i in 0 until ROWS_CNT) { + val y = rowHeight * i.toFloat() + canvas.drawLine(0f, y, width.toFloat(), y, paint) + } + + val rowWidth = width / COLS_CNT.toFloat() + for (i in 0 until COLS_CNT) { + val x = rowWidth * i.toFloat() + canvas.drawLine(x, 0f, x, height.toFloat(), paint) + } + } +} diff --git a/app/src/main/res/drawable/stroke_bottom.xml b/app/src/main/res/drawable/stroke_bottom.xml index d851d1192..c229316f9 100644 --- a/app/src/main/res/drawable/stroke_bottom.xml +++ b/app/src/main/res/drawable/stroke_bottom.xml @@ -2,9 +2,9 @@ + android:left="-1px" + android:right="-1px" + android:top="-1px"> diff --git a/app/src/main/res/drawable/stroke_bottom_right.xml b/app/src/main/res/drawable/stroke_bottom_right.xml index 206722803..46574e93e 100644 --- a/app/src/main/res/drawable/stroke_bottom_right.xml +++ b/app/src/main/res/drawable/stroke_bottom_right.xml @@ -2,9 +2,9 @@ + android:top="-1px"> diff --git a/app/src/main/res/drawable/stroke_right.xml b/app/src/main/res/drawable/stroke_right.xml index 9bd8e4265..ae1dbec32 100644 --- a/app/src/main/res/drawable/stroke_right.xml +++ b/app/src/main/res/drawable/stroke_right.xml @@ -1,10 +1,10 @@ + android:top="-1px"> diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 2e0c294b0..1cbb9b137 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -600,7 +600,7 @@ android:importantForAccessibility="no"/> + + @@ -57,6 +58,7 @@ android:layout_toLeftOf="@+id/event_item_color" android:layout_toRightOf="@+id/event_item_end" android:ellipsize="end" + android:includeFontPadding="false" android:maxLines="1" android:paddingRight="@dimen/activity_margin" android:textSize="@dimen/day_text_size" diff --git a/app/src/main/res/layout/event_list_item_simple.xml b/app/src/main/res/layout/event_list_item_simple.xml new file mode 100644 index 000000000..4e26dfd16 --- /dev/null +++ b/app/src/main/res/layout/event_list_item_simple.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/event_list_item_widget.xml b/app/src/main/res/layout/event_list_item_widget.xml index 86531f6d0..15c284031 100644 --- a/app/src/main/res/layout/event_list_item_widget.xml +++ b/app/src/main/res/layout/event_list_item_widget.xml @@ -4,13 +4,14 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/event_item_holder" android:layout_width="match_parent" - android:layout_height="wrap_content"> + android:layout_height="wrap_content" + android:layout_marginBottom="@dimen/medium_margin"> @@ -19,7 +20,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/event_item_start" - android:layout_marginLeft="@dimen/activity_margin" + android:layout_marginLeft="@dimen/medium_margin" + android:includeFontPadding="false" android:text="15:00" android:textSize="@dimen/day_text_size"/> @@ -27,12 +29,12 @@ android:id="@+id/event_section_title" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginLeft="@dimen/big_margin" + android:layout_marginLeft="@dimen/normal_margin" android:layout_toLeftOf="@+id/event_item_color" android:layout_toRightOf="@+id/event_item_start" android:ellipsize="end" android:maxLines="1" - android:paddingRight="@dimen/activity_margin" + android:paddingRight="@dimen/small_margin" android:textSize="@dimen/day_text_size" tools:text="Event title"/> @@ -41,12 +43,13 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/event_section_title" - android:layout_marginLeft="@dimen/big_margin" + android:layout_marginLeft="@dimen/normal_margin" android:layout_toLeftOf="@+id/event_item_color" android:layout_toRightOf="@+id/event_item_end" android:ellipsize="end" + android:includeFontPadding="false" android:maxLines="1" - android:paddingRight="@dimen/activity_margin" + android:paddingRight="@dimen/small_margin" android:textSize="@dimen/day_text_size" tools:text="Event description"/> @@ -58,7 +61,7 @@ android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_alignTop="@+id/event_section_title" - android:paddingRight="@dimen/activity_margin" + android:paddingRight="@dimen/medium_margin" android:src="@drawable/monthly_event_dot"/> diff --git a/app/src/main/res/layout/event_list_item_widget_simple.xml b/app/src/main/res/layout/event_list_item_widget_simple.xml new file mode 100644 index 000000000..44cfc65b9 --- /dev/null +++ b/app/src/main/res/layout/event_list_item_widget_simple.xml @@ -0,0 +1,42 @@ + + + + + + + + + + diff --git a/app/src/main/res/layout/event_list_section_widget.xml b/app/src/main/res/layout/event_list_section_widget.xml index 0a8f45071..fcfe6ad6c 100644 --- a/app/src/main/res/layout/event_list_section_widget.xml +++ b/app/src/main/res/layout/event_list_section_widget.xml @@ -6,6 +6,7 @@ android:layout_height="wrap_content" android:drawablePadding="1dp" android:drawableTop="@drawable/divider_width" - android:paddingTop="@dimen/medium_margin" + android:paddingBottom="@dimen/small_margin" + android:paddingTop="@dimen/small_margin" android:textSize="@dimen/normal_text_size" android:textStyle="bold"/> diff --git a/app/src/main/res/layout/fragment_week.xml b/app/src/main/res/layout/fragment_week.xml index 0ec204391..7319495d6 100644 --- a/app/src/main/res/layout/fragment_week.xml +++ b/app/src/main/res/layout/fragment_week.xml @@ -5,12 +5,6 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - - + android:layout_height="@dimen/weekly_view_events_height"/> diff --git a/app/src/main/res/layout/stroke_horizontal_divider.xml b/app/src/main/res/layout/stroke_horizontal_divider.xml deleted file mode 100644 index 924faf4a3..000000000 --- a/app/src/main/res/layout/stroke_horizontal_divider.xml +++ /dev/null @@ -1,7 +0,0 @@ - - diff --git a/app/src/main/res/layout/stroke_vertical_divider.xml b/app/src/main/res/layout/stroke_vertical_divider.xml deleted file mode 100644 index afca637d1..000000000 --- a/app/src/main/res/layout/stroke_vertical_divider.xml +++ /dev/null @@ -1,7 +0,0 @@ - - diff --git a/app/src/main/res/layout/widget_event_list.xml b/app/src/main/res/layout/widget_event_list.xml index f789f19f0..d1efe9816 100644 --- a/app/src/main/res/layout/widget_event_list.xml +++ b/app/src/main/res/layout/widget_event_list.xml @@ -15,8 +15,8 @@ android:ellipsize="end" android:gravity="center_vertical" android:maxLines="1" - android:paddingLeft="@dimen/activity_margin" - android:paddingRight="@dimen/activity_margin" + android:paddingLeft="@dimen/medium_margin" + android:paddingRight="@dimen/medium_margin" android:textSize="@dimen/normal_text_size"/> @@ -40,9 +40,8 @@ android:layout_below="@+id/widget_event_new_event" android:clipToPadding="false" android:divider="@null" - android:dividerHeight="@dimen/medium_margin" - android:paddingBottom="@dimen/medium_margin" - android:paddingLeft="@dimen/activity_margin"/> + android:paddingBottom="@dimen/small_margin" + android:paddingLeft="@dimen/medium_margin"/> Bu hadisə təkrarlanabilər Seçim təkrarlanan hadisələr ehtiva edir Yalnız seçilmiş hadisəni sil + Delete this and all future occurrences Bütün hadisələri sil Yalnız seçilmiş hadisəni yenilə Bütün hadisələri yenilə diff --git a/app/src/main/res/values-br/strings.xml b/app/src/main/res/values-br/strings.xml index 518b3cd92..383383936 100644 --- a/app/src/main/res/values-br/strings.xml +++ b/app/src/main/res/values-br/strings.xml @@ -44,6 +44,7 @@ An darvoud a c\'hall addegouezhout Darvoudoù a c\'hall addegouezhout a zo en diuzad Dilemel an degouezh bremanel nemetken + Delete this and all future occurrences Dilemel an holl zegouezhioù Hizivaat an degouezh diuzet hepken Hizivaat an holl zegouezhioù diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index e799e07c1..27a2dbd41 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -44,6 +44,7 @@ Událost se opakuje Výběr zahrnuje opakující se události Vymazat pouze vybrané výskyty + Delete this and all future occurrences Vymazat všechny výskyty Změnit pouze vybrané výskyty Změnit všechny výskyty diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 33289da56..aba991e5c 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -19,7 +19,7 @@ Begivenhed Rediger begivenhed Ny begivenhed - Create a new event + Opret en ny begivenhed Kopier begivenhed Indtast titel Begivenheden skal starte inden den slutter @@ -44,6 +44,7 @@ Begivenheden kan gentages Valget indeholder gentagne begivenheder Slet kun denne forekomst + Slet denne og alle fremtidige forekomster Slet alle forekomster Opdater kun denne forekomst Opdater alle forekomster diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 56b112f42..1809832c8 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -7,9 +7,9 @@ Wochenansicht Monatsansicht Jahresansicht - Schlichte Terminliste + Einfache Terminliste Keine anstehenden Termine - Gehe zu Heute + Springe zu Heute Monatskalender @@ -19,8 +19,8 @@ Termin Termin bearbeiten Neuer Termin - Create a new event - Duplicate event + Neuen Termin erstellen + Event duplizieren Titel darf nicht leer sein Der Termin darf nicht früher enden als er beginnt Termin erfolgreich hinzugefügt @@ -44,6 +44,7 @@ Termin ist wiederholbar Die Auswahl enthält Ereignisse mit Wiederholungen Lösche nur die ausgewählte Wiederholung + Delete this and all future occurrences Lösche alle Wiederholungen Ändere nur die ausgewählte Wiederholung Ändere alle Wiederholungen @@ -59,7 +60,7 @@ Der letzte Tag Am gleichen Tag jeden Monats wiederholen Am letzten Tag des Monats wiederholen - Repeat on the same day every year + Am selben Tag jeden Jahres wiederholen Wiederhole jeden Jeden ersten @@ -105,7 +106,7 @@ Vergangene Termine auch exportieren Beziehe Termintypen mit ein Dateiname (ohne .ics) - Override event types in the file + Überschreibe Termintypen in der Datei Titel @@ -155,9 +156,9 @@ Alle Termine löschen Bist du sicher, dass du alle Termine löschen willst? Deine Termintypen und Einstellungen bleiben erhalten. Raster anzeigen - Loop reminders until dismissed - Dim past events - Events + Erinnerungen wiederholen bis sie verworfen werden + Vergangene Termine ausgrauen + Termine CalDAV diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index f477b44d1..48add30eb 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -44,6 +44,7 @@ Este evento se repite La selección contiene repetición de eventos Eliminar sólo el evento seleccionado + Delete this and all future occurrences Eliminar todos los eventos Actualizar sólo el evento seleccionado Actualizar todos los eventos diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 9630e24f5..02462868c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -19,15 +19,15 @@ Événement Éditer l\'événement Nouvel événement - Create a new event - Duplicate event + Créer un nouvel événement + Evénement en double Le titre ne peut pas être vide L\'événement ne peut pas se terminer plus tôt qu\'il ne commence Événement ajouté avec succès Événement ajouté avec succès Filtrer les événements par type Veuillez remplir un emplacement pour être affiché sur une carte - An event is upcoming + Un événement est à venir Répétition @@ -44,6 +44,7 @@ L\'événement est répétable La sélection contient des événements avec répétition Supprimer seulement l\'occurrence sélectionnée + Delete this and all future occurrences Supprimer toutes les occurrences Mettre à jour seulement l\'occurrence sélectionnée Mettre à jour toutes les occurrences @@ -59,7 +60,7 @@ Le dernier jour Répéter le même jour de chaque mois Répéter le dernier jour de chaque mois - Repeat on the same day every year + Répéter le même jour chaque année Répéter chaque Chaque premier @@ -105,7 +106,7 @@ Exporter aussi les événements passés Inclure les types d\'événement Nom de fichier (sans .ics) - Override event types in the file + Remplacer les types d'événement dans le fichier Titre @@ -134,7 +135,7 @@ Ajouter des jours fériés Jours fériés nationaux Jours fériés religieux - Holidays have been successfully imported into the \"Holidays\" event type + Les vacances ont été importées avec succès dans le type d\'événement \"Vacances\" L\'import de certains événements a échoué L\'import des jours fériés a échoué @@ -154,10 +155,10 @@ Remplacer la description de l\'événement par l\'emplacement Supprimer tous les événements Êtes-vous sûr de vouloir supprimer tous les événements ? Cela laissera vos types d\'événements et autres paramètres intacts. - Show a grid - Loop reminders until dismissed - Dim past events - Events + Afficher une grille + Boucles de rappel jusqu\'à ce qu\'il soit rejeté + Diminuer l\'affichage des événements passés + Evénements CalDAV diff --git a/app/src/main/res/values-gl/strings.xml b/app/src/main/res/values-gl/strings.xml index 18cba5b3f..1559926d4 100644 --- a/app/src/main/res/values-gl/strings.xml +++ b/app/src/main/res/values-gl/strings.xml @@ -44,6 +44,7 @@ O evento é repetible A seleción contén eventos recurrentes Eliminar só o evento selecionado + Delete this and all future occurrences Eliminar todos os eventos Actualizar só o evento selecionado Actualizar todos os eventos diff --git a/app/src/main/res/values-hi-rIN/strings.xml b/app/src/main/res/values-hi-rIN/strings.xml index 38e4f82d0..ce50644eb 100644 --- a/app/src/main/res/values-hi-rIN/strings.xml +++ b/app/src/main/res/values-hi-rIN/strings.xml @@ -45,6 +45,7 @@ The event is repeatable The selection contains repeating events Delete the selected occurrence only + Delete this and all future occurrences Delete all occurrences Update the selected occurrence only Update all occurrences diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index cca4bbd11..836667195 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -44,6 +44,7 @@ Događaj je ponovljiv Odabir sadrži ponavljajuće događaje Izbriši samo odabrano ponavljanje + Delete this and all future occurrences Izbriši sva ponavljanja Ažuriraj samo odabrano ponavljanje Ažuriraj sva ponavljanja diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index f5641d2de..ac2a39aec 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -44,6 +44,7 @@ The event is repeatable The selection contains repeating events Delete the selected occurrence only + Delete this and all future occurrences Delete all occurrences Update the selected occurrence only Update all occurrences diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 0ea3a368f..704a30c9c 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -44,6 +44,7 @@ L\'evento è ripetibile La selezione contiene eventi ripetuti Elimina solamente l\'occorenza selezionata + Delete this and all future occurrences Elimina tutte le occorrenze Aggiorna solamente l\'occorenza selezionata Aggiorna tutte le occorenze diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index eb7f61ca2..00fdcd70c 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -45,6 +45,7 @@ The event is repeatable The selection contains repeating events Delete the selected occurrence only + Delete this and all future occurrences Delete all occurrences Update the selected occurrence only Update all occurrences diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 43e6b0bac..44358fbf6 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -44,6 +44,7 @@ The event is repeatable The selection contains repeating events Delete the selected occurrence only + Delete this and all future occurrences Delete all occurrences Update the selected occurrence only Update all occurrences diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 87c8f7fea..ad792ac2e 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -44,6 +44,7 @@ 반복 이벤트입니다 선택한 항목에 반복되는 이벤트들이 있습니다 선택한 항목만 삭제 + Delete this and all future occurrences 모든 항목 삭제 선택한 항목만 변경 모든 항목 변경 diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 37c3d1086..288fd384e 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -44,6 +44,7 @@ Įvykis pakartojamas Pasirinkimas susideda iš pasikartojančių įvykių Ištrinti tik pasirinktą įvykį + Delete this and all future occurrences Ištrinti visus įvykius Atnaujinti tik pasirinktą įvykį Atnaujinti visus įvykius diff --git a/app/src/main/res/values-nb/strings.xml b/app/src/main/res/values-nb/strings.xml index 16886abe8..06dde0ddc 100644 --- a/app/src/main/res/values-nb/strings.xml +++ b/app/src/main/res/values-nb/strings.xml @@ -19,8 +19,8 @@ Hendelse Rediger hendelse Ny hendelse - Create a new event - Duplicate event + Opprett en ny hendelse + Dupliser hendelse Tittel kan ikke være tom Hendelsen kan ikke slutte tidligere enn den starter Hendelse vellykket lagt til @@ -44,6 +44,7 @@ Hendelsen er repeterbar Markeringen inneholder gjentagende hendelser Slett bare den merkede forekomsten + Delete this and all future occurrences Slett alle forekomster Oppdater bare den merkede forekomsten Oppdater alle forekomster @@ -59,7 +60,7 @@ Den siste dagen Gjenta på den samme dagen hver måned Gjenta på den siste dagen i måneden - Repeat on the same day every year + Gjenta på den samme dagen hvert år Gjenta hver Hver første @@ -105,7 +106,7 @@ Eksporter fortidige hendelser også Inkluder hendelsestyper Filnavn (uten .ics) - Override event types in the file + Overstyr hendelsestyper i filen Tittel @@ -155,9 +156,9 @@ Slett alle hendelser Er du sikker på at du vil slette alle hendelser? Dine hendelsestyper og andre innstillinger blir beholdt. Vis rutenett - Loop reminders until dismissed - Dim past events - Events + Gjenta påminnelser inntil avvist + Dim tidligere hendelser + Hendelser CalDAV diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index a6914b604..535b4cf99 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -44,6 +44,7 @@ De afspraak wordt herhaald De selectie bevat herhaalde afspraken Alleen huidige afspraak verwijderen + Deze afspraak en hierop volgende herhalingen verwijderen Al deze afspraken verwijderen Alleen huidige afspraak bijwerken Alle afspraken bijwerken diff --git a/app/src/main/res/values-no/strings.xml b/app/src/main/res/values-no/strings.xml index 9546b4635..193a20550 100644 --- a/app/src/main/res/values-no/strings.xml +++ b/app/src/main/res/values-no/strings.xml @@ -44,6 +44,7 @@ Hendelsen er repeterbar Markeringen inneholder gjentagende hendelser Slett bare den merkede forekomsten + Delete this and all future occurrences Slett alle forekomster Oppdater bare den merkede forekomsten Oppdater alle forekomster diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 2a6520e0a..23ce2b7a4 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -44,6 +44,7 @@ Wydarzenie jest powtarzalne Wybór zawiera powtarzające się wydarzenia Usuń tylko wybrane wystąpienie + Delete this and all future occurrences Usuń wszystkie wystąpienia Zaktualizuj tylko wybrane wystąpienia Zaktualizuj wszystkie wystąpienia diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 92a1daa12..ef86efa1c 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -44,6 +44,7 @@ The event is repeatable A seleção contém eventos recorrentes Apagar a ocorrência selecionada + Delete this and all future occurrences Apagar todas as ocorrências Atualizar a ocorrência selecionada Atualizar todas as ocorrências diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 6664e0a07..e3d17b06b 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -19,8 +19,8 @@ Evento Editar evento Novo evento - Create a new event - Duplicate event + Criar novo evento + Duplicar evento O título não pode estar vazio O evento não pode terminar antes de iniciar Evento adicionado com sucesso @@ -44,6 +44,7 @@ O evento é repetível A seleção contém eventos recorrentes Apagar a ocorrência selecionada + Delete this and all future occurrences Apagar todas as ocorrências Atualizar a ocorrência selecionada Atualizar todas as ocorrências @@ -155,9 +156,9 @@ Apagar todos os eventos Tem a certeza de que deseja apagar todos os eventos? Esta ação não afeta os tipos de eventos nem as outras definições. Mostrar grelha - Loop reminders until dismissed - Dim past events - Events + Mostrar lembretes até serem descartados + Desvanecer eventos passados + Eventos CalDAV diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 3727dca5e..c8310d507 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -44,6 +44,7 @@ Это событие может повторяться В выбранном есть повторяющиеся события Удалить только выбранное + Delete this and all future occurrences Удалить все связанные Обновить только выбранное Обновить все связанные diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 273a9940c..19984115b 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -44,6 +44,7 @@ Udalosť je opakujúca sa Výber obsahuje opakujúce sa udalosti Vymazať iba označené opakovania + Vymazať toto a všetky budúce opakovania Vymazať všetky opakovania Upraviť iba označené opakovania Upraviť všetky opakovania diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 3a54c652d..2755888aa 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -19,8 +19,8 @@ Händelse Redigera händelse Ny händelse - Create a new event - Duplicate event + Skapa en ny händelse + Duplicera händelse Titeln får inte vara tom Händelsen kan inte sluta innan den har startat Händelsen har lagts till @@ -44,6 +44,7 @@ Händelsen är återkommande Markeringen innehåller återkommande händelser Ta bara bort den markerade förekomsten + Delete this and all future occurrences Ta bort alla förekomster Uppdatera bara den markerade förekomsten Uppdatera alla förekomster @@ -59,7 +60,7 @@ Den sista dagen Upprepa på samma dag varje månad Upprepa på månadens sista dag - Repeat on the same day every year + Upprepa på samma dag varje år Upprepa varje Varje första @@ -105,7 +106,7 @@ Exportera även tidigare händelser Inkludera händelsetyper Filnamn (utan .ics) - Override event types in the file + Ignorera händelsetyper i filen Titel @@ -155,9 +156,9 @@ Ta bort alla händelser Är du säker på att du vill ta bort alla händelser? Dina händelsetyper och andra inställningar påverkas inte av borttagningen. Visa ett rutnät - Loop reminders until dismissed - Dim past events - Events + Upprepa påminnelser tills de tas bort + Tona ned tidigare händelser + Händelser CalDAV @@ -173,13 +174,13 @@ - Måndag - Tisdag - Onsdag - Torsdag - Fredag - Lördag - Söndag + måndag + tisdag + onsdag + torsdag + fredag + lördag + söndag Träning diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 31fb72107..8adb9cdad 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -3,12 +3,12 @@ Basit Takvim Takvim Görünümü değiştir - Daily view + Günlük görünüm Haftalık görünüm Aylık görünüm Yıllık görünüm - Basit durum listesi - Gelecekteki etkinliğiniz yok gibi görünüyor. + Basit etkinlik listesi + Yaklaşan etkinlikleriniz yok gibi görünüyor. Bugüne git @@ -19,15 +19,15 @@ Durum Etkinliği Düzenle Yeni Etkinlik - Create a new event - Duplicate event - Başlık başlığı boş olamaz - Etkinlik, başlamasından önce sona eremez + Yeni etkinlik oluştur + Tekrarlanan etkinlik + Başlık boş olamaz + Etkinlik başladığından daha erken bitemez Etkinlik başarıyla eklendi Etkinlik başarıyla güncellendi - Etkinlikleri türe göre filtreleyin - Please fill in a location to be shown on a map - An event is upcoming + Etkinlikleri türe göre filtrele + Lütfen haritada gösterilecek bir yeri doldurun + Bir etkinlik yaklaşıyor Tekrarla @@ -36,31 +36,32 @@ Haftalık Aylık Yıllık - haftalar - aylar - yıllar - Kadar tekrarla: - Sonsuza dek - The event is repeatable - Seçim, tekrar eden etkinlikleri içeriyor - Yalnızca seçilen olayı sil - Tüm tekrarlamaları sil - Sadece seçilen olayı güncelle - Tüm olayları güncelle - Tarihe kadar tekrarla - X süresini tekrarla + hafta + ay + yıl + Şu kadar tekrarla: + Sonsuza kadar + Etkinlik tekrarlanabilir + Seçim tekrarlanan etkinlikleri içeriyor + Yalnızca seçilen etkinlikleri sil + Delete this and all future occurrences + Tüm tekrarlanan etkinlikleri sil + Yalnızca seçilen etkinlikleri güncelle + Tüm etkinlikleri güncelle + Şu tarihe kadar tekrarla + X kere tekrarla Sonsuza kadar tekrarla - zamanlar + kere Tekrarla Tekrarlama açık Her gün Seçilen günlerde Aynı gün Son gün - Her ay aynı gün tekrar edin - Ayın son gününde tekrar et - Repeat on the same day every year - Her seferinde tekrarla + Her ay aynı günde tekrarla + Ayın son gününde tekrarla + Her yıl aynı günde tekrarla + Her tekrar Her ilk ikinci @@ -70,7 +71,7 @@ - Her seferinde tekrarla + Her tekrar Her ilk ikinci @@ -79,37 +80,37 @@ son - Birthdays - Add contact birthdays - No birthdays have been found - Birthdays added successfully + Doğum günleri + Kişi doğum günlerini ekle + Hiçbir doğum günü bulunamadı + Doğum günleri başarıyla eklendi - Anniversaries - Add contact anniversaries - No anniversaries have been found - Anniversaries added successfully + Yıldönümleri + Kişi yıldönümlerini ekle + Yıldönümleri bulunamadı + Yıldönümleri başarıyla eklendi Hatırlatma önce - Başka bir hatırlatma ekle - Event reminders + Başka hatırlatma ekle + Etkinlik hatırlatıcılar - Olayları içe aktar - Olayları dışa aktar - Bir .ics dosyasından olayları içe aktar - Etkinlikleri bir .ics dosyasına aktarın - Varsayılan olay türü - Geçmişteki etkinlikleri de dışa aktar - Include event types - Filename (without .ics) - Override event types in the file + Etkinlikleri içe aktar + Etkinlikleri dışa aktar + Etkinlikleri .ics dosyasından içe aktar + Etkinlikleri .ics dosyasına aktar + Varsayılan etkinlik türü + Geçmiş etkinlikleri de dışa aktar + Etkinlik türlerini ekle + Dosya adı (.ics olmadan) + Dosyadaki etkinlik türlerini geçersiz kıl Başlık - Location + Konum Açıklama Tüm-gün @@ -117,59 +118,59 @@ Hafta - Olay türleri - Yeni bir tür ekle + Etkinlik türleri + Yeni tür ekle Türü düzenle - Bu başlığı taşıyan tür zaten var + Bu başlığı taşıyan bir tür zaten var Renk Düzenli etkinlik - Varsayılan etkinlik türü silinemiyor + Varsayılan etkinlik türü silinemez Bir etkinlik türü seçin - Move affected events into the default event type - Permanently remove affected events - To remove a CalDAV calendar you have to unsynchronize it + Etkilenen etkinlikleri varsayılan etkinlik türüne taşı + Etkilenen etkinlikleri kalıcı olarak kaldır + CalDAV takvimini kaldırmak için, senkronizasyonu kaldırmalısınız - Holidays + Tatiller Tatil ekle - National holidays - Religious holidays - Holidays have been successfully imported into the \"Holidays\" event type - Importing some events failed - Importing holidays failed + Ulusal tatiller + Dini tatiller + Tatiller \"Tatiller\" etkinlik türüne başarıyla aktarıldı + Bazı etkinlikler içe aktarılamadı + Tatiller içe aktarılamadı - Olay türlerini yönet - Haftalık görüntüleme gününü şu saatte başlatın - Haftalık görüntüleme gününü bitiştir - Aylık görünümde hafta sayılarını göster - Hatırlatma bildiriminde titreşim + Etkinlik türlerini yönet + Gün başlangıcı + Gün bitişi + Hafta sayılarını göster + Hatırlatma bildiriminde titre Hatırlatma sesi - Zil sesi ayarlayabilen hiçbir uygulama bulunamadı - Boş - Gün başlamadan önce bitemez - CalDAV sync - Event lists - Display events from the past - Replace event description with location - Delete all events - Are you sure you want to delete all events? This will leave your event types and other settings intact. - Show a grid - Loop reminders until dismissed - Dim past events - Events + Zil sesi ayarlayabilen uygulama yok + Hiçbiri + Gün başladığından daha erken bitemez + CalDAV senkronizasyonu + Etkinlik listeleri + Geçmişten gelen etkinlikleri görüntüle + Etkinlik açıklamasını konumla değiştir + Tüm etkinlikleri sil + Tüm etkinlikleri silmek istediğinizden emin misiniz? Bu, etkinlik türlerinizi ve diğer ayarlarınızı bozulmamış halde bırakır. + Izgara göster + Kapatılana kadar hatırlatıcıları tekrarla + Geçmiş etkinlikleri karart + Etkinlikler CalDAV - Select calendars to sync - Manage synced calendars - Store locally only - Refresh CalDAV calendars - Refreshing… - Refreshing complete - Editing calendar failed - Syncing… - Sync completed + Senkronize edilecek takvimleri seç + Senkronize edilmiş takvimleri yönet + Yalnızca yerel olarak depola + CalDAV takvimlerini yenile + Yenileniyor… + Yenileme tamamlandı + Takvim düzenlenme başarısız + Senkronize ediliyor… + Senkronizasyon tamamlandı @@ -182,38 +183,37 @@ Pazar - Egzersiz yapma - Etap günü - John ile görüşme - Rockstone bahçesinde + Egzersiz + Bacak günü + Can ile buluşma + Gülhane parkında Kütüphane - Mary ile öğle yemeği - Plaza\'da + Merve ile öğle yemeği + Şehir meydanında Kahve zamanı - How can I remove the holidays imported via the \"Add holidays\" button? - Holidays created that way are inserted in a new event type called \"Holidays\". You can go in Settings -> Manage Event Types, - long press the given event type and delete it by selecting the trashbin. - Can I sync my events via Google Calendar, or other service supporting CalDAV? - Yes, just toggle \"CalDAV sync\" in the app settings and select the calendars you want to sync. However, you will need some third party app handling the synchronization between the device and servers. - In case you want to synchronize a Google calendar, their official Calendar app will do the job. For other calendars you will need a third party sync adapter, for example DAVdroid. + \"Tatil ekle\" düğmesiyle içe aktarılan tatilleri nasıl kaldırabilirim? + Tatiller, \"Tatiller\" olarak adlandırılan yeni bir etkinlik türüne eklenir. Ayarlar -> Etkinlik Türlerini Yönet\'e gidip, belirlenen etkinlik türüne uzun basıp çöp kutusunu seçerek silebilirsiniz. + Etkinliklerimi Google Takvim\'le veya CalDAV\'ı destekleyen başka bir hizmetle senkronize edebilir miyim? + Evet, uygulama ayarlarından \"CalDAV senkronizasyonu\" seçeneğini işaretleyin ve senkronize etmek istediğiniz takvimleri seçin. Bununla birlikte, cihaz ve sunucular arasındaki senkronizasyonu ele alan bazı üçüncü taraf uygulamalarına ihtiyacınız olacaktır. + Bu durumda bir Google takvimini senkronize etmek istiyorsanız, resmi Takvim uygulaması işi yapar. Diğer takvimler için, DAVdroid gibi üçüncü taraf senkronizasyon adaptörüne ihtiyacınız olacaktır. - Etkinlikler, özelleştirilebilir widget ve reklamsız basit bir takvim. + Etkinlikler, özelleştirilebilir widget\'lı reklamsız basit bir takvim. - Başka bir takvim entegrasyonu gerektirmeyen çevrimdışı bir takvim. Yinelenen etkinlikler kolayca oluşturabilir ve hatırlatıcılar oluşturabilir, haftanın sayılarını da gösterebilir. + İsteğe bağlı CalDAV senkronizasyonu ile basit bir takvim. Kolayca tekrarlanan etkinlikler oluşturabilir ve hatırlatıcılar ayarlayabilir, ayrıca hafta sayılarını görüntüleyebilirsiniz. - Metnin rengini, ayrıca alfa ve arka plan rengini özelleştirebileceğiniz resizable 4x4 bir widget içerir. + Metnin renginin yanı sıra alfa ve arka plan rengini özelleştirebileceğiniz aylık görünüm ve etkinlik listesi widget\'ı içerir. - Reklam içermeyen veya gereksiz izinler. Tamamen açık kaynaktır, özelleştirilebilir renkler sağlar. + Reklam veya gereksiz izinler içermez. Tamamen açık kaynaktır, özelleştirilebilir renkler sağlar. - Depolama izni yalnızca .ics dosyalarından olayları içe aktarmak için gereklidir. + Depolama izni yalnızca .ics dosyalarındaki etkinlikleri dışa veya içe aktarmak için gereklidir. - The Contacts permission is used only at importing contact birthdays and anniversaries. + Kişiler izni yalnızca doğum günlerini ve yıldönümlerini içe aktarırken kullanılır. - Bu uygulama, daha büyük bir uygulama serisinden sadece bir parça. Geri kalanını şu adresten bulabilirsiniz: https://www.simplemobiletools.com + Bu uygulama, daha büyük bir uygulama serisinden sadece bir parça. Geri kalanı http://www.simplemobiletools.com adresinde bulabilirsiniz 重複 @@ -44,6 +44,7 @@ 這是個重複活動 選擇的項目含有重複活動 只刪除選擇的事件 + Delete this and all future occurrences 刪除全部事件 只更新選擇的事件 更新全部事件 @@ -59,7 +60,7 @@ 最後一天 重複每月同一天 重複每月最後一天 - Repeat on the same day every year + 重複每年同一天 重複每月 每月 第一個 @@ -105,7 +106,7 @@ 也匯出過去的活動 包含活動類型 檔案名稱 (不含.ics) - Override event types in the file + 覆寫檔案內的活動類型 標題 @@ -154,10 +155,10 @@ 活動描述改成地點 刪除全部活動 你確定要刪除全部活動嗎?會完整留下你的活動類型和其他設定。 - Show a grid - Loop reminders until dismissed - Dim past events - Events + 顯示網格 + 不斷重複提醒直到解除 + 淡化過去的活動 + 活動 CalDAV diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3f6a63415..07033f025 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -44,6 +44,7 @@ The event is repeatable The selection contains repeating events Delete the selected occurrence only + Delete this and all future occurrences Delete all occurrences Update the selected occurrence only Update all occurrences diff --git a/build.gradle b/build.gradle index 0a7f22883..7cbfad621 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.1.2' + classpath 'com.android.tools.build:gradle:3.1.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong diff --git a/fastlane/metadata/android/en-US/images/icon.png b/fastlane/metadata/android/en-US/images/icon.png index 377b57397..3f9fc85cb 100644 Binary files a/fastlane/metadata/android/en-US/images/icon.png and b/fastlane/metadata/android/en-US/images/icon.png differ