From 5bab72b8be9dee66dfd8b11e609247797acf1846 Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 27 Jan 2023 10:34:40 -0700 Subject: [PATCH] Use client-side Et2LAvatar for user accounts whenever possible, only using avatar.php when there's a real image. TODO: - Need to find a cheap way to determine if there's a real image in Api/src/Accounts.php & class.mail_compose.inc.php - Still some work for me to do in Et2SelectEmail --- api/js/etemplate/Et2Select/Et2Select.ts | 28 ++++++++++--- .../etemplate/Et2Select/Et2SelectAccount.ts | 39 +++++++++++++++++-- api/src/Accounts.php | 16 ++++++-- api/src/Contacts.php | 4 +- mail/inc/class.mail_compose.inc.php | 19 ++++++--- 5 files changed, 86 insertions(+), 20 deletions(-) diff --git a/api/js/etemplate/Et2Select/Et2Select.ts b/api/js/etemplate/Et2Select/Et2Select.ts index a3ed5fcf65..0653b73f8a 100644 --- a/api/js/etemplate/Et2Select/Et2Select.ts +++ b/api/js/etemplate/Et2Select/Et2Select.ts @@ -424,15 +424,13 @@ export class Et2Select extends Et2WithSearchMixin(Et2WidgetWithSelect) _optionTemplate(option : SelectOption) : TemplateResult { - let icon = option.icon ? html` - ` : ""; - // Tag used must match this.optionTag, but you can't use the variable directly. // Pass option along so SearchMixin can grab it if needed return html` - - ${icon} + + ${this._iconTemplate(option)} ${this.noLang ? option.label : this.egw().lang(option.label)} `; } @@ -502,6 +500,24 @@ export class Et2Select extends Et2WithSearchMixin(Et2WidgetWithSelect) return tag; } + /** + * Get the icon for the select option + * + * @param option + * @protected + */ + protected _iconTemplate(option) + { + if(!option.icon) + { + return html``; + } + + return html` + ` + } + protected _createImage(item) { let image = item.querySelector("et2-image"); diff --git a/api/js/etemplate/Et2Select/Et2SelectAccount.ts b/api/js/etemplate/Et2Select/Et2SelectAccount.ts index 8827a27cab..2a23fafbf8 100644 --- a/api/js/etemplate/Et2Select/Et2SelectAccount.ts +++ b/api/js/etemplate/Et2Select/Et2SelectAccount.ts @@ -12,6 +12,7 @@ import {cleanSelectOptions, SelectOption} from "./FindSelectOptions"; import {Et2Image} from "../Et2Image/Et2Image"; import {SelectAccountMixin} from "./SelectAccountMixin"; import {Et2StaticSelectMixin} from "./StaticOptions"; +import {html, nothing} from "@lion/core"; export type AccountType = 'accounts'|'groups'|'both'|'owngroups'; @@ -115,6 +116,26 @@ export class Et2SelectAccount extends SelectAccountMixin(Et2StaticSelectMixin(Et super.select_options = new_options; } + /** + * Override icon for the select option + * + * @param option + * @protected + */ + protected _iconTemplate(option) + { + // lavatar uses a size property, not a CSS variable + let style = getComputedStyle(this); + + return html` + + `; + } + /** * Override the prefix image for tags (multiple=true) * The default is probably fine, but we're being explicit here. @@ -125,11 +146,23 @@ export class Et2SelectAccount extends SelectAccountMixin(Et2StaticSelectMixin(Et */ protected _createImage(item) : Et2Image { - const image = super._createImage(item); - if(image) + const image = document.createElement("et2-lavatar"); + image.contactId = item.value; + if(item.lname) { - image.src = "/egroupware/api/avatar.php?account_id=" + item.value + "&etag=1"; + image.lname = item.lname; } + if(item.fname) + { + image.fname = item.fname; + } + + // If there's an actual image associated with the account, use that image instead of initials + if(item.src) + { + image.src = item.src; + } + return image; } } diff --git a/api/src/Accounts.php b/api/src/Accounts.php index 2da0c6d3c8..fe08e2f845 100644 --- a/api/src/Accounts.php +++ b/api/src/Accounts.php @@ -439,14 +439,22 @@ class Accounts if (!empty($options['tag_list'])) { - $accounts[] = [ + $result = [ 'value' => $account['account_id'], 'label' => $displayName, - 'icon' => Framework::link('/api/avatar.php', [ + // Send what lavatar needs to skip a server-side request + 'lname' => $account['account_id'] < 0 ? $account['account_lid'] : $account['account_lastname'], + 'fname' => $account['account_id'] < 0 ? lang('group') : $account['account_firstname'] + ]; + // TODO: Ralf find a cheap way to get this + if($actual_picture) + { + $result['icon'] = Framework::link('/api/avatar.php', [ 'account_id' => $account['account_id'], 'modified' => $account['account_modified'], - ]), - ]; + ]); + } + $accounts[] = $result; } else { diff --git a/api/src/Contacts.php b/api/src/Contacts.php index f6e543092b..998127a959 100755 --- a/api/src/Contacts.php +++ b/api/src/Contacts.php @@ -1705,7 +1705,9 @@ class Contacts extends Contacts\Storage if ($contact['cat_id'] && ($color = Categories::cats2color($contact['cat_id']))) { $result[$contact['id']] = array( - 'label' => $result[$contact['id']], + 'lname' => $contact['n_family'], + 'fname' => $contact['n_given'], + 'label' => $result[$contact['id']], 'style.backgroundColor' => $color, ); } diff --git a/mail/inc/class.mail_compose.inc.php b/mail/inc/class.mail_compose.inc.php index 00048bc728..f051a06943 100644 --- a/mail/inc/class.mail_compose.inc.php +++ b/mail/inc/class.mail_compose.inc.php @@ -3692,17 +3692,24 @@ class mail_compose $args[] = trim($contact['n_fn'] ? $contact['n_fn'] : $contact['fn']); $completeMailString = call_user_func_array('imap_rfc822_write_address', $args); if(!empty($email) && in_array($completeMailString ,$results) === false) { - $results[] = array( + $result = array( 'value' => $completeMailString, 'label' => $completeMailString, // Add just name for nice display, with title for hover - 'name' => $contact['n_fn'], + 'name' => $contact['n_fn'], 'title' => $email, - 'icon' => Egw::link('/api/avatar.php', array( + 'lname' => $contact['n_family'], + 'fname' => $contact['n_given'] + ); + // TODO: Ralf find a cheap way to get this + if($actual_picture) + { + $result['icon'] = Egw::link('/api/avatar.php', array( 'contact_id' => $contact['id'], - 'etag' => $contact['etag'] - )) - ); + 'etag' => $contact['etag'] + )); + } + $results[] = $result; } } }