]> git.ipfire.org Git - ipfire.org.git/commitdiff
accounts: Show all initials if no avatar is available
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 6 Jan 2024 17:02:53 +0000 (17:02 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 6 Jan 2024 17:02:53 +0000 (17:02 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/backend/accounts.py
src/web/users.py

index be791808fd2a99301e0bcb0fa1907ce8734427d5..beb4636dfa26bc89e6109a1eeeb9b3f519bc6331 100644 (file)
@@ -1029,6 +1029,30 @@ class Account(LDAPObject):
                if self.country_code:
                        return self.backend.get_country_name(self.country_code)
 
+       @property
+       def initials(self):
+               initials = []
+
+               # If a nickname is set, only use the nickname
+               if self.nickname:
+                       for m in re.findall(r"(\w+)", self.nickname):
+                               initials.append(m[0])
+
+               # Otherwise use the first and last name
+               else:
+                       if self.first_name:
+                               initials.append(self.first_name[0])
+
+                       if self.last_name:
+                               initials.append(self.last_name[0])
+
+               # Truncate to two initials
+               initials = initials[:2]
+
+               return [i.upper() for i in initials]
+
+       # Email
+
        @property
        def email(self):
                return self._get_string("mail")
index aaaca82551162f3925e06658c9037cb414e4de66..7867e9d632f16b8cb09845864e22d0210b513077 100644 (file)
@@ -10,6 +10,7 @@ import os.path
 import tornado.web
 
 from .. import countries
+from .. import util
 
 from . import base
 from . import ui_modules
@@ -92,7 +93,7 @@ class AvatarHandler(base.BaseHandler):
                self.finish(avatar)
 
        async def _get_avatar(self, account, size=None, **args):
-               letter = ("%s" % account)[0].upper()
+               letters = account.initials
 
                if size is None:
                        size = 256
@@ -101,51 +102,59 @@ class AvatarHandler(base.BaseHandler):
                if size >= 2048:
                        size = 2048
 
+               print("LETTERS", letters)
+
                # Cache key
-               key = "avatar:letter:%s:%s" % (letter, size)
+               key = "avatar:letter:%s:%s" % ("".join(letters), size)
 
                # Fetch avatar from the cache
-               avatar = await self.backend.cache.get(key)
+               #avatar = await self.backend.cache.get(key)
+               avatar = None
                if not avatar:
-                       avatar = self._make_avatar(letter, size=size, **args)
+                       avatar = self._make_avatar(letters, size=size, **args)
 
                        # Cache for forever
                        await self.backend.cache.set(key, avatar)
 
                return avatar
 
-       def _make_avatar(self, letter, format="PNG", size=None, **args):
-               # Generate an image of the correct size
-               image = PIL.Image.new("RGBA", (size, size), COLOUR_LIGHT)
-
-               # Have a canvas
-               draw = PIL.ImageDraw.Draw(image)
-
+       def _make_avatar(self, letters, format="PNG", size=None, **args):
                # Load font
                font = PIL.ImageFont.truetype(os.path.join(
                        self.application.settings.get("static_path", ""),
                        "fonts/Prompt-Bold.ttf"
                ), size, encoding="unic")
 
-               # Determine size of the printed letter
-               w, h = font.getsize(letter)
+               width = 0
+               height = 0
 
-               # Prompt seems to be very broken and the height needs to be corrected
-               h //= 0.7
+               for letter in letters:
+                       # Determine size of the printed letter
+                       w, h = font.getsize(letter)
 
-               # Draw the letter in the center
-               draw.text(((size - w) / 2, (size - h) / 2), letter,
-                       font=font, fill=COLOUR_DARK)
+                       # Store the maximum height
+                       height = max(h, height)
 
-               with io.BytesIO() as f:
-                       # If writing out the image does not work with optimization,
-                       # we try to write it out without any optimization.
-                       try:
-                               image.save(f, format, optimize=True, **args)
-                       except:
-                               image.save(f, format, **args)
+                       # Add up the width
+                       width += w
+
+               # Add the margin
+               width  = int(width  * 1.5)
+               height = int(height * 1.5)
+
+               print(width, height)
+
+               # Generate an image of the correct size
+               image = PIL.Image.new("RGBA", (width, height), COLOUR_LIGHT)
+
+               # Have a canvas
+               draw = PIL.ImageDraw.Draw(image)
+
+               # Draw the letter in the center
+               draw.text((width // 2, height // 2), "".join(letters),
+                       font=font, anchor="mm", fill=COLOUR_DARK)
 
-                       return f.getvalue()
+               return util.generate_thumbnail(image, size, square=True)
 
 
 class EditHandler(base.BaseHandler):