Merge branch 'master' into open-day-from-weekly

This commit is contained in:
Naveen Singh
2024-11-14 19:50:07 +05:30
committed by GitHub
15 changed files with 255 additions and 59 deletions

View File

@@ -28,6 +28,7 @@ function log(toLog) {
*/
function getEvents(countryCode) {
const generator = new Holidays(countryCode);
generator.setTimezone("UTC");
const events = [];
for (let i = START_YEAR; i <= END_YEAR; i++) {
events.push(...generator.getHolidays(i).filter((x) => TYPE_WHITELIST.includes(x.type)));
@@ -54,7 +55,7 @@ function generateUid(countryCode, date, rule) {
* @returns
*/
function getDateArray(date) {
return [date.getFullYear(), date.getMonth() + 1, date.getDate()];
return [date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate()];
}
/**
@@ -79,9 +80,9 @@ async function generateIcal(events, countryCode) {
if (isFixedDate(x.rule)) {
const uid = generateUid(countryCode, "", x.rule);
if (!eventsMap.has(uid)) {
const yearDiff = x.end.getFullYear() - x.start.getFullYear();
x.start.setFullYear(FIXED_DATE_START_YEAR);
x.end.setFullYear(FIXED_DATE_START_YEAR + yearDiff);
const yearDiff = x.end.getUTCFullYear() - x.start.getUTCFullYear();
x.start.setUTCFullYear(FIXED_DATE_START_YEAR);
x.end.setUTCFullYear(FIXED_DATE_START_YEAR + yearDiff);
eventsMap.set(uid, {
title: x.name,
uid,

View File

@@ -21,5 +21,5 @@ jobs:
with:
token: ${{ github.token }}
# Number of days of inactivity before an issue is closed for lack of response.
daysUntilClose: 30
daysUntilClose: 14
responseRequiredLabel: waiting for author

View File

@@ -0,0 +1,128 @@
BEGIN:VCALENDAR
BEGIN:VEVENT
UID:bgd_1
DTSTART;VALUE=DATE:20250221
DTEND;VALUE=DATE:20250222
RRULE:FREQ=YEARLY;INTERVAL=1
SUMMARY:শহীদ দিবস
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_2
DTSTART;VALUE=DATE:20250317
DTEND;VALUE=DATE:20250318
RRULE:FREQ=YEARLY;INTERVAL=1
SUMMARY:শেখ মুজিবুর রহমানের জন্মদিন
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_3
DTSTART;VALUE=DATE:20250326
DTEND;VALUE=DATE:20250327
RRULE:FREQ=YEARLY;INTERVAL=1
SUMMARY:স্বাধীনতা দিবস
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_4
DTSTART;VALUE=DATE:20250414
DTEND;VALUE=DATE:20250415
RRULE:FREQ=YEARLY;INTERVAL=1
SUMMARY:পহেলা বৈশাখ
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_5
DTSTART;VALUE=DATE:20250501
DTEND;VALUE=DATE:20250502
RRULE:FREQ=YEARLY;INTERVAL=1
SUMMARY:মে দিবস
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_6
DTSTART;VALUE=DATE:20241216
DTEND;VALUE=DATE:20241217
RRULE:FREQ=YEARLY;INTERVAL=1
SUMMARY:বিজয় দিবস
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_7
DTSTART;VALUE=DATE:20241225
DTEND;VALUE=DATE:20241226
RRULE:FREQ=YEARLY;INTERVAL=1
SUMMARY:বড়দিন
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_8
DTSTART;VALUE=DATE:20250214
DTEND;VALUE=DATE:20250215
SUMMARY:শবে বরাত
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_9
DTSTART;VALUE=DATE:20250327
DTEND;VALUE=DATE:20250328
SUMMARY:শবে কদর
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_10
DTSTART;VALUE=DATE:20250328
DTEND;VALUE=DATE:20250329
SUMMARY:জুমাতুল বিদা
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_11
DTSTART;VALUE=DATE:20250331
DTEND;VALUE=DATE:20250403
SUMMARY:ঈদুল ফিতর
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_12
DTSTART;VALUE=DATE:20250505
DTEND;VALUE=DATE:20250506
SUMMARY:বুদ্ধ পূর্ণিমা
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_13
DTSTART;VALUE=DATE:20250606
DTEND;VALUE=DATE:20250509
SUMMARY:ঈদুল আজহা
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_14
DTSTART;VALUE=DATE:20250706
DTEND;VALUE=DATE:20250707
SUMMARY:আশুরা
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_15
DTSTART;VALUE=DATE:20250816
DTEND;VALUE=DATE:20250817
SUMMARY:জন্মাষ্টমী
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_16
DTSTART;VALUE=DATE:20250905
DTEND;VALUE=DATE:20250906
SUMMARY:ঈদে মিলাদুন্নবী
STATUS:CONFIRMED
END:VEVENT
BEGIN:VEVENT
UID:bgd_17
DTSTART;VALUE=DATE:20251002
DTEND;VALUE=DATE:20251003
SUMMARY:বিজয়া দশমী
STATUS:CONFIRMED
END:VEVENT
END:VCALENDAR

View File

@@ -415,11 +415,13 @@ class MainActivity : SimpleActivity(), RefreshRecyclerViewListener {
val eventIdToOpen = intent.getLongExtra(EVENT_ID, 0L)
val eventOccurrenceToOpen = intent.getLongExtra(EVENT_OCCURRENCE_TS, 0L)
val isTask = intent.getBooleanExtra(IS_TASK, false)
intent.removeExtra(EVENT_ID)
intent.removeExtra(EVENT_OCCURRENCE_TS)
intent.removeExtra(IS_TASK)
if (eventIdToOpen != 0L && eventOccurrenceToOpen != 0L) {
hideKeyboard()
Intent(this, EventActivity::class.java).apply {
Intent(this, getActivityToOpen(isTask)).apply {
putExtra(EVENT_ID, eventIdToOpen)
putExtra(EVENT_OCCURRENCE_TS, eventOccurrenceToOpen)
startActivity(this)

View File

@@ -18,6 +18,7 @@ class SplashActivity : BaseSplashActivity() {
intent.extras?.containsKey(EVENT_ID) == true -> Intent(this, MainActivity::class.java).apply {
putExtra(EVENT_ID, intent.getLongExtra(EVENT_ID, 0L))
putExtra(EVENT_OCCURRENCE_TS, intent.getLongExtra(EVENT_OCCURRENCE_TS, 0L))
putExtra(IS_TASK, intent.getBooleanExtra(IS_TASK, false))
startActivity(this)
}

View File

@@ -98,7 +98,7 @@ class EventListWidgetAdapter(val context: Context, val intent: Intent) : RemoteV
setText(R.id.event_item_time, "$timeText\n$descriptionText")
}
if (item.isTask && item.isTaskCompleted && dimCompletedTasks || dimPastEvents && item.isPastEvent) {
if (item.isTask && item.isTaskCompleted && dimCompletedTasks || dimPastEvents && item.isPastEvent && !item.isTask) {
curTextColor = weakTextColor
}
@@ -126,6 +126,7 @@ class EventListWidgetAdapter(val context: Context, val intent: Intent) : RemoteV
Intent().apply {
putExtra(EVENT_ID, item.id)
putExtra(EVENT_OCCURRENCE_TS, item.startTS)
putExtra(IS_TASK, item.isTask)
setOnClickFillInIntent(R.id.event_item_holder, this)
}
}

View File

@@ -138,7 +138,7 @@ class ManageEventTypesAdapter(
private fun askConfirmDelete() {
val eventTypes = eventTypes.filter { selectedKeys.contains(it.id?.toInt()) }.map { it.id } as ArrayList<Long>
activity.eventsHelper.doEventTypesContainEvents(eventTypes) {
activity.eventsHelper.doEventTypesContainEventsOrTasks(eventTypes) {
activity.runOnUiThread {
if (it) {
val res = activity.resources

View File

@@ -755,8 +755,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
private fun shouldAddEventOnTopBar(isAllDay: Boolean, startDayCode: String, endDayCode: String): Boolean {
val spansMultipleDays = startDayCode != endDayCode
val isSingleDayAllDayEvent = isAllDay && !spansMultipleDays
return isSingleDayAllDayEvent || (spansMultipleDays && config.showMidnightSpanningEventsAtTop)
return isAllDay || (spansMultipleDays && config.showMidnightSpanningEventsAtTop)
}
@SuppressLint("NewApi")

View File

@@ -40,6 +40,7 @@ const val SHORTCUT_NEW_TASK = "shortcut_new_task"
const val REGULAR_EVENT_TYPE_ID = 1L
const val TIME_ZONE = "time_zone"
const val CURRENT_TIME_ZONE = "current_time_zone"
const val IS_TASK = "is_task"
const val MONTHLY_VIEW = 1
const val YEARLY_VIEW = 2

View File

@@ -97,9 +97,9 @@ class EventsHelper(val context: Context) {
for (eventTypeId in deleteIds) {
if (deleteEvents) {
deleteEventsWithType(eventTypeId!!)
deleteEventsAndTasksWithType(eventTypeId!!)
} else {
eventsDB.resetEventsWithType(eventTypeId!!)
eventsDB.resetEventsAndTasksWithType(eventTypeId!!)
}
}
@@ -291,8 +291,8 @@ class EventsHelper(val context: Context) {
}
}
private fun deleteEventsWithType(eventTypeId: Long) {
val eventIds = eventsDB.getEventIdsByEventType(eventTypeId).toMutableList()
private fun deleteEventsAndTasksWithType(eventTypeId: Long) {
val eventIds = eventsDB.getEventAndTasksIdsByEventType(eventTypeId).toMutableList()
deleteEvents(eventIds, true)
}
@@ -317,9 +317,9 @@ class EventsHelper(val context: Context) {
}
}
fun doEventTypesContainEvents(eventTypeIds: ArrayList<Long>, callback: (contain: Boolean) -> Unit) {
fun doEventTypesContainEventsOrTasks(eventTypeIds: ArrayList<Long>, callback: (contain: Boolean) -> Unit) {
ensureBackgroundThread {
val eventIds = eventsDB.getEventIdsByEventType(eventTypeIds)
val eventIds = eventsDB.getEventAndTasksIdsByEventType(eventTypeIds)
callback(eventIds.isNotEmpty())
}
}

View File

@@ -367,7 +367,7 @@ fun getAllTimeZones() = arrayListOf(
MyTimeZone("GMT+5:30", "Asia/Kolkata"),
MyTimeZone("GMT+5:45", "Asia/Kathmandu"),
MyTimeZone("GMT+6", "Antarctica/Vostok"),
MyTimeZone("GMT+6", "Asia/Almaty"),
MyTimeZone("GMT+5", "Asia/Almaty"),
MyTimeZone("GMT+6", "Asia/Bishkek"),
MyTimeZone("GMT+6", "Asia/Dhaka"),
MyTimeZone("GMT+6", "Asia/Omsk"),

View File

@@ -140,7 +140,7 @@ class MyWidgetMonthlyProvider : AppWidgetProvider() {
val backgroundColor = it.color
var eventTextColor = backgroundColor.getContrastColor()
if (it.isTask() && it.isTaskCompleted() && dimCompletedTasks || !day.isThisMonth || (dimPastEvents && it.isPastEvent)) {
if (it.isTask() && it.isTaskCompleted() && dimCompletedTasks || !day.isThisMonth || (dimPastEvents && it.isPastEvent && !it.isTask())) {
eventTextColor = eventTextColor.adjustAlpha(MEDIUM_ALPHA)
}

View File

@@ -97,11 +97,11 @@ interface EventsDao {
@Query("SELECT id FROM events WHERE import_id LIKE :importId AND type = $TYPE_EVENT")
fun getEventIdWithLastImportId(importId: String): Long?
@Query("SELECT id FROM events WHERE event_type = :eventTypeId AND type = $TYPE_EVENT")
fun getEventIdsByEventType(eventTypeId: Long): List<Long>
@Query("SELECT id FROM events WHERE event_type = :eventTypeId")
fun getEventAndTasksIdsByEventType(eventTypeId: Long): List<Long>
@Query("SELECT id FROM events WHERE event_type IN (:eventTypeIds) AND type = $TYPE_EVENT")
fun getEventIdsByEventType(eventTypeIds: List<Long>): List<Long>
@Query("SELECT id FROM events WHERE event_type IN (:eventTypeIds)")
fun getEventAndTasksIdsByEventType(eventTypeIds: List<Long>): List<Long>
@Query("SELECT id FROM events WHERE parent_id IN (:parentIds)")
fun getEventIdsWithParentIds(parentIds: List<Long>): List<Long>
@@ -109,8 +109,8 @@ interface EventsDao {
@Query("SELECT id FROM events WHERE source = :source AND import_id != \"\" AND type = $TYPE_EVENT")
fun getCalDAVCalendarEvents(source: String): List<Long>
@Query("UPDATE events SET event_type = $REGULAR_EVENT_TYPE_ID WHERE event_type = :eventTypeId AND type = $TYPE_EVENT")
fun resetEventsWithType(eventTypeId: Long)
@Query("UPDATE events SET event_type = $REGULAR_EVENT_TYPE_ID WHERE event_type = :eventTypeId")
fun resetEventsAndTasksWithType(eventTypeId: Long)
@Query("UPDATE events SET import_id = :importId, source = :source WHERE id = :id AND type = $TYPE_EVENT")
fun updateEventImportIdAndSource(importId: String, source: String, id: Long)

View File

@@ -4,17 +4,29 @@ import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import org.fossify.calendar.R
import org.fossify.calendar.databinding.MonthViewBackgroundBinding
import org.fossify.calendar.databinding.MonthViewBinding
import org.fossify.calendar.extensions.config
import org.fossify.calendar.extensions.launchNewEventIntent
import org.fossify.calendar.extensions.launchNewTaskIntent
import org.fossify.calendar.helpers.COLUMN_COUNT
import org.fossify.calendar.helpers.Formatter
import org.fossify.calendar.helpers.ROW_COUNT
import org.fossify.calendar.helpers.TYPE_EVENT
import org.fossify.calendar.helpers.TYPE_TASK
import org.fossify.calendar.models.DayMonthly
import org.fossify.commons.compose.extensions.getActivity
import org.fossify.commons.dialogs.RadioGroupDialog
import org.fossify.commons.extensions.onGlobalLayout
import org.fossify.commons.models.RadioItem
// used in the Monthly view fragment, 1 view per screen
class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : FrameLayout(context, attrs, defStyle) {
class MonthViewWrapper(
context: Context,
attrs: AttributeSet,
defStyle: Int
) : FrameLayout(context, attrs, defStyle) {
private var dayWidth = 0f
private var dayHeight = 0f
private var weekDaysLetterHeight = 0
@@ -29,7 +41,8 @@ class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : F
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
init {
val normalTextSize = resources.getDimensionPixelSize(org.fossify.commons.R.dimen.normal_text_size).toFloat()
val normalTextSize =
resources.getDimensionPixelSize(org.fossify.commons.R.dimen.normal_text_size).toFloat()
weekDaysLetterHeight = 2 * normalTextSize.toInt()
inflater = LayoutInflater.from(context)
@@ -72,7 +85,12 @@ class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : F
val childRight = childLeft + childWidth
val childBottom = childTop + childHeight
child.layout(childLeft.toInt(), childTop.toInt(), childRight.toInt(), childBottom.toInt())
child.layout(
childLeft.toInt(),
childTop.toInt(),
childRight.toInt(),
childBottom.toInt()
)
if (curLeft + childWidth <= end) {
curLeft += childWidth
@@ -85,7 +103,11 @@ class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : F
}
}
fun updateDays(newDays: ArrayList<DayMonthly>, addEvents: Boolean, callback: ((DayMonthly) -> Unit)? = null) {
fun updateDays(
newDays: ArrayList<DayMonthly>,
addEvents: Boolean,
callback: ((DayMonthly) -> Unit)? = null
) {
setupHorizontalOffset()
measureSizes()
dayClickCallback = callback
@@ -128,7 +150,12 @@ class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : F
background = null
}
//Accessible label composed by day and month
contentDescription = "${day.value} ${Formatter.getMonthName(context, Formatter.getDateTimeFromCode(day.code).monthOfYear)}"
contentDescription = "${day.value} ${
Formatter.getMonthName(
context,
Formatter.getDateTimeFromCode(day.code).monthOfYear
)
}"
setOnClickListener {
dayClickCallback?.invoke(day)
@@ -138,6 +165,26 @@ class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : F
}
}
setOnLongClickListener {
if (context.config.allowCreatingTasks) {
val items = arrayListOf(
RadioItem(TYPE_EVENT, context.getString(R.string.event)),
RadioItem(TYPE_TASK, context.getString(R.string.task))
)
RadioGroupDialog(context.getActivity(), items) {
if (it == TYPE_EVENT) {
context.launchNewEventIntent(day.code)
} else {
context.launchNewTaskIntent(day.code)
}
}
} else {
context.launchNewEventIntent(day.code)
}
true
}
addView(this)
}
}

View File

@@ -9,40 +9,56 @@
android:id="@+id/widget_date_background"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignStart="@+id/widget_date"
android:layout_alignTop="@+id/widget_date"
android:layout_alignEnd="@+id/widget_date"
android:layout_alignBottom="@+id/widget_month"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:src="@drawable/widget_round_background"
tools:ignore="ContentDescription" />
<TextClock
android:id="@+id/widget_date"
<LinearLayout
android:id="@+id/widget_date_time_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:format12Hour="d"
android:format24Hour="d"
android:gravity="center"
android:includeFontPadding="false"
android:paddingTop="@dimen/medium_margin"
android:textColor="@color/md_grey_white"
android:textSize="26sp"
tools:text="1" />
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/small_margin"
android:paddingRight="@dimen/small_margin"
android:paddingBottom="@dimen/small_margin">
<TextClock
android:id="@+id/widget_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/widget_date"
android:layout_alignStart="@+id/widget_date"
android:layout_alignEnd="@+id/widget_date"
android:format12Hour="MMM"
android:format24Hour="MMM"
android:gravity="center"
android:includeFontPadding="false"
android:paddingBottom="@dimen/medium_margin"
android:textColor="@color/md_grey_white"
android:textSize="@dimen/bigger_text_size"
tools:text="Jan" />
<TextClock
android:id="@+id/widget_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:autoSizeMaxTextSize="300sp"
android:autoSizeMinTextSize="2sp"
android:autoSizeStepGranularity="1sp"
android:autoSizeTextType="uniform"
android:format12Hour="d"
android:format24Hour="d"
android:gravity="center"
android:includeFontPadding="false"
android:paddingTop="@dimen/medium_margin"
android:textColor="@color/md_grey_white"
android:textSize="26sp"
tools:text="1" />
<TextClock
android:id="@+id/widget_month"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:autoSizeMinTextSize="1sp"
android:autoSizeStepGranularity="1sp"
android:autoSizeTextType="uniform"
android:format12Hour="MMM"
android:format24Hour="MMM"
android:gravity="center"
android:includeFontPadding="false"
android:paddingBottom="@dimen/medium_margin"
android:textColor="@color/md_grey_white"
android:textSize="@dimen/bigger_text_size"
tools:text="Jan" />
</LinearLayout>
</RelativeLayout>