Files
dbx/apps/desktop/src/components/icons/AiProviderLogo.vue
T

46 lines
1.7 KiB
Vue

<script setup lang="ts">
import { computed, ref, watch } from "vue";
import { Settings2 } from "@lucide/vue";
import type { AiProvider } from "@/stores/settingsStore";
import { useTheme } from "@/composables/useTheme";
import { webPath } from "@/lib/common/webPath";
const props = defineProps<{
provider: AiProvider;
label: string;
iconSlug?: string;
}>();
const failed = ref(false);
const { isDark } = useTheme();
watch(
() => props.iconSlug,
() => {
failed.value = false;
},
);
const usesWhiteDarkIcon = computed(
() => props.provider === "claude" || props.provider === "anthropic-compatible" || props.provider === "ollama" || props.provider === "openai" || props.provider === "openai-compatible" || props.provider === "opencode-cli" || props.provider === "cursor-cli" || props.provider === "grok-cli",
);
const localIconUrl = computed(() => {
if (props.provider === "openai-compatible") return webPath("/icons/ai/openai.svg");
return props.iconSlug ? webPath(`/icons/ai/${props.iconSlug}.svg`) : "";
});
const fallbackText = computed(() => {
if (props.provider === "openai-compatible") return "OC";
return props.label.slice(0, 1).toUpperCase();
});
</script>
<template>
<span class="flex h-4 w-4 shrink-0 items-center justify-center overflow-hidden rounded-sm">
<Settings2 v-if="provider === 'custom'" class="h-4 w-4 text-muted-foreground" />
<img v-else-if="localIconUrl && !failed" :src="localIconUrl" :alt="label" class="h-4 w-4 object-contain" :class="{ 'dark:invert': isDark && usesWhiteDarkIcon }" @error="failed = true" />
<span v-else class="flex h-4 w-4 items-center justify-center rounded-sm bg-muted text-[8px] font-semibold">
{{ fallbackText }}
</span>
</span>
</template>