Fixed
-
A colour set on a CalDAV or Apple appointment now reaches the server (#897).
colorhas
always been one of the mirrored fields, so recolouring an appointment marked it for an outbound
push - butCOLORappeared exactly once in the whole server, inics-parser.js, where it is
read. Nothing ever wrote it. Every recolouring therefore cost a fullPUTround trip that
changed nothing on the server, and the field list claimed a mirroring that did not happen for two
of the three outbound providers. This was the promise from #815 that never got a thread of its own.Yuvomi now writes
COLOR(RFC 7986), the same property its parser already reads. The value is a
CSS3 colour name, not a hex code - §5.9 allows nothing else, and a strict server may reject a hex
value - so a stored#RRGGBBis mapped to the nearest of the 147 CSS3 names by the same
perceptual redmean distance that already maps colours onto Google's elevencolorIds. The loss is
small (the largest deviation across Yuvomi's own palette is 28 of 255 in a single channel) and it
stays on the wire: recolouring setscolor_modified = 1(#899), and an inbound run writescolor
only while that is0, so the neighbouring value read back on the next sync never overwrites the
choice.COLORis now a managed property of the ICS patcher - without that it may be written but not
replaced, and an emitted value would not have survived the patch. Freshly uploaded appointments
carry their colour from the start too, so one created in Yuvomi no longer arrives at the server
colourless.An appointment whose colour was never learned sends no
COLORfield at all - "leave it alone",
not "remove it". Anullthere would let a mere title change strip a colour somebody else chose on
the server. Telling that state apart from a deliberately cleared colour is what #899 below is
for; with it, clearing a colour reaches the provider as well. -
A title edit no longer freezes an appointment's colour, and a cleared colour now reaches the
provider (#899, migration 167).user_modifiedmeans "something about this appointment was
edited locally" - it is set on any edit to a mirrored appointment. All three inbound syncs read
it as "the colour is managed locally" and wrotecoloronly while it was0. Renaming an
appointment was therefore enough to freeze its colour column forever: if somebody coloured that
same appointment in Nextcloud, Apple Calendar or Google afterwards, Yuvomi never found out.The colour now carries a state of its own,
calendar_events.color_modified, set only when the
colour actually changes - re-sending the unchanged value with the rest of a form is not a
recolouring. Three things follow. Inbound gates on it, so an edit to any other field leaves the
colour open to the provider again.color IS NULL AND color_modified = 1is unambiguously
cleared, so the CalDAV/Apple outbound may remove theCOLORproperty and Google'scolorId: null
now goes out only for a colour somebody really cleared, rather than for every appointment without
one. And the upload paths record the flag when the appointment carries a colour, so the next
inbound run no longer replaces the chosen hex with the mapped one - both mappings are lossy (a
CSS3 name, or one of Google's elevencolorIds), and every colour in Yuvomi's palette maps to a
different hex.The backfill is deliberately conservative:
color_modified = user_modifiedfor existing rows.
Every colour protected today stays protected. A blanket0would undo exactly the bug described
here, but it would also let the next sync overwrite a colour somebody set on purpose - and in
existing data the two are indistinguishable. Resetting an ICS appointment to its original clears
both flags: the feed manages it again, colour included.