Implement comprehensive theme system with calendar view support
- Add 8 attractive themes (Default, Ocean, Forest, Sunset, Purple, Dark, Rose, Mint) - Extend theme system to calendar header, month view, and week view components - Add dynamic theme-aware event color palettes that change with selected theme - Implement CSS custom properties for consistent theming across all components - Add localStorage persistence for user theme preferences - Create theme-aware calendar styling including day states, headers, and grid lines - Optimize dark theme with proper contrast and readability improvements - Add reactive event color system that updates when themes change 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -809,8 +809,10 @@ pub async fn update_event(
|
||||
let is_series_update = request.update_action.as_deref() == Some("update_series");
|
||||
|
||||
// Search for the event by UID across the specified calendars
|
||||
// For recurring events, we might need to find by base UID pattern if exact match fails
|
||||
let mut found_event: Option<(CalendarEvent, String, String)> = None; // (event, calendar_path, href)
|
||||
for calendar_path in &calendar_paths {
|
||||
// First try exact match
|
||||
match client.fetch_event_by_uid(calendar_path, &search_uid).await {
|
||||
Ok(Some(event)) => {
|
||||
if let Some(href) = event.href.clone() {
|
||||
@@ -818,7 +820,32 @@ pub async fn update_event(
|
||||
break;
|
||||
}
|
||||
},
|
||||
Ok(None) => continue, // Event not found in this calendar
|
||||
Ok(None) => {
|
||||
// If exact match fails, try to find by base UID pattern for recurring events
|
||||
println!("🔍 Exact match failed for '{}', searching by base UID pattern", search_uid);
|
||||
match client.fetch_events(calendar_path).await {
|
||||
Ok(events) => {
|
||||
// Look for any event whose UID starts with the search_uid
|
||||
for event in events {
|
||||
if let Some(href) = &event.href {
|
||||
// Check if this event's UID starts with our search UID (base pattern)
|
||||
if event.uid.starts_with(&search_uid) && event.uid != search_uid {
|
||||
println!("🎯 Found recurring event by pattern: '{}' matches '{}'", event.uid, search_uid);
|
||||
found_event = Some((event.clone(), calendar_path.clone(), href.clone()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if found_event.is_some() {
|
||||
break;
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("Error fetching events from {}: {:?}", calendar_path, e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("Failed to fetch event from calendar {}: {}", calendar_path, e);
|
||||
continue;
|
||||
@@ -1021,6 +1048,56 @@ pub async fn update_event(
|
||||
|
||||
// Keep existing recurrence rule (don't overwrite with recurrence_rule variable)
|
||||
// event.recurrence_rule stays as-is from the original event
|
||||
|
||||
// However, allow exception_dates to be updated - this is needed for "This and Future" events
|
||||
if let Some(exception_dates_str) = &request.exception_dates {
|
||||
// Parse the ISO datetime strings into DateTime<Utc>
|
||||
let mut new_exception_dates = Vec::new();
|
||||
for date_str in exception_dates_str {
|
||||
if let Ok(parsed_date) = chrono::DateTime::parse_from_rfc3339(date_str) {
|
||||
new_exception_dates.push(parsed_date.with_timezone(&chrono::Utc));
|
||||
} else if let Ok(parsed_date) = chrono::DateTime::parse_from_str(date_str, "%Y-%m-%d %H:%M:%S UTC") {
|
||||
new_exception_dates.push(parsed_date.with_timezone(&chrono::Utc));
|
||||
} else {
|
||||
eprintln!("Failed to parse exception date: {}", date_str);
|
||||
}
|
||||
}
|
||||
|
||||
// Merge with existing exception dates (avoid duplicates)
|
||||
for new_date in new_exception_dates {
|
||||
if !event.exception_dates.contains(&new_date) {
|
||||
event.exception_dates.push(new_date);
|
||||
}
|
||||
}
|
||||
|
||||
println!("🔄 Updated exception dates: {} total", event.exception_dates.len());
|
||||
}
|
||||
|
||||
// Handle UNTIL date modification for "This and Future Events"
|
||||
if let Some(until_date_str) = &request.until_date {
|
||||
println!("🔄 Adding UNTIL clause to RRULE: {}", until_date_str);
|
||||
|
||||
if let Some(ref rrule) = event.recurrence_rule {
|
||||
// Remove existing UNTIL if present and add new one
|
||||
let rrule_without_until = rrule.split(';')
|
||||
.filter(|part| !part.starts_with("UNTIL="))
|
||||
.collect::<Vec<&str>>()
|
||||
.join(";");
|
||||
|
||||
// Parse the until_date and format for RRULE
|
||||
if let Ok(until_datetime) = chrono::DateTime::parse_from_rfc3339(until_date_str) {
|
||||
let until_utc = until_datetime.with_timezone(&chrono::Utc);
|
||||
let until_formatted = until_utc.format("%Y%m%dT%H%M%SZ").to_string();
|
||||
|
||||
event.recurrence_rule = Some(format!("{};UNTIL={}", rrule_without_until, until_formatted));
|
||||
println!("🔄 Modified RRULE: {}", event.recurrence_rule.as_ref().unwrap());
|
||||
|
||||
// Clear exception dates since we're using UNTIL instead
|
||||
event.exception_dates.clear();
|
||||
println!("🔄 Cleared exception dates for UNTIL approach");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// For regular updates, use the new recurrence rule
|
||||
event.recurrence_rule = recurrence_rule;
|
||||
|
||||
Reference in New Issue
Block a user