Skip to content

Commit

Permalink
fixup! perf: reduce number of avatar requests
Browse files Browse the repository at this point in the history
Signed-off-by: Hamza Mahjoubi <[email protected]>
  • Loading branch information
hamza221 committed Jan 12, 2025
1 parent 6f3086e commit 5dce0d1
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 9 deletions.
5 changes: 3 additions & 2 deletions lib/Contracts/IAvatarService.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ interface IAvatarService {
*
* @param string $email
* @param string $uid
* @return Avatar|null
* @param bool $cachedOnly
* @return Avatar|null|false the avatar if found, false if $cachedOnly is true and no value cached and null if not found
*/
public function getAvatar(string $email, string $uid): ?Avatar;
public function getAvatar(string $email, string $uid, bool $cachedOnly = false): mixed;

/**
* @param string $email
Expand Down
12 changes: 12 additions & 0 deletions lib/Db/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ class Message extends Entity implements JsonSerializable {

/** @var Avatar|null */
private $avatar;

/** @var bool*/
private $fetchAvatarFromClient = false;

public function __construct() {
$this->from = new AddressList([]);
$this->to = new AddressList([]);
Expand Down Expand Up @@ -297,6 +301,13 @@ public function setAvatar(?Avatar $avatar): void {
$this->avatar = $avatar;

Check warning on line 301 in lib/Db/Message.php

View check run for this annotation

Codecov / codecov/patch

lib/Db/Message.php#L300-L301

Added lines #L300 - L301 were not covered by tests
}

/**
* @param bool $fetchAvatarFromClient
*/
public function setFetchAvatarFromClient(bool $fetchAvatarFromClient): void {
$this->fetchAvatarFromClient = $fetchAvatarFromClient;

Check warning on line 308 in lib/Db/Message.php

View check run for this annotation

Codecov / codecov/patch

lib/Db/Message.php#L307-L308

Added lines #L307 - L308 were not covered by tests
}

/**
* @return Avatar
*/
Expand Down Expand Up @@ -349,6 +360,7 @@ static function (Tag $tag) {
'encrypted' => ($this->isEncrypted() === true),
'mentionsMe' => $this->getMentionsMe(),
'avatar' => $this->avatar ? $this->avatar->jsonSerialize() : null,
'fetchAvatarFromClient' => $this->fetchAvatarFromClient,

Check warning on line 363 in lib/Db/Message.php

View check run for this annotation

Codecov / codecov/patch

lib/Db/Message.php#L362-L363

Added lines #L362 - L363 were not covered by tests
];
}
}
9 changes: 8 additions & 1 deletion lib/IMAP/PreviewEnhancer.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use OCA\Mail\Db\MessageMapper as DbMapper;
use OCA\Mail\IMAP\MessageMapper as ImapMapper;
use OCA\Mail\Service\AvatarService;
use OCA\Mail\Service\Avatar\Avatar;
use Psr\Log\LoggerInterface;
use function array_key_exists;
use function array_map;
Expand Down Expand Up @@ -70,7 +71,13 @@ public function process(Account $account, Mailbox $mailbox, array $messages, boo
$from = $message->getFrom()->first();
if ($message->getAvatar() === null && $from !== null && $from->getEmail() !== null && $userId !== null) {
$avatar = $this->avatarService->getAvatar($from->getEmail(), $userId, true);
$message->setAvatar($avatar);
if ($avatar === false) {
$message->setFetchAvatarFromClient(true);

Check warning on line 75 in lib/IMAP/PreviewEnhancer.php

View check run for this annotation

Codecov / codecov/patch

lib/IMAP/PreviewEnhancer.php#L70-L75

Added lines #L70 - L75 were not covered by tests
}
if ($avatar instanceof Avatar) {
$message->setAvatar($avatar);

Check warning on line 78 in lib/IMAP/PreviewEnhancer.php

View check run for this annotation

Codecov / codecov/patch

lib/IMAP/PreviewEnhancer.php#L77-L78

Added lines #L77 - L78 were not covered by tests
}

}
}
}
Expand Down
12 changes: 9 additions & 3 deletions lib/Service/AvatarService.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,24 @@ private function hasAllowedMime(Avatar $avatar): bool {
/**
* @param string $email
* @param string $uid
* @return Avatar|null
* @param bool $cachedOnly
* @return Avatar|null|false
*/
public function getAvatar(string $email, string $uid, bool $cachedOnly = false): ?Avatar {
public function getAvatar(string $email, string $uid, bool $cachedOnly = false): mixed{
$cachedAvatar = $this->cache->get($email, $uid);
if ($cachedAvatar) {
return $cachedAvatar;
}
if ($cachedAvatar === false || $cachedOnly) {
if ($cachedAvatar === false) {
// We know there is no avatar
return null;
}

if($cachedOnly){
// We want to fetch the avatar from the frontend
return false;

Check warning on line 107 in lib/Service/AvatarService.php

View check run for this annotation

Codecov / codecov/patch

lib/Service/AvatarService.php#L107

Added line #L107 was not covered by tests
}

$avatar = $this->source->fetch($email, $this->avatarFactory, $this->externalAvatarsAllowed($uid));
if (is_null($avatar) || !$this->hasAllowedMime($avatar)) {
// Cannot locate any avatar -> nothing to do here
Expand Down
6 changes: 5 additions & 1 deletion src/components/Avatar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export default {
type: Object,
default: null,
},
fetchAvatar: {
type: Boolean,
default: false,
},
email: {
type: String,
required: true,
Expand Down Expand Up @@ -66,7 +70,7 @@ export default {
email: this.email,
})
: this.avatar.url
} else {
} else if (this.fetchAvatar) {
if (this.email !== '') {
try {
this.avatarUrl = await fetchAvatarUrlMemoized(this.email)
Expand Down
5 changes: 4 additions & 1 deletion src/components/Envelope.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,10 @@
<CheckIcon :size="40" class="check-icon" :class="{ 'app-content-list-item-avatar-selected': selected }" />
</template>
<template v-else>
<Avatar :display-name="addresses" :email="avatarEmail" :avatar="data.avatar" />
<Avatar :display-name="addresses"
:email="avatarEmail"
:fetch-avatar="data.fetchAvatarFromClient"
:avatar="data.avatar" />
</template>
</div>
</template>
Expand Down
5 changes: 4 additions & 1 deletion src/components/OutboxMessageListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
:details="details"
@click="openModal">
<template #icon>
<Avatar :display-name="avatarDisplayName" :email="avatarEmail" :avatar="message.avatar" />
<Avatar :display-name="avatarDisplayName"
:email="avatarEmail"
::fetch-avatar="data.fetchAvatarFromClient"
:avatar="message.avatar" />
</template>
<template #subname>
{{ subjectForSubtitle }}
Expand Down
1 change: 1 addition & 0 deletions src/components/ThreadEnvelope.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
:display-name="envelope.from[0].label"
:disable-tooltip="true"
:size="40"
:fetch-avatar="data.fetchAvatarFromClient"
:avatar="envelope.avatar"
class="envelope__header__avatar-avatar" />
<div v-if="isImportant"
Expand Down

0 comments on commit 5dce0d1

Please sign in to comment.