32
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)*
|
||||
----------------------------
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
android:launchMode="singleTask"
|
||||
android:theme="@style/SplashTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Event>, r
|
|||
private fun askConfirmDelete() {
|
||||
val eventIds = ArrayList<Int>(selectedPositions.size)
|
||||
val timestamps = ArrayList<Int>(selectedPositions.size)
|
||||
val eventsToDelete = ArrayList<Event>(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<Event>(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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<ListIt
|
|||
recyclerView: MyRecyclerView, itemClick: (Any) -> 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<ListIt
|
|||
override fun getSelectableItemCount() = listItems.filter { it is ListEvent }.size
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyRecyclerViewAdapter.ViewHolder {
|
||||
val layoutId = if (viewType == ITEM_EVENT) R.layout.event_list_item else R.layout.event_list_section
|
||||
val layoutId = when (viewType) {
|
||||
ITEM_EVENT -> 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<ListIt
|
|||
|
||||
override fun getItemCount() = listItems.size
|
||||
|
||||
override fun getItemViewType(position: Int) = if (listItems[position] is ListEvent) ITEM_EVENT else ITEM_HEADER
|
||||
override fun getItemViewType(position: Int) = if (listItems[position] is ListEvent) {
|
||||
val event = listItems[position] as ListEvent
|
||||
val detailField = if (replaceDescription) event.location else event.description
|
||||
if (event.startTS == event.endTS && detailField.isEmpty()) {
|
||||
ITEM_EVENT_SIMPLE
|
||||
} else {
|
||||
ITEM_EVENT
|
||||
}
|
||||
} else {
|
||||
ITEM_HEADER
|
||||
}
|
||||
|
||||
fun toggle24HourFormat(use24HourFormat: Boolean) {
|
||||
this.use24HourFormat = use24HourFormat
|
||||
|
@ -114,16 +130,16 @@ class EventListAdapter(activity: SimpleActivity, var listItems: ArrayList<ListIt
|
|||
private fun setupListEvent(view: View, listEvent: ListEvent) {
|
||||
view.apply {
|
||||
event_section_title.text = listEvent.title
|
||||
event_item_description.text = if (replaceDescriptionWithLocation) listEvent.location else listEvent.description
|
||||
event_item_description?.text = if (replaceDescription) listEvent.location else listEvent.description
|
||||
event_item_start.text = if (listEvent.isAllDay) allDayString else Formatter.getTimeFromTS(context, listEvent.startTS)
|
||||
event_item_end.beInvisibleIf(listEvent.startTS == listEvent.endTS)
|
||||
event_item_end?.beInvisibleIf(listEvent.startTS == listEvent.endTS)
|
||||
event_item_color.applyColorFilter(listEvent.color)
|
||||
|
||||
if (listEvent.startTS != listEvent.endTS) {
|
||||
val startCode = Formatter.getDayCodeFromTS(listEvent.startTS)
|
||||
val endCode = Formatter.getDayCodeFromTS(listEvent.endTS)
|
||||
event_item_end?.apply {
|
||||
val startCode = Formatter.getDayCodeFromTS(listEvent.startTS)
|
||||
val endCode = Formatter.getDayCodeFromTS(listEvent.endTS)
|
||||
|
||||
event_item_end.apply {
|
||||
text = Formatter.getTimeFromTS(context, listEvent.endTS)
|
||||
if (startCode != endCode) {
|
||||
if (listEvent.isAllDay) {
|
||||
|
@ -155,9 +171,9 @@ class EventListAdapter(activity: SimpleActivity, var listItems: ArrayList<ListIt
|
|||
}
|
||||
|
||||
event_item_start.setTextColor(startTextColor)
|
||||
event_item_end.setTextColor(endTextColor)
|
||||
event_item_end?.setTextColor(endTextColor)
|
||||
event_section_title.setTextColor(startTextColor)
|
||||
event_item_description.setTextColor(startTextColor)
|
||||
event_item_description?.setTextColor(startTextColor)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,31 +203,26 @@ class EventListAdapter(activity: SimpleActivity, var listItems: ArrayList<ListIt
|
|||
private fun askConfirmDelete() {
|
||||
val eventIds = ArrayList<Int>(selectedPositions.size)
|
||||
val timestamps = ArrayList<Int>(selectedPositions.size)
|
||||
val eventsToDelete = ArrayList<ListEvent>(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<ListItem>(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()
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Int>, val callback: (allOccurrences: Boolean) -> Unit) {
|
||||
class DeleteEventDialog(val activity: Activity, eventIds: List<Int>, 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<Int>, 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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Account>()
|
||||
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<Account>()
|
||||
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<Event>): ArrayList<ListItem> {
|
|||
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<Int>, timestamps: List<Int>, 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Event>()
|
||||
private var allDayHolders = ArrayList<RelativeLayout>()
|
||||
private var allDayRows = ArrayList<HashSet<Int>>()
|
||||
|
@ -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<Event>) {
|
||||
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
|
||||
|
|
|
@ -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<Int>(colors.size())
|
||||
(0 until colors.size()).mapTo(sortedColors) { colors[it] }
|
||||
sortedColors = sortedColors.distinct() as ArrayList<Int>
|
||||
if (sortedColors.isNotEmpty()) {
|
||||
sortedColors = sortedColors.distinct() as ArrayList<Int>
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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<EventType>, 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<Int>
|
||||
|
@ -559,8 +576,9 @@ class DBHelper private constructor(val context: Context) : SQLiteOpenHelper(cont
|
|||
val deletedSet = HashSet<String>()
|
||||
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)
|
||||
|
|
|
@ -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<Event>)
|
||||
gotEvents(it)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ class MonthlyCalendarImpl(val mCallback: MonthlyCalendar, val mContext: Context)
|
|||
|
||||
private fun gotEvents(events: ArrayList<Event>) {
|
||||
mEvents = if (mFilterEventTypes) {
|
||||
mContext.getFilteredEvents(events) as ArrayList<Event>
|
||||
mContext.getFilteredEvents(events)
|
||||
} else {
|
||||
events
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<Event>
|
||||
mEvents = it
|
||||
mCallback.updateWeeklyCalendar(it)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Event>,
|
||||
var indexOnMonthView: Int) {
|
||||
}
|
||||
var indexOnMonthView: Int)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,9 +2,9 @@
|
|||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:bottom="0px"
|
||||
android:left="-2px"
|
||||
android:right="-2px"
|
||||
android:top="-2px">
|
||||
android:left="-1px"
|
||||
android:right="-1px"
|
||||
android:top="-1px">
|
||||
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@android:color/transparent"/>
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:bottom="0px"
|
||||
android:left="-2px"
|
||||
android:left="-1px"
|
||||
android:right="0px"
|
||||
android:top="-2px">
|
||||
android:top="-1px">
|
||||
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@android:color/transparent"/>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:bottom="-2px"
|
||||
android:left="-2px"
|
||||
android:bottom="-1px"
|
||||
android:left="-1px"
|
||||
android:right="0px"
|
||||
android:top="-2px">
|
||||
android:top="-1px">
|
||||
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@android:color/transparent"/>
|
||||
|
|
|
@ -600,7 +600,7 @@
|
|||
android:importantForAccessibility="no"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyTextView
|
||||
android:id="@+id/simple_font_size_label"
|
||||
android:id="@+id/widgets_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/bigger_margin"
|
||||
|
|
|
@ -39,6 +39,14 @@
|
|||
android:paddingTop="@dimen/normal_margin"
|
||||
android:text="@string/delete_one_only"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyCompatRadioButton
|
||||
android:id="@+id/delete_event_future"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/normal_margin"
|
||||
android:text="@string/delete_future_occurrences"/>
|
||||
|
||||
<com.simplemobiletools.commons.views.MyCompatRadioButton
|
||||
android:id="@+id/delete_event_all"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/event_item_start"
|
||||
android:includeFontPadding="false"
|
||||
android:text="15:00"
|
||||
android:textSize="@dimen/day_text_size"/>
|
||||
|
||||
|
@ -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"
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/event_item_frame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:foreground="@drawable/selector"
|
||||
android:paddingLeft="@dimen/activity_margin">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/event_item_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/activity_margin"
|
||||
android:paddingRight="@dimen/activity_margin"
|
||||
android:paddingTop="@dimen/small_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/event_item_start"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/day_text_size"
|
||||
tools:text="13:00"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/event_section_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/activity_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:textSize="@dimen/day_text_size"
|
||||
tools:text="Event title"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/event_item_color"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignBottom="@+id/event_section_title"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignTop="@+id/event_section_title"
|
||||
android:paddingRight="@dimen/medium_margin"
|
||||
android:src="@drawable/monthly_event_dot"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</FrameLayout>
|
|
@ -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">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/event_item_start"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/activity_margin"
|
||||
android:layout_marginLeft="@dimen/medium_margin"
|
||||
android:textSize="@dimen/day_text_size"
|
||||
tools:text="13:00"/>
|
||||
|
||||
|
@ -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"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
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_marginBottom="@dimen/medium_margin">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/event_item_start"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/medium_margin"
|
||||
android:textSize="@dimen/day_text_size"
|
||||
tools:text="13:00"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/event_section_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
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/small_margin"
|
||||
android:textSize="@dimen/day_text_size"
|
||||
tools:text="Event title"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/event_item_color"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignBottom="@+id/event_section_title"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignTop="@+id/event_section_title"
|
||||
android:paddingRight="@dimen/medium_margin"
|
||||
android:src="@drawable/monthly_event_dot"/>
|
||||
|
||||
</RelativeLayout>
|
|
@ -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"/>
|
||||
|
|
|
@ -5,12 +5,6 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/week_vertical_grid_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"/>
|
||||
|
||||
<com.simplemobiletools.calendar.views.MyScrollView
|
||||
android:id="@+id/week_events_scrollview"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -25,11 +19,10 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
<com.simplemobiletools.calendar.views.WeeklyViewGrid
|
||||
android:id="@+id/week_horizontal_grid_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/weekly_view_events_height"
|
||||
android:orientation="vertical"/>
|
||||
android:layout_height="@dimen/weekly_view_events_height"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/week_events_columns_holder"
|
||||
|
@ -95,6 +88,7 @@
|
|||
android:id="@+id/week_letters_holder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/stroke_bottom"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="@dimen/small_margin">
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ImageView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/stroke_bottom"/>
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ImageView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/stroke_right"/>
|
|
@ -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"/>
|
||||
|
||||
<ImageView
|
||||
|
@ -26,10 +26,10 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:paddingBottom="@dimen/medium_margin"
|
||||
android:paddingLeft="@dimen/normal_margin"
|
||||
android:paddingRight="@dimen/normal_margin"
|
||||
android:paddingTop="@dimen/normal_margin"
|
||||
android:paddingBottom="@dimen/small_margin"
|
||||
android:paddingLeft="@dimen/medium_margin"
|
||||
android:paddingRight="@dimen/medium_margin"
|
||||
android:paddingTop="@dimen/medium_margin"
|
||||
android:scaleType="fitCenter"
|
||||
android:src="@drawable/ic_plus"/>
|
||||
|
||||
|
@ -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"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widget_event_list_empty"
|
||||
|
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.6 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.5 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |