Release Notes Architecture - Component refactor: removed monoliths (`Calendar.vue`, `CalendarGrid.vue`); expanded granular view + header/control components. - Dialog system introduced (`BaseDialog`, `SettingsDialog`). State & Data - Store redesigned: Map-based events + recurrence map; mutation counters. - Local persistence + undo/redo history (custom plugins). Date & Holidays - Migrated all date logic to `date-fns` (+ tz). - Added national holiday support (toggle + loading utilities). Recurrence & Events - Consolidated recurrence handling; fixes for monthly edge days (29–31), annual, multi‑day, and complex weekly repeats. - Reliable splitting/moving/resizing/deletion of repeating and multi‑day events. Interaction & UX - Double‑tap to create events; improved drag (multi‑day + position retention). - Scroll & inertial/momentum navigation; year change via numeric scroller. - Movable event dialog; live settings application. Performance - Progressive / virtual week rendering, reduced off‑screen buffer. - Targeted repaint strategy; minimized full re-renders. Plugins Added - History, undo normalization, persistence, scroll manager, virtual weeks. Styling & Layout - Responsive + compact layout refinements; header restructured. - Simplified visual elements (removed dots/overflow text); holiday styling adjustments. Reliability / Fixes - Numerous recurrence, deletion, orientation/rotation, and event indexing corrections. - Cross-browser fallback (Firefox week info). Dependencies Added - date-fns, date-fns-tz, date-holidays, pinia-plugin-persistedstate. Net Change - 28 files modified; ~4.4K insertions / ~2.2K deletions (major refactor + feature set).
		
			
				
	
	
		
			25 lines
		
	
	
		
			764 B
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			25 lines
		
	
	
		
			764 B
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // Simple Pinia persistence plugin supporting `persist: true` and Map serialization.
 | |
| export function persistPlugin({ store }) {
 | |
|   if (!store.$options || !store.$options.persist) return
 | |
|   const key = `pinia-${store.$id}`
 | |
|   try {
 | |
|     const raw = localStorage.getItem(key)
 | |
|     if (raw) {
 | |
|       const state = JSON.parse(raw, (k, v) => {
 | |
|         if (v && v.__map === true && Array.isArray(v.data)) return new Map(v.data)
 | |
|         return v
 | |
|       })
 | |
|       store.$patch(state)
 | |
|     }
 | |
|   } catch {}
 | |
|   store.$subscribe((_mutation, state) => {
 | |
|     try {
 | |
|       const json = JSON.stringify(state, (_k, v) => {
 | |
|         if (v instanceof Map) return { __map: true, data: Array.from(v.entries()) }
 | |
|         return v
 | |
|       })
 | |
|       localStorage.setItem(key, json)
 | |
|     } catch {}
 | |
|   })
 | |
| }
 |