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", | ||||
|  |  | |||
							
								
								
									
										9
									
								
								Foxnouns.Frontend/pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								Foxnouns.Frontend/pnpm-lock.yaml
									
										
									
										generated
									
									
									
								
							|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue