diff options
author | Joas Schilling <coding@schilljs.com> | 2023-05-02 16:27:11 +0200 |
---|---|---|
committer | Joas Schilling <coding@schilljs.com> | 2023-05-02 16:27:11 +0200 |
commit | 3d28d93e175350eede30293cd475481bec6c865d (patch) | |
tree | 4dc446f5e45ef6235426685f56e100442233ebeb /lib | |
parent | 5e28cae6cc66bd11af0ed2893507bfeb3aadd17c (diff) |
feat(avatar): Use the first emoji of room names as avatar emoji
Signed-off-by: Joas Schilling <coding@schilljs.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Service/AvatarService.php | 74 |
1 files changed, 54 insertions, 20 deletions
diff --git a/lib/Service/AvatarService.php b/lib/Service/AvatarService.php index 0919f19f2..b6927ea44 100644 --- a/lib/Service/AvatarService.php +++ b/lib/Service/AvatarService.php @@ -35,33 +35,22 @@ use OCP\Files\SimpleFS\InMemoryFile; use OCP\Files\SimpleFS\ISimpleFile; use OCP\Files\SimpleFS\ISimpleFolder; use OCP\IAvatarManager; +use OCP\IEmojiHelper; use OCP\IL10N; use OCP\IURLGenerator; use OCP\IUser; use OCP\Security\ISecureRandom; class AvatarService { - private IAppData $appData; - private IL10N $l; - private IURLGenerator $url; - private ISecureRandom $random; - private RoomService $roomService; - private IAvatarManager $avatarManager; - public function __construct( - IAppData $appData, - IL10N $l, - IURLGenerator $url, - ISecureRandom $random, - RoomService $roomService, - IAvatarManager $avatarManager, + private IAppData $appData, + private IL10N $l, + private IURLGenerator $url, + private ISecureRandom $random, + private RoomService $roomService, + private IAvatarManager $avatarManager, + private IEmojiHelper $emojiHelper, ) { - $this->appData = $appData; - $this->l = $l; - $this->url = $url; - $this->random = $random; - $this->roomService = $roomService; - $this->avatarManager = $avatarManager; } public function setAvatarFromRequest(Room $room, ?array $file): void { @@ -148,6 +137,22 @@ class AvatarService { return $avatarFolder; } + /** + * https://github.com/sebdesign/cap-height -- for 500px height + * Automated check: https://codepen.io/skjnldsv/pen/PydLBK/ + * Noto Sans cap-height is 0.715 and we want a 200px caps height size + * (0.4 letter-to-total-height ratio, 500*0.4=200), so: 200/0.715 = 280px. + * Since we start from the baseline (text-anchor) we need to + * shift the y axis by 100px (half the caps height): 500/2+100=350 + * + * Copied from @see \OC\Avatar\Avatar::$svgTemplate with only `{font}` being modified + */ + private string $svgTemplate = '<?xml version="1.0" encoding="UTF-8" standalone="no"?> + <svg width="{size}" height="{size}" version="1.1" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg"> + <rect width="100%" height="100%" fill="#{fill}"></rect> + <text x="50%" y="350" style="font-weight:normal;font-size:280px;font-family:{font};text-anchor:middle;fill:#{fgFill}">{letter}</text> + </svg>'; + public function getAvatar(Room $room, ?IUser $user, bool $darkTheme = false): ISimpleFile { $token = $room->getToken(); $avatar = $room->getAvatar(); @@ -161,7 +166,6 @@ class AvatarService { } } - // Fallback if (!isset($file)) { $colorTone = $darkTheme ? 'dark' : 'bright'; @@ -174,6 +178,20 @@ class AvatarService { $file = $avatar->getFile(512, $darkTheme); } } + } elseif ($this->emojiHelper->isValidSingleEmoji(mb_substr($room->getName(), 0, 1))) { + $file = new InMemoryFile($token, str_replace([ + '{letter}', + '{size}', + '{fill}', + '{font}', + '{fgFill}', + ], [ + $this->getFirstCombinedEmoji($room->getName()), + 512, + $darkTheme ? '3B3B3B' : 'DBDBDB', + "'Segoe UI', Roboto, Oxygen-Sans, Cantarell, Ubuntu, 'Helvetica Neue', Arial, sans-serif, 'Noto Color Emoji', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Sans'", + '000', + ], $this->svgTemplate)); } elseif ($room->getType() === Room::TYPE_CHANGELOG) { $file = new InMemoryFile($token, file_get_contents(__DIR__ . '/../../img/changelog.svg')); } elseif ($room->getObjectType() === 'file') { @@ -193,6 +211,22 @@ class AvatarService { return $file; } + /** + * Get the first combined full emoji (including gender, skin tone, job, …) + * + * @param string $roomName + * @param int $length + * @return string + */ + protected function getFirstCombinedEmoji(string $roomName, int $length = 0): string { + $attempt = mb_substr($roomName, 0, $length + 1); + if ($this->emojiHelper->isValidSingleEmoji($attempt)) { + $longerAttempt = $this->getFirstCombinedEmoji($roomName, $length + 1); + return $longerAttempt ?: $attempt; + } + return ''; + } + public function deleteAvatar(Room $room): void { try { $folder = $this->appData->getFolder('room-avatar'); |