Major new version #2
@ -87,7 +87,7 @@ const vwm = createVirtualWeekManager({
|
||||
contentHeight,
|
||||
})
|
||||
const visibleWeeks = vwm.visibleWeeks
|
||||
const { scheduleWindowUpdate, resetWeeks } = vwm
|
||||
const { scheduleWindowUpdate, resetWeeks, refreshEvents } = vwm
|
||||
|
||||
// Scroll managers (after scheduleWindowUpdate available)
|
||||
const scrollManager = createScrollManager({ viewport, scheduleRebuild: scheduleWindowUpdate })
|
||||
@ -395,11 +395,17 @@ watch(
|
||||
watch(
|
||||
() => calendarStore.events,
|
||||
() => {
|
||||
resetWeeks('events')
|
||||
refreshEvents('events')
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
// Reflect selection & events by rebuilding day objects in-place
|
||||
watch(
|
||||
() => [selection.value.startDate, selection.value.dayCount],
|
||||
() => refreshEvents('selection'),
|
||||
)
|
||||
|
||||
// Rebuild if viewport height changes (e.g., resize)
|
||||
window.addEventListener('resize', () => {
|
||||
if (viewport.value) viewportHeight.value = viewport.value.clientHeight
|
||||
|
@ -69,17 +69,14 @@ export function createVirtualWeekManager({
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const dateStr = toLocalString(cur, DEFAULT_TZ)
|
||||
const collectEventsForDate = (dateStr, curDateObj) => {
|
||||
const storedEvents = []
|
||||
|
||||
for (const ev of calendarStore.events.values()) {
|
||||
if (!ev.isRepeating && dateStr >= ev.startDate && dateStr <= ev.endDate) {
|
||||
storedEvents.push(ev)
|
||||
}
|
||||
}
|
||||
const dayEvents = [...storedEvents]
|
||||
// Expand repeating events
|
||||
for (const base of repeatingBases) {
|
||||
if (dateStr >= base.startDate && dateStr <= base.endDate) {
|
||||
dayEvents.push({ ...base, _recurrenceIndex: 0, _baseId: base.id })
|
||||
@ -88,7 +85,7 @@ export function createVirtualWeekManager({
|
||||
const baseStart = fromLocalString(base.startDate, DEFAULT_TZ)
|
||||
const baseEnd = fromLocalString(base.endDate, DEFAULT_TZ)
|
||||
const spanDays = Math.max(0, differenceInCalendarDays(baseEnd, baseStart))
|
||||
const currentDate = fromLocalString(dateStr, DEFAULT_TZ)
|
||||
const currentDate = curDateObj
|
||||
let occurrenceFound = false
|
||||
for (let offset = 0; offset <= spanDays && !occurrenceFound; offset++) {
|
||||
const candidateStart = addDays(currentDate, -offset)
|
||||
@ -114,6 +111,12 @@ export function createVirtualWeekManager({
|
||||
}
|
||||
}
|
||||
}
|
||||
return dayEvents
|
||||
}
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const dateStr = toLocalString(cur, DEFAULT_TZ)
|
||||
const dayEvents = collectEventsForDate(dateStr, fromLocalString(dateStr, DEFAULT_TZ))
|
||||
const dow = cur.getDay()
|
||||
const isFirst = cur.getDate() === 1
|
||||
if (isFirst) {
|
||||
@ -281,6 +284,77 @@ export function createVirtualWeekManager({
|
||||
scheduleWindowUpdate(reason)
|
||||
}
|
||||
|
||||
// Reflective update of only events inside currently visible weeks (keeps week objects stable)
|
||||
function refreshEvents(reason = 'events-refresh') {
|
||||
if (!visibleWeeks.value.length) return
|
||||
const repeatingBases = []
|
||||
if (calendarStore.events) {
|
||||
for (const ev of calendarStore.events.values()) if (ev.isRepeating) repeatingBases.push(ev)
|
||||
}
|
||||
const selStart = selection.value.startDate
|
||||
const selCount = selection.value.dayCount
|
||||
const selEnd = selStart && selCount > 0 ? addDaysStr(selStart, selCount - 1) : null
|
||||
for (const week of visibleWeeks.value) {
|
||||
for (const day of week.days) {
|
||||
const dateStr = day.date
|
||||
// Update selection flag
|
||||
if (selStart && selEnd) day.isSelected = dateStr >= selStart && dateStr <= selEnd
|
||||
else day.isSelected = false
|
||||
// Rebuild events list for this day
|
||||
const storedEvents = []
|
||||
for (const ev of calendarStore.events.values()) {
|
||||
if (!ev.isRepeating && dateStr >= ev.startDate && dateStr <= ev.endDate) {
|
||||
storedEvents.push(ev)
|
||||
}
|
||||
}
|
||||
const dayEvents = [...storedEvents]
|
||||
for (const base of repeatingBases) {
|
||||
if (dateStr >= base.startDate && dateStr <= base.endDate) {
|
||||
dayEvents.push({ ...base, _recurrenceIndex: 0, _baseId: base.id })
|
||||
continue
|
||||
}
|
||||
const baseStart = fromLocalString(base.startDate, DEFAULT_TZ)
|
||||
const baseEnd = fromLocalString(base.endDate, DEFAULT_TZ)
|
||||
const spanDays = Math.max(0, differenceInCalendarDays(baseEnd, baseStart))
|
||||
const currentDate = fromLocalString(dateStr, DEFAULT_TZ)
|
||||
let occurrenceFound = false
|
||||
for (let offset = 0; offset <= spanDays && !occurrenceFound; offset++) {
|
||||
const candidateStart = addDays(currentDate, -offset)
|
||||
const candidateStartStr = toLocalString(candidateStart, DEFAULT_TZ)
|
||||
const occurrenceIndex = getOccurrenceIndex(base, candidateStartStr, DEFAULT_TZ)
|
||||
if (occurrenceIndex !== null) {
|
||||
const virtualEndDate = getVirtualOccurrenceEndDate(
|
||||
base,
|
||||
candidateStartStr,
|
||||
DEFAULT_TZ,
|
||||
)
|
||||
if (dateStr >= candidateStartStr && dateStr <= virtualEndDate) {
|
||||
const virtualId = base.id + '_v_' + candidateStartStr
|
||||
const alreadyExists = dayEvents.some((ev) => ev.id === virtualId)
|
||||
if (!alreadyExists) {
|
||||
dayEvents.push({
|
||||
...base,
|
||||
id: virtualId,
|
||||
startDate: candidateStartStr,
|
||||
endDate: virtualEndDate,
|
||||
_recurrenceIndex: occurrenceIndex,
|
||||
_baseId: base.id,
|
||||
})
|
||||
}
|
||||
occurrenceFound = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
day.events = dayEvents
|
||||
}
|
||||
}
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug('[VirtualWeeks] refreshEvents', reason, { weeks: visibleWeeks.value.length })
|
||||
}
|
||||
}
|
||||
|
||||
function goToToday() {
|
||||
const top = addDays(new Date(calendarStore.now), -21)
|
||||
const targetWeekIndex = getWeekIndex(top)
|
||||
@ -300,6 +374,7 @@ export function createVirtualWeekManager({
|
||||
scheduleWindowUpdate,
|
||||
resetWeeks,
|
||||
updateVisibleWeeks,
|
||||
refreshEvents,
|
||||
getWeekIndex,
|
||||
getFirstDayForVirtualWeek,
|
||||
goToToday,
|
||||
|
Loading…
x
Reference in New Issue
Block a user