branch: externals/ebdb commit 2a87f5ed2a53e3a4e91e8c88ba5afc49f5e945df Author: Eric Abrahamsen <e...@ericabrahamsen.net> Commit: Eric Abrahamsen <e...@ericabrahamsen.net>
Fix one-primary-mail-per-record constraint Previously the constraint that each record have one and only one 'primary mail was enforced at the database level, but buggily. Move that constraint to ebdb-com: people can do what they like when interacting with the database. * ebdb-com.el (eieio-done-customizing): Move the mail-specific method from :after to :around, so it's nested inside the more general one. Now we don't have to redisplay. Match the edited mail by string: `equal' won't work because it's been edited. (ebdb-com-delete-field): New method specializing on mail fields. If we deleted the primary mail, make some other mail primary. * ebdb.el (ebdb-record-insert-field, ebdb-record-delete-field): Remove specializations for the mail field. This was buggy anyway, because `change-field' calls one and then the other, and you ended up with a mess. --- ebdb-com.el | 38 ++++++++++++++++++++++++++++++-------- ebdb.el | 22 ---------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/ebdb-com.el b/ebdb-com.el index 73e8ceb..538d530 100644 --- a/ebdb-com.el +++ b/ebdb-com.el @@ -1890,21 +1890,25 @@ commands, called from an *EBDB* buffer, and the lower-level (cl-defmethod eieio-done-customizing :around ((_field ebdb-field)) "Check that the record owning FIELD can be edited. -Also redisplays it after customization." +Also redisplay the record after customization." (let ((rec ebdb-customization-record)) (when rec (ebdb-with-record-edits rec (cl-call-next-method))))) -(cl-defmethod eieio-done-customizing :after ((mail ebdb-field-mail)) +(cl-defmethod eieio-done-customizing :around ((mail ebdb-field-mail)) "Handle mail priority after customizing. Check that some mail is marked as primary after MAIL is edited." (let* ((rec ebdb-customization-record) - (all-mails (remove mail (ebdb-record-mail rec t))) + (other-mails (seq-remove + (lambda (m) + (string-equal (ebdb-string mail) + (ebdb-string m))) + (ebdb-record-mail rec t))) (primaries (when rec (seq-filter (lambda (m) (eq (slot-value m 'priority) 'primary)) - all-mails))) + other-mails))) (prim (eq (slot-value mail 'priority) 'primary))) (cond ((and prim primaries) ;; MAIL is primary, so set all other primary mails to @@ -1912,13 +1916,13 @@ Check that some mail is marked as primary after MAIL is edited." (dolist (p primaries) (ebdb-record-change-field rec p (clone p :priority 'normal)))) ((and (null (or prim primaries)) - (car-safe all-mails)) + (car-safe other-mails)) ;; Nothing is primary, so try to set some other mail to ;; primary. (ebdb-record-change-field - rec (car all-mails) - (clone (car all-mails) :priority 'primary)))) - (ebdb-redisplay-records rec 'reformat))) + rec (car other-mails) + (clone (car other-mails) :priority 'primary)))) + (cl-call-next-method))) ;;;###autoload (defun ebdb-edit-foo (record field) @@ -2015,6 +2019,24 @@ confirm before deleting the field." (let ((person (ebdb-gethash (slot-value field 'record-uuid) 'uuid))) (ebdb-com-delete-field person field noprompt))) +(cl-defmethod ebdb-com-delete-field :after ((record ebdb-record-entity) + (mail ebdb-field-mail) + _noprompt) + "Possibly alter the priority of RECORD's remaining mails. +If there aren't any other primary mails, make the first of the +remaining mails primary." + (let* ((mails (seq-remove + (lambda (m) + (string-equal + (ebdb-string m) + (ebdb-string mail))) + (ebdb-record-mail record t))) + (clone (unless (object-assoc 'primary 'priority mails) + (when (car mails) + (clone (car mails) :priority 'primary))))) + (when clone + (ebdb-record-change-field record (car mails) clone)))) + ;;;###autoload (defun ebdb-delete-records (records &optional noprompt) "Delete RECORDS. diff --git a/ebdb.el b/ebdb.el index 3f8872f..ac63a12 100644 --- a/ebdb.el +++ b/ebdb.el @@ -3067,28 +3067,6 @@ If FIELD doesn't specify a year, use the current year." (cl-defmethod ebdb-record-organizations ((_record ebdb-record-entity)) nil) -(cl-defmethod ebdb-record-insert-field :before ((record ebdb-record-entity) - (mail ebdb-field-mail) - &optional _slot) - "Possibly set the priority of a newly-added mail address. -If RECORD has no other primary mail, set MAIL's priority to -primary." - (when (null (ebdb-record-one-mail record nil 'primary-only)) - (setf (slot-value mail 'priority) 'primary))) - -(cl-defmethod ebdb-record-delete-field :after ((record ebdb-record-entity) - (mail ebdb-field-mail) - &optional _slot) - "Possibly alter the priority of RECORD's remaining mails. -If there aren't any other primary mails, make the first of the -remaining mails primary." - (let* ((mails (remove mail (ebdb-record-mail record t))) - (clone (unless (object-assoc 'primary 'priority mails) - (when (car mails) - (clone (car mails) :priority 'primary))))) - (when clone - (ebdb-record-change-field record (car mails) clone)))) - (cl-defgeneric ebdb-compose-mail (records &rest args) "Prepare to compose a mail message to RECORDS. Mail-sending MUAs can override this method to do extra setup