Actually render emoji in calendar event titles; stack duplicate shared events
Build and push server image / build-and-push (push) Successful in 53s
Build and push server image / build-and-push (push) Successful in 53s
The earlier fix stripped emoji instead of rendering them, which wasn't what was asked for. Event titles now draw with two fonts: the usual default font for text, and a vendored monochrome emoji font (Noto Emoji, OFL-1.1) for actual emoji runs, so they show up as real glyphs instead of a tofu box or nothing at all. Monochrome rather than color, since reliably rendering COLR/CBDT color glyphs depends on how Pillow's FreeType was built -- not something to depend on across deployments. Also: events sharing the exact same title and time across different calendars (e.g. a shared family event synced onto more than one person's calendar) now collapse into one row instead of showing twice, with a color bar split between every contributing calendar so it's still clear whose event it is.
This commit is contained in:
@@ -115,8 +115,18 @@ def merge_events(
|
||||
fetch_summary is "" when every source succeeded, else "N of M
|
||||
calendars unavailable" (never *which* source -- naming whose feed is
|
||||
down to everyone who looks at a shared household display is a bigger
|
||||
overshare than the outage itself)."""
|
||||
overshare than the outage itself).
|
||||
|
||||
Events sharing the exact same (summary, start, end, all_day) across
|
||||
different calendars -- e.g. a shared family event synced onto more
|
||||
than one person's calendar -- collapse into one entry rather than
|
||||
showing as duplicate rows. Every merged event carries a "sources"
|
||||
list ([{"owner_display_name", "color_index"}, ...], length 1 for an
|
||||
ordinary non-duplicated event) that calendar_render.py draws a
|
||||
color indicator per entry of, so a collapsed event still visibly
|
||||
shows every calendar it came from."""
|
||||
merged: list[dict] = []
|
||||
by_key: dict[tuple, dict] = {}
|
||||
failures = 0
|
||||
for source in sources:
|
||||
try:
|
||||
@@ -130,9 +140,15 @@ def merge_events(
|
||||
failures += 1
|
||||
continue
|
||||
for event in events:
|
||||
event["owner_display_name"] = source.owner_display_name
|
||||
event["color_index"] = source.color_index
|
||||
merged.append(event)
|
||||
source_entry = {"owner_display_name": source.owner_display_name, "color_index": source.color_index}
|
||||
key = (event["summary"], event["start"], event["end"], event["all_day"])
|
||||
existing = by_key.get(key)
|
||||
if existing is None:
|
||||
event["sources"] = [source_entry]
|
||||
by_key[key] = event
|
||||
merged.append(event)
|
||||
else:
|
||||
existing["sources"].append(source_entry)
|
||||
|
||||
merged.sort(key=lambda e: e["start"])
|
||||
summary = f"{failures} of {len(sources)} calendars unavailable" if failures else ""
|
||||
|
||||
Reference in New Issue
Block a user