Mouse/touch event handling improvement
- prefer passive handlers - fix event moving on touch - faster selection updates
This commit is contained in:
parent
ecae48fd85
commit
5a0d6804bc
@ -248,7 +248,7 @@ function onGlobalTouchMove(e) {
|
|||||||
if (!isDragging.value) return
|
if (!isDragging.value) return
|
||||||
const t = e.touches && e.touches[0]
|
const t = e.touches && e.touches[0]
|
||||||
if (!t) return
|
if (!t) return
|
||||||
e.preventDefault()
|
if (e.cancelable) e.preventDefault()
|
||||||
const dateStr = getDateUnderPoint(t.clientX, t.clientY)
|
const dateStr = getDateUnderPoint(t.clientX, t.clientY)
|
||||||
if (dateStr) updateDrag(dateStr)
|
if (dateStr) updateDrag(dateStr)
|
||||||
}
|
}
|
||||||
@ -435,10 +435,11 @@ function buildSearchResults() {
|
|||||||
|
|
||||||
watch(searchQuery, buildSearchResults)
|
watch(searchQuery, buildSearchResults)
|
||||||
watch(
|
watch(
|
||||||
() => calendarStore.eventsMutation,
|
() => calendarStore.events,
|
||||||
() => {
|
() => {
|
||||||
if (searchOpen.value && searchQuery.value.trim()) buildSearchResults()
|
if (searchOpen.value && searchQuery.value.trim()) buildSearchResults()
|
||||||
},
|
},
|
||||||
|
{ deep: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
function openSearch(prefill = '') {
|
function openSearch(prefill = '') {
|
||||||
@ -569,19 +570,22 @@ watch(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Event changes
|
// Event changes (optimized): react to mutation counter & targeted range payload
|
||||||
watch(
|
watch(
|
||||||
() => calendarStore.events,
|
() => calendarStore.events,
|
||||||
() => {
|
() => refreshEvents('events'),
|
||||||
refreshEvents('events')
|
|
||||||
},
|
|
||||||
{ deep: true },
|
{ deep: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reflect selection & events by rebuilding day objects in-place
|
// Reflect selection & events by rebuilding day objects in-place
|
||||||
watch(
|
watch(
|
||||||
() => [selection.value.startDate, selection.value.dayCount],
|
() => [selection.value.startDate, selection.value.dayCount],
|
||||||
() => refreshEvents('selection'),
|
([start, count]) => {
|
||||||
|
const hasSel = !!start && !!count && count > 0
|
||||||
|
const end = hasSel ? addDaysStr(start, count, DEFAULT_TZ) : null
|
||||||
|
for (const w of visibleWeeks.value)
|
||||||
|
for (const d of w.days) d.isSelected = hasSel && d.date >= start && d.date < end
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Rebuild if viewport height changes (e.g., resize)
|
// Rebuild if viewport height changes (e.g., resize)
|
||||||
|
@ -57,7 +57,7 @@ function shouldRotateMonth(label) {
|
|||||||
@mousedown="handleDayMouseDown(day.date)"
|
@mousedown="handleDayMouseDown(day.date)"
|
||||||
@mouseenter="handleDayMouseEnter(day.date)"
|
@mouseenter="handleDayMouseEnter(day.date)"
|
||||||
@mouseup="handleDayMouseUp(day.date)"
|
@mouseup="handleDayMouseUp(day.date)"
|
||||||
@touchstart="handleDayTouchStart(day.date)"
|
@touchstart.passive="handleDayTouchStart(day.date)"
|
||||||
/>
|
/>
|
||||||
<EventOverlay :week="props.week" @event-click="handleEventClick" />
|
<EventOverlay :week="props.week" @event-click="handleEventClick" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -278,9 +278,7 @@ function startLocalDrag(init, evt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(evt.pointerType === 'touch')) {
|
if (evt.cancelable) evt.preventDefault()
|
||||||
evt.preventDefault()
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('pointermove', onDragPointerMove, { passive: false })
|
window.addEventListener('pointermove', onDragPointerMove, { passive: false })
|
||||||
window.addEventListener('pointerup', onDragPointerUp, { passive: false })
|
window.addEventListener('pointerup', onDragPointerUp, { passive: false })
|
||||||
@ -486,6 +484,8 @@ function applyRangeDuringDrag(st, startDate, endDate) {
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
/* Ensure touch pointer events aren't turned into a scroll gesture; needed for reliable drag on mobile */
|
||||||
|
touch-action: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Inner title wrapper ensures proper ellipsis within flex/grid constraints */
|
/* Inner title wrapper ensures proper ellipsis within flex/grid constraints */
|
||||||
@ -510,6 +510,7 @@ function applyRangeDuringDrag(st, startDate, endDate) {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
cursor: ew-resize;
|
cursor: ew-resize;
|
||||||
|
touch-action: none; /* Allow touch resizing without scroll */
|
||||||
}
|
}
|
||||||
|
|
||||||
.event-span .resize-handle.left {
|
.event-span .resize-handle.left {
|
||||||
|
@ -18,7 +18,6 @@ function restoreCalendarState(store, snap) {
|
|||||||
store.weekend = Array.isArray(snap.weekend) ? [...snap.weekend] : snap.weekend
|
store.weekend = Array.isArray(snap.weekend) ? [...snap.weekend] : snap.weekend
|
||||||
store.config = JSON.parse(JSON.stringify(snap.config))
|
store.config = JSON.parse(JSON.stringify(snap.config))
|
||||||
store.events = new Map([...snap.events].map(([k, v]) => [k, { ...v }]))
|
store.events = new Map([...snap.events].map(([k, v]) => [k, { ...v }]))
|
||||||
store.eventsMutation = (store.eventsMutation + 1) % 1_000_000_000
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function calendarHistory({ store }) {
|
export function calendarHistory({ store }) {
|
||||||
@ -36,8 +35,7 @@ export function calendarHistory({ store }) {
|
|||||||
|
|
||||||
function serializeForComparison() {
|
function serializeForComparison() {
|
||||||
const evCount = store.events instanceof Map ? store.events.size : 0
|
const evCount = store.events instanceof Map ? store.events.size : 0
|
||||||
const em = store.eventsMutation || 0
|
return `${evCount}|${store.today}|${JSON.stringify(store.config)}`
|
||||||
return `${em}|${evCount}|${store.today}|${JSON.stringify(store.config)}`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function pushSnapshot() {
|
function pushSnapshot() {
|
||||||
|
@ -124,7 +124,6 @@ function createMomentumDrag({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
applyDragPosition(e.touches[0].clientY, reasonDragTouch)
|
applyDragPosition(e.touches[0].clientY, reasonDragTouch)
|
||||||
e.preventDefault()
|
|
||||||
}
|
}
|
||||||
function handlePointerDown(e) {
|
function handlePointerDown(e) {
|
||||||
if (e.button !== undefined && e.button !== 0) return
|
if (e.button !== undefined && e.button !== 0) return
|
||||||
@ -158,7 +157,7 @@ function createMomentumDrag({
|
|||||||
window.addEventListener('touchmove', onTouchMove, { passive: false })
|
window.addEventListener('touchmove', onTouchMove, { passive: false })
|
||||||
window.addEventListener('touchend', endDrag, { passive: false })
|
window.addEventListener('touchend', endDrag, { passive: false })
|
||||||
window.addEventListener('touchcancel', endDrag, { passive: false })
|
window.addEventListener('touchcancel', endDrag, { passive: false })
|
||||||
e.preventDefault()
|
if (e.cancelable) e.preventDefault()
|
||||||
}
|
}
|
||||||
function onPointerLockChange() {
|
function onPointerLockChange() {
|
||||||
const lockedEl = document.pointerLockElement
|
const lockedEl = document.pointerLockElement
|
||||||
|
@ -14,9 +14,6 @@ export const useCalendarStore = defineStore('calendar', {
|
|||||||
today: toLocalString(new Date(), DEFAULT_TZ),
|
today: toLocalString(new Date(), DEFAULT_TZ),
|
||||||
now: new Date().toISOString(),
|
now: new Date().toISOString(),
|
||||||
events: new Map(),
|
events: new Map(),
|
||||||
// Lightweight mutation counter so views can rebuild in a throttled / idle way
|
|
||||||
// without tracking deep reactivity on every event object.
|
|
||||||
eventsMutation: 0,
|
|
||||||
// Incremented internally by history plugin to force reactive updates for canUndo/canRedo
|
// Incremented internally by history plugin to force reactive updates for canUndo/canRedo
|
||||||
historyTick: 0,
|
historyTick: 0,
|
||||||
historyCanUndo: false,
|
historyCanUndo: false,
|
||||||
@ -117,10 +114,7 @@ export const useCalendarStore = defineStore('calendar', {
|
|||||||
return 'e-' + Math.random().toString(36).slice(2, 10) + '-' + Date.now().toString(36)
|
return 'e-' + Math.random().toString(36).slice(2, 10) + '-' + Date.now().toString(36)
|
||||||
},
|
},
|
||||||
|
|
||||||
notifyEventsChanged() {
|
notifyEventsChanged() {},
|
||||||
// Bump simple counter (wrapping to avoid overflow in extreme long sessions)
|
|
||||||
this.eventsMutation = (this.eventsMutation + 1) % 1_000_000_000
|
|
||||||
},
|
|
||||||
touchEvents() {
|
touchEvents() {
|
||||||
this.notifyEventsChanged()
|
this.notifyEventsChanged()
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user