feat(frontend): replace placeholder avatar with identicons
i don't actually know what the license on the kitten image is, and while it's very unlikely, i don't want to get into legal trouble. it was only ever supposed to be a temporary image, too. identicons aren't the prettiest but at least they have a clear license :3
This commit is contained in:
parent
71d3b42330
commit
74222ead45
10 changed files with 37 additions and 6 deletions
|
@ -42,6 +42,7 @@
|
|||
"bootstrap-icons": "^1.11.3",
|
||||
"luxon": "^3.5.0",
|
||||
"markdown-it": "^14.1.0",
|
||||
"minidenticons": "^4.2.1",
|
||||
"pretty-bytes": "^6.1.1",
|
||||
"sanitize-html": "^2.13.1",
|
||||
"svelte-tippy": "^1.3.2",
|
||||
|
|
|
@ -23,6 +23,9 @@ importers:
|
|||
markdown-it:
|
||||
specifier: ^14.1.0
|
||||
version: 14.1.0
|
||||
minidenticons:
|
||||
specifier: ^4.2.1
|
||||
version: 4.2.1
|
||||
pretty-bytes:
|
||||
specifier: ^6.1.1
|
||||
version: 6.1.1
|
||||
|
@ -1110,6 +1113,10 @@ packages:
|
|||
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
|
||||
engines: {node: '>=8.6'}
|
||||
|
||||
minidenticons@4.2.1:
|
||||
resolution: {integrity: sha512-oWfFivA0lOx/V/bO/YIJbthB26lV8JXYvhnv9zM2hNd3fzsHTXQ6c6bWZPcvhD3nnOB+lQk/D9lF43BXixrN8g==}
|
||||
engines: {node: '>=15.14.0'}
|
||||
|
||||
minimatch@3.1.2:
|
||||
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
||||
|
||||
|
@ -2369,6 +2376,8 @@ snapshots:
|
|||
braces: 3.0.3
|
||||
picomatch: 2.3.1
|
||||
|
||||
minidenticons@4.2.1: {}
|
||||
|
||||
minimatch@3.1.2:
|
||||
dependencies:
|
||||
brace-expansion: 1.1.11
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
<script lang="ts">
|
||||
import { DEFAULT_AVATAR } from "$lib";
|
||||
import { minidenticon } from "minidenticons";
|
||||
|
||||
type Props = { url: string | null; alt: string; lazyLoad?: boolean; size?: number };
|
||||
let { url, alt, lazyLoad, size }: Props = $props();
|
||||
type Props = { url: string | null; alt: string; lazyLoad?: boolean; size?: number; name: string };
|
||||
let { url, alt, lazyLoad, size, name }: Props = $props();
|
||||
|
||||
let width = $derived(size || 200);
|
||||
|
||||
let identicon: string | null = $derived.by(() => {
|
||||
if (url) return null;
|
||||
return "data:image/svg+xml;utf8," + encodeURIComponent(minidenticon(name, 50, 80));
|
||||
});
|
||||
</script>
|
||||
|
||||
<img
|
||||
class="rounded-circle img-fluid"
|
||||
style="height: {width}px; width: {width}px"
|
||||
src={url || DEFAULT_AVATAR}
|
||||
class:identicon={!url}
|
||||
src={url || identicon}
|
||||
{alt}
|
||||
{width}
|
||||
loading={lazyLoad ? "lazy" : "eager"}
|
||||
|
@ -20,4 +26,12 @@
|
|||
img {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.identicon {
|
||||
@media (prefers-color-scheme: dark) {
|
||||
background-color: var(--bs-secondary-border-subtle);
|
||||
}
|
||||
|
||||
background-color: var(--bs-light-border-subtle);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
import ShortNoscriptWarning from "./ShortNoscriptWarning.svelte";
|
||||
|
||||
type Props = {
|
||||
name: string;
|
||||
current: string | null;
|
||||
alt: string;
|
||||
update: (avatar: string) => Promise<void>;
|
||||
updated: boolean;
|
||||
};
|
||||
let { current, alt, update: onclick, updated }: Props = $props();
|
||||
let { name, current, alt, update: onclick, updated }: Props = $props();
|
||||
|
||||
const MAX_AVATAR_BYTES = 1_000_000;
|
||||
|
||||
|
@ -40,7 +41,7 @@
|
|||
</script>
|
||||
|
||||
<p class="text-center">
|
||||
<Avatar url={avatarExists ? avatar : current} {alt} />
|
||||
<Avatar {name} url={avatarExists ? avatar : current} {alt} />
|
||||
</p>
|
||||
|
||||
<InputGroup class="mb-2">
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
<div class="row">
|
||||
<div class="col-md-4 text-center">
|
||||
<Avatar
|
||||
name={"name" in profile ? profile.name : profile.username}
|
||||
url={profile.avatar_url}
|
||||
alt={$t("avatar-tooltip", { name })}
|
||||
lazyLoad={lazyLoadAvatar}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
<div>
|
||||
<a href="/@{username}/{member.name}">
|
||||
<Avatar
|
||||
name={member.name}
|
||||
url={member.avatar_url}
|
||||
lazyLoad
|
||||
alt={$t("avatar-tooltip", { name: member.display_name })}
|
||||
|
|
|
@ -55,6 +55,7 @@
|
|||
<div class="col-md-3 text-center">
|
||||
<h5>{$t("settings.avatar")}</h5>
|
||||
<Avatar
|
||||
name={data.user.username}
|
||||
url={data.user.avatar_url}
|
||||
alt={$t("avatar-tooltip", { name: "@" + data.user.username })}
|
||||
/>
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
{#each data.members as member (member.id)}
|
||||
<ListGroupItem tag="a" href="/settings/members/{member.id}" data-sveltekit-preload-data="tap">
|
||||
<Avatar
|
||||
name={member.name}
|
||||
url={member.avatar_url}
|
||||
alt={$t("avatar-tooltip", { name: member.display_name })}
|
||||
size={20}
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
<div class="col-md">
|
||||
<h4>{$t("settings.avatar")}</h4>
|
||||
<AvatarEditor
|
||||
name={data.member.name}
|
||||
current={data.member.avatar_url}
|
||||
alt={$t("avatar-tooltip", { name: data.member.name })}
|
||||
update={updateAvatar}
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
<div class="col-md">
|
||||
<h4>{$t("settings.avatar")}</h4>
|
||||
<AvatarEditor
|
||||
name={data.user.username}
|
||||
current={data.user.avatar_url}
|
||||
alt={$t("avatar-tooltip", { name: "@" + data.user.username })}
|
||||
update={updateAvatar}
|
||||
|
|
Loading…
Reference in a new issue