mirror of
https://github.com/pocket-id/pocket-id.git
synced 2026-09-25 04:19:05 +02:00
feat: add animated logo as default logo
This commit is contained in:
@@ -1,18 +1,149 @@
|
||||
<script module lang="ts">
|
||||
type LogoVariant = 'light' | 'dark';
|
||||
|
||||
let defaultLogoHasAnimated = false;
|
||||
const customLogoAvailability: Record<LogoVariant, boolean | undefined> = {
|
||||
light: undefined,
|
||||
dark: undefined
|
||||
};
|
||||
|
||||
const finalLogoPath =
|
||||
'M-250.368,-706.48C-166.912,-706.48 -83.456,-706.48 0,-706.48C149.377,-706.48 270.906,-584.953 270.906,-435.576C270.906,-376.876 252.438,-321.028 217.506,-274.062C183.258,-228.019 136.385,-194.563 81.955,-177.305C76.939,-175.715 71.924,-174.124 66.908,-172.534C54.955,-231.481 43.003,-290.429 31.05,-349.376C34.355,-350.974 37.661,-352.571 40.966,-354.169C73.345,-369.822 94.269,-403.156 94.269,-439.094C94.269,-491.073 51.982,-533.36 0,-533.36C-51.978,-533.36 -94.267,-491.073 -94.267,-439.094C-94.267,-403.156 -73.344,-369.822 -40.963,-354.169C-37.718,-352.6 -34.473,-351.032 -31.228,-349.463C-50.48,-230.815 -69.733,-112.167 -88.985,6.48C-142.779,6.48 -196.574,6.48 -250.368,6.48Z';
|
||||
|
||||
const animationValues = `
|
||||
M-189.277,-455.654C-183.639,-520.099 -145.598,-577.247 -88.32,-607.319C-29.581,-638.158 40.991,-636.125 97.857,-601.956C125.29,-585.473 148.114,-562.328 164.212,-534.668C211.414,-453.567 192.341,-350.154 119.313,-291.228C92.569,-269.648 60.47,-255.723 26.44,-250.94C27.98,-283.752 29.51,-316.564 31.05,-349.376C34.355,-350.974 37.661,-352.571 40.966,-354.169C73.345,-369.822 94.269,-403.156 94.269,-439.094C94.269,-491.073 51.982,-533.36 0,-533.36C-51.978,-533.36 -94.267,-491.073 -94.267,-439.094C-94.267,-403.156 -73.344,-369.822 -40.963,-354.169C-37.718,-352.6 -34.473,-351.032 -31.228,-349.463C-29.632,-316.622 -28.036,-283.781 -26.44,-250.94C-114.05,-263.255 -181.567,-334.403 -189.277,-422.534Z;
|
||||
|
||||
M-189.277,-455.654C-183.639,-520.099 -145.598,-577.247 -88.32,-607.319C-29.581,-638.158 40.991,-636.125 97.857,-601.956C125.29,-585.473 148.114,-562.328 164.212,-534.668C211.414,-453.567 192.341,-350.154 119.313,-291.228C92.569,-269.648 60.47,-255.723 26.44,-250.94C27.98,-283.752 29.51,-316.564 31.05,-349.376C34.355,-350.974 37.661,-352.571 40.966,-354.169C73.345,-369.822 94.269,-403.156 94.269,-439.094C94.269,-491.073 51.982,-533.36 0,-533.36C-51.978,-533.36 -94.267,-491.073 -94.267,-439.094C-94.267,-403.156 -73.344,-369.822 -40.963,-354.169C-37.718,-352.6 -34.473,-351.032 -31.228,-349.463C-29.632,-316.622 -28.036,-283.781 -26.44,-250.94C-114.05,-263.255 -181.567,-334.403 -189.277,-422.534Z;
|
||||
|
||||
M-208.638,-523.827C-208.638,-580.969 -167.157,-631.565 -113.16,-644.659C-38.396,-662.79 43.369,-658.5 117.928,-641.978C156.432,-633.446 188.336,-602.071 196.106,-563.334C220.586,-441.292 205.573,-309.149 173.656,-196.614C158.003,-141.421 105.235,-133.862 43.22,-131.47C39.165,-204.106 35.105,-276.742 31.05,-349.376C34.355,-350.974 37.661,-352.571 40.966,-354.169C73.344,-369.823 94.269,-403.156 94.269,-439.094C94.269,-491.073 51.982,-533.36 0,-533.36C-51.978,-533.36 -94.267,-491.073 -94.267,-439.094C-94.267,-403.156 -73.343,-369.823 -40.963,-354.169C-37.718,-352.6 -34.473,-351.032 -31.228,-349.463C-38.561,-276.801 -45.888,-204.136 -53.22,-131.47C-137.025,-137.627 -208.638,-173.118 -208.638,-262.267Z;
|
||||
|
||||
M-228,-592C-228,-641.7 -187.7,-682 -138,-682C-46,-682 46,-682 138,-682C187.7,-682 228,-641.7 228,-592C228,-428.67 228,-265.33 228,-102C228,-12 150,-12 60,-12C50.35,-124.46 40.7,-236.92 31.05,-349.376C34.355,-350.974 37.661,-352.571 40.966,-354.169C73.345,-369.822 94.269,-403.156 94.269,-439.094C94.269,-491.073 51.982,-533.36 0,-533.36C-51.978,-533.36 -94.267,-491.073 -94.267,-439.094C-94.267,-403.156 -73.344,-369.822 -40.963,-354.169C-37.718,-352.6 -34.473,-351.032 -31.228,-349.463C-47.49,-236.98 -63.74,-124.49 -80,-12C-160,-12 -228,-12 -228,-102Z;
|
||||
|
||||
M-239.184,-594.24C-239.184,-649.466 -194.411,-694.24 -139.184,-694.24C-42.969,-694.24 53.238,-694.24 149.453,-694.24C204.679,-694.24 249.453,-649.466 249.453,-594.24C249.453,-430.415 249.453,-266.585 249.453,-102.76C249.453,-2.76 159.455,-2.76 63.454,-2.76C52.653,-118.299 41.852,-233.839 31.05,-349.376C34.355,-350.974 37.661,-352.571 40.966,-354.169C73.344,-369.823 94.269,-403.156 94.269,-439.094C94.269,-491.073 51.982,-533.36 0,-533.36C-51.978,-533.36 -94.267,-491.073 -94.267,-439.094C-94.267,-403.156 -73.343,-369.823 -40.963,-354.169C-37.718,-352.6 -34.473,-351.032 -31.228,-349.463C-48.985,-233.897 -66.737,-118.328 -84.493,-2.76C-162.5,-2.76 -239.184,-2.76 -239.184,-102.76Z;
|
||||
|
||||
M-250.368,-596.48C-250.368,-657.233 -201.121,-706.48 -140.368,-706.48C-39.938,-706.48 60.476,-706.48 160.906,-706.48C221.659,-706.48 270.906,-657.233 270.906,-596.48C270.906,-432.16 270.906,-267.84 270.906,-103.52C270.906,6.48 168.91,6.48 66.908,6.48C54.955,-112.139 43.003,-230.757 31.05,-349.376C34.355,-350.974 37.661,-352.571 40.966,-354.169C73.345,-369.822 94.269,-403.156 94.269,-439.094C94.269,-491.073 51.982,-533.36 0,-533.36C-51.978,-533.36 -94.267,-491.073 -94.267,-439.094C-94.267,-403.156 -73.344,-369.822 -40.963,-354.169C-37.718,-352.6 -34.473,-351.032 -31.228,-349.463C-50.48,-230.815 -69.733,-112.167 -88.985,6.48C-165,6.48 -250.368,6.48 -250.368,-103.52Z;
|
||||
|
||||
M-250.368,-596.48C-250.368,-657.233 -201.121,-706.48 -140.368,-706.48C-39.938,-706.48 60.476,-706.48 160.906,-706.48C221.659,-706.48 270.906,-657.233 270.906,-596.48C270.906,-432.16 270.906,-267.84 270.906,-103.52C270.906,6.48 168.91,6.48 66.908,6.48C54.955,-112.139 43.003,-230.757 31.05,-349.376C34.355,-350.974 37.661,-352.571 40.966,-354.169C73.345,-369.822 94.269,-403.156 94.269,-439.094C94.269,-491.073 51.982,-533.36 0,-533.36C-51.978,-533.36 -94.267,-491.073 -94.267,-439.094C-94.267,-403.156 -73.344,-369.822 -40.963,-354.169C-37.718,-352.6 -34.473,-351.032 -31.228,-349.463C-50.48,-230.815 -69.733,-112.167 -88.985,6.48C-165,6.48 -250.368,6.48 -250.368,-103.52Z;
|
||||
|
||||
M-250.368,-651.48C-208.64,-681.856 -142.288,-706.48 -70.184,-706.48C54.72,-706.48 158.116,-640.023 215.906,-571.028C243.028,-538.647 257.527,-490.302 244.206,-435.271C219.135,-331.696 192.286,-233.857 176.43,-140.412C167.087,-85.348 120.417,-83.822 66.908,-83.027C54.955,-171.81 43.003,-260.593 31.05,-349.376C34.355,-350.974 37.661,-352.571 40.966,-354.169C73.344,-369.823 94.269,-403.156 94.269,-439.094C94.269,-491.073 51.982,-533.36 0,-533.36C-51.978,-533.36 -94.267,-491.073 -94.267,-439.094C-94.267,-403.156 -73.343,-369.823 -40.963,-354.169C-37.718,-352.6 -34.473,-351.032 -31.228,-349.463C-50.48,-230.815 -69.733,-112.167 -88.985,6.48C-153.889,6.48 -223.471,6.48 -250.368,-48.52Z;
|
||||
|
||||
M-250.368,-706.48C-166.912,-706.48 -83.456,-706.48 0,-706.48C149.377,-706.48 270.906,-584.953 270.906,-435.576C270.906,-376.876 252.438,-321.028 217.506,-274.062C183.258,-228.019 136.385,-194.563 81.955,-177.305C76.939,-175.715 71.924,-174.124 66.908,-172.534C54.955,-231.481 43.003,-290.429 31.05,-349.376C34.355,-350.974 37.661,-352.571 40.966,-354.169C73.345,-369.822 94.269,-403.156 94.269,-439.094C94.269,-491.073 51.982,-533.36 0,-533.36C-51.978,-533.36 -94.267,-491.073 -94.267,-439.094C-94.267,-403.156 -73.344,-369.822 -40.963,-354.169C-37.718,-352.6 -34.473,-351.032 -31.228,-349.463C-50.48,-230.815 -69.733,-112.167 -88.985,6.48C-142.779,6.48 -196.574,6.48 -250.368,6.48Z`;
|
||||
const initialLogoPath = animationValues.trim().split(';', 1)[0];
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { m } from '$lib/paraglide/messages';
|
||||
import appConfigStore from '$lib/stores/application-configuration-store';
|
||||
import { cachedApplicationLogo } from '$lib/utils/cached-image-util';
|
||||
import { cn } from '$lib/utils/style';
|
||||
import { mode } from 'mode-watcher';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let { ...props }: HTMLAttributes<HTMLImageElement> = $props();
|
||||
let {
|
||||
class: className,
|
||||
alt,
|
||||
defaultOnly = false,
|
||||
animate = true,
|
||||
colorScheme
|
||||
}: {
|
||||
class?: string;
|
||||
alt?: string;
|
||||
defaultOnly?: boolean;
|
||||
animate?: boolean;
|
||||
colorScheme?: 'light' | 'dark';
|
||||
} = $props();
|
||||
|
||||
const isLightMode = $derived(mode.current === 'light');
|
||||
const initialIsLightMode = colorScheme ? colorScheme === 'light' : mode.current === 'light';
|
||||
const initialLogoVariant: LogoVariant = initialIsLightMode ? 'light' : 'dark';
|
||||
|
||||
let customLogoAvailabilityState = $state<Record<LogoVariant, boolean | undefined>>({
|
||||
...customLogoAvailability
|
||||
});
|
||||
let animateDefaultLogo = $state(
|
||||
customLogoAvailability[initialLogoVariant] === false && claimDefaultLogoAnimation()
|
||||
);
|
||||
|
||||
const isLightMode = $derived(colorScheme ? colorScheme === 'light' : mode.current === 'light');
|
||||
const logoVariant = $derived(isLightMode ? 'light' : 'dark');
|
||||
const logoAlt = $derived(alt ?? m.logo());
|
||||
const useDefaultLogo = $derived(
|
||||
defaultOnly || customLogoAvailabilityState[logoVariant] === false
|
||||
);
|
||||
const customLogoLoaded = $derived(customLogoAvailabilityState[logoVariant] === true);
|
||||
|
||||
function handleImageLoad() {
|
||||
customLogoAvailability[logoVariant] = true;
|
||||
customLogoAvailabilityState[logoVariant] = true;
|
||||
}
|
||||
|
||||
function handleImageError() {
|
||||
animateDefaultLogo = claimDefaultLogoAnimation();
|
||||
customLogoAvailability[logoVariant] = false;
|
||||
customLogoAvailabilityState[logoVariant] = false;
|
||||
}
|
||||
|
||||
function claimDefaultLogoAnimation() {
|
||||
if (!animate || defaultOnly || defaultLogoHasAnimated || $appConfigStore?.disableAnimations) {
|
||||
return false;
|
||||
}
|
||||
|
||||
defaultLogoHasAnimated = true;
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<img
|
||||
{...props}
|
||||
class={cn('aspect-square object-contain', props.class)}
|
||||
src={cachedApplicationLogo.getUrl(isLightMode)}
|
||||
alt={m.logo()}
|
||||
/>
|
||||
{#if useDefaultLogo}
|
||||
<svg
|
||||
class={cn('aspect-square', isLightMode ? 'text-black' : 'text-white', className)}
|
||||
viewBox="-346.211 -706.48 712.96 712.96"
|
||||
role="img"
|
||||
aria-label={logoAlt}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill="currentColor"
|
||||
opacity={animateDefaultLogo ? 0 : 1}
|
||||
d={animateDefaultLogo ? initialLogoPath : finalLogoPath}
|
||||
>
|
||||
{#if animateDefaultLogo}
|
||||
<animate
|
||||
attributeName="opacity"
|
||||
dur="1.5s"
|
||||
begin="0s"
|
||||
fill="freeze"
|
||||
keyTimes="0; 0.15; 1"
|
||||
values="0; 1; 1"
|
||||
/>
|
||||
<animateTransform
|
||||
attributeName="transform"
|
||||
type="rotate"
|
||||
dur="1.5s"
|
||||
begin="0s"
|
||||
fill="freeze"
|
||||
calcMode="spline"
|
||||
keyTimes="0; 0.20; 0.26; 0.44; 1"
|
||||
keySplines="0 0 1 1; 0 0 1 1; 0.35 0 0.35 1; 0 0 1 1"
|
||||
values="-90 0 -439.094; -90 0 -439.094; -90 0 -439.094; 0 0 -439.094; 0 0 -439.094"
|
||||
/>
|
||||
<animate
|
||||
attributeName="d"
|
||||
dur="1.5s"
|
||||
begin="0s"
|
||||
fill="freeze"
|
||||
calcMode="spline"
|
||||
keyTimes="0; 0.4; 0.4681; 0.53; 0.5689; 0.63; 0.68; 0.7944; 1"
|
||||
keySplines="0 0 1 1; 0.402 0 0.6982 0.4985; 0.2986 0.4514 0.6022 0.9053; 0.2862 0.178 0.6233 0.5935; 0.2988 0.5071 0.6368 1; 0 0 1 1; 0.5175 0 0.6923 0.5; 0.1712 0.5 0.4163 1"
|
||||
values={animationValues}
|
||||
/>
|
||||
{/if}
|
||||
</path>
|
||||
</svg>
|
||||
{:else}
|
||||
<img
|
||||
class={cn('aspect-square object-contain', className)}
|
||||
style:visibility={customLogoLoaded ? 'visible' : 'hidden'}
|
||||
src={cachedApplicationLogo.getUrl(isLightMode)}
|
||||
alt={logoAlt}
|
||||
onload={handleImageLoad}
|
||||
onerror={handleImageError}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
@@ -47,6 +47,13 @@ export default class AppConfigService extends APIService {
|
||||
cachedApplicationLogo.bustCache(light);
|
||||
};
|
||||
|
||||
deleteLogo = async (light = true) => {
|
||||
await this.api.delete(`/application-images/logo`, {
|
||||
params: { light }
|
||||
});
|
||||
cachedApplicationLogo.bustCache(light);
|
||||
};
|
||||
|
||||
updateEmailLogo = async (emailLogo: File) => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', emailLogo);
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
? 'translate-x-[108px]'
|
||||
: ''}"
|
||||
>
|
||||
<Logo class="size-10" />
|
||||
<Logo class="size-10" animate={false} />
|
||||
</div>
|
||||
|
||||
<ConnectArrow
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
}
|
||||
|
||||
async function updateImages(
|
||||
logoLight: File | undefined,
|
||||
logoDark: File | undefined,
|
||||
logoLight: File | null | undefined,
|
||||
logoDark: File | null | undefined,
|
||||
logoEmail: File | undefined,
|
||||
defaultProfilePicture: File | null | undefined,
|
||||
backgroundImage: File | null | undefined,
|
||||
@@ -45,13 +45,19 @@
|
||||
) {
|
||||
const faviconPromise = favicon ? appConfigService.updateFavicon(favicon) : Promise.resolve();
|
||||
|
||||
const lightLogoPromise = logoLight
|
||||
? appConfigService.updateLogo(logoLight, true)
|
||||
: Promise.resolve();
|
||||
const lightLogoPromise =
|
||||
logoLight === null
|
||||
? appConfigService.deleteLogo(true)
|
||||
: logoLight
|
||||
? appConfigService.updateLogo(logoLight, true)
|
||||
: Promise.resolve();
|
||||
|
||||
const darkLogoPromise = logoDark
|
||||
? appConfigService.updateLogo(logoDark, false)
|
||||
: Promise.resolve();
|
||||
const darkLogoPromise =
|
||||
logoDark === null
|
||||
? appConfigService.deleteLogo(false)
|
||||
: logoDark
|
||||
? appConfigService.updateLogo(logoDark, false)
|
||||
: Promise.resolve();
|
||||
|
||||
const emailLogoPromise = logoEmail
|
||||
? appConfigService.updateEmailLogo(logoEmail)
|
||||
|
||||
+10
-1
@@ -2,8 +2,10 @@
|
||||
import FileInput from '$lib/components/form/file-input.svelte';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import * as Field from '$lib/components/ui/field';
|
||||
import { m } from '$lib/paraglide/messages';
|
||||
import { cn } from '$lib/utils/style';
|
||||
import { LucideImageOff, LucideUpload, LucideX } from '@lucide/svelte';
|
||||
import type { Snippet } from 'svelte';
|
||||
import type { HTMLAttributes } from 'svelte/elements';
|
||||
|
||||
let {
|
||||
@@ -12,6 +14,7 @@
|
||||
label,
|
||||
image = $bindable(),
|
||||
imageURL,
|
||||
fallback,
|
||||
accept = 'image/png, image/jpeg, image/svg+xml, image/gif, image/webp, image/avif, image/heic',
|
||||
forceColorScheme,
|
||||
isResetable = false,
|
||||
@@ -23,6 +26,7 @@
|
||||
label: string;
|
||||
image: File | null | undefined;
|
||||
imageURL: string;
|
||||
fallback?: Snippet;
|
||||
forceColorScheme?: 'light' | 'dark';
|
||||
accept?: string;
|
||||
isResetable?: boolean;
|
||||
@@ -70,7 +74,11 @@
|
||||
imageClass
|
||||
)}
|
||||
>
|
||||
<LucideImageOff class="text-muted-foreground" />
|
||||
{#if fallback}
|
||||
{@render fallback()}
|
||||
{:else}
|
||||
<LucideImageOff class="text-muted-foreground" />
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<img
|
||||
@@ -97,6 +105,7 @@
|
||||
{#if isResetable && isImageSet}
|
||||
<Button
|
||||
size="icon"
|
||||
aria-label={`${m.reset_to_default()} ${label}`}
|
||||
onclick={(e) => {
|
||||
e.stopPropagation();
|
||||
onReset();
|
||||
|
||||
+21
-4
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import Logo from '$lib/components/logo.svelte';
|
||||
import Button from '$lib/components/ui/button/button.svelte';
|
||||
import { m } from '$lib/paraglide/messages';
|
||||
import {
|
||||
@@ -13,8 +14,8 @@
|
||||
callback
|
||||
}: {
|
||||
callback: (
|
||||
logoLight: File | undefined,
|
||||
logoDark: File | undefined,
|
||||
logoLight: File | null | undefined,
|
||||
logoDark: File | null | undefined,
|
||||
logoEmail: File | undefined,
|
||||
defaultProfilePicture: File | null | undefined,
|
||||
backgroundImage: File | null | undefined,
|
||||
@@ -22,8 +23,8 @@
|
||||
) => void;
|
||||
} = $props();
|
||||
|
||||
let logoLight = $state<File | undefined>();
|
||||
let logoDark = $state<File | undefined>();
|
||||
let logoLight = $state<File | null | undefined>();
|
||||
let logoDark = $state<File | null | undefined>();
|
||||
let logoEmail = $state<File | undefined>();
|
||||
let defaultProfilePicture = $state<File | null | undefined>();
|
||||
let backgroundImage = $state<File | null | undefined>();
|
||||
@@ -31,8 +32,18 @@
|
||||
|
||||
let defaultProfilePictureSet = $state(true);
|
||||
let backgroundImageSet = $state(true);
|
||||
let logoLightSet = $state(true);
|
||||
let logoDarkSet = $state(true);
|
||||
</script>
|
||||
|
||||
{#snippet lightLogoFallback()}
|
||||
<Logo defaultOnly colorScheme="light" class="size-full" />
|
||||
{/snippet}
|
||||
|
||||
{#snippet darkLogoFallback()}
|
||||
<Logo defaultOnly colorScheme="dark" class="size-full" />
|
||||
{/snippet}
|
||||
|
||||
<div class="flex flex-col gap-8">
|
||||
<ApplicationImage
|
||||
id="favicon"
|
||||
@@ -48,7 +59,10 @@
|
||||
label={m.light_mode_logo()}
|
||||
bind:image={logoLight}
|
||||
imageURL={cachedApplicationLogo.getUrl(true)}
|
||||
fallback={lightLogoFallback}
|
||||
forceColorScheme="light"
|
||||
isResetable
|
||||
bind:isImageSet={logoLightSet}
|
||||
/>
|
||||
<ApplicationImage
|
||||
id="logo-dark"
|
||||
@@ -56,7 +70,10 @@
|
||||
label={m.dark_mode_logo()}
|
||||
bind:image={logoDark}
|
||||
imageURL={cachedApplicationLogo.getUrl(false)}
|
||||
fallback={darkLogoFallback}
|
||||
forceColorScheme="dark"
|
||||
isResetable
|
||||
bind:isImageSet={logoDarkSet}
|
||||
/>
|
||||
<ApplicationImage
|
||||
id="logo-email"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import ImageBox from '$lib/components/image-box.svelte';
|
||||
import Logo from '$lib/components/logo.svelte';
|
||||
import { Button } from '$lib/components/ui/button';
|
||||
import * as Card from '$lib/components/ui/card';
|
||||
import * as DropdownMenu from '$lib/components/ui/dropdown-menu';
|
||||
@@ -8,7 +9,7 @@
|
||||
import { m } from '$lib/paraglide/messages';
|
||||
import userStore from '$lib/stores/user-store';
|
||||
import type { AccessibleOidcClient, OidcClientMetaData } from '$lib/types/oidc.type';
|
||||
import { cachedApplicationLogo, cachedOidcClientLogo } from '$lib/utils/cached-image-util';
|
||||
import { cachedOidcClientLogo } from '$lib/utils/cached-image-util';
|
||||
import { encodeClientIdParam } from '$lib/utils/client-id-util';
|
||||
import {
|
||||
LucideBan,
|
||||
@@ -38,13 +39,17 @@
|
||||
<Card.Content class=" p-0">
|
||||
<div class="flex gap-3">
|
||||
<div class="aspect-square h-[56px]">
|
||||
<ImageBox
|
||||
class="size-14"
|
||||
src={client.hasLogo
|
||||
? cachedOidcClientLogo.getUrl(client.id, isLightMode)
|
||||
: cachedApplicationLogo.getUrl(isLightMode)}
|
||||
alt={m.name_logo({ name: client.name })}
|
||||
/>
|
||||
{#if client.hasLogo}
|
||||
<ImageBox
|
||||
class="size-14"
|
||||
src={cachedOidcClientLogo.getUrl(client.id, isLightMode)}
|
||||
alt={m.name_logo({ name: client.name })}
|
||||
/>
|
||||
{:else}
|
||||
<div class="bg-muted flex size-14 items-center justify-center rounded-2xl p-3">
|
||||
<Logo class="size-full" alt={m.name_logo({ name: client.name })} animate={false} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="flex w-full justify-between gap-3">
|
||||
<div class="h-20">
|
||||
|
||||
Reference in New Issue
Block a user