From 058f3132bf3f95ce5f1fe81a11a7c46be05ba756 Mon Sep 17 00:00:00 2001 From: Paulhenry Saux Date: Fri, 24 Jul 2026 18:10:37 +0200 Subject: [PATCH] feat(plugins): add new contact-cryptokeys UI slot --- components/contacts/contact-detail.tsx | 10 +++++++++- lib/__tests__/plugin-types.test.ts | 1 + lib/plugin-types.ts | 5 +++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/components/contacts/contact-detail.tsx b/components/contacts/contact-detail.tsx index c4160b7e0..3606f27ec 100644 --- a/components/contacts/contact-detail.tsx +++ b/components/contacts/contact-detail.tsx @@ -12,6 +12,8 @@ import { ContactActivity } from "./contact-activity"; import { toast } from "@/stores/toast-store"; import { exportContact } from "./contact-export"; import { printContact } from "./contact-print"; +import { usePluginSlotOffers } from "@/hooks/use-plugin-slot-offers"; +import { PluginSlot } from "@/components/plugins/plugin-slot"; type MoreItem = | { @@ -118,6 +120,7 @@ export function ContactDetail({ contact, onEdit, onDelete, onAddToGroup, onDupli const t = useTranslations("contacts"); const cryptoKeys = contact?.cryptoKeys ? Object.values(contact.cryptoKeys) : []; + const hasCryptoKeysSlotOffers = usePluginSlotOffers('contact-cryptokeys').length > 0; if (!contact) { return ( @@ -426,7 +429,12 @@ export function ContactDetail({ contact, onEdit, onDelete, onAddToGroup, onDupli {cryptoKeys.length > 0 && (
- {cryptoKeys.map((key, i) => ( + + {hasCryptoKeysSlotOffers && ( + + )} + + {!hasCryptoKeysSlotOffers &&cryptoKeys.map((key, i) => (
diff --git a/lib/__tests__/plugin-types.test.ts b/lib/__tests__/plugin-types.test.ts index a5e6a090c..f48ab1b19 100644 --- a/lib/__tests__/plugin-types.test.ts +++ b/lib/__tests__/plugin-types.test.ts @@ -39,6 +39,7 @@ describe('plugin-types constants', () => { expect(ALL_PERMISSIONS).toContain('ui:toolbar'); expect(ALL_PERMISSIONS).toContain('ui:email-banner'); expect(ALL_PERMISSIONS).toContain('ui:email-footer'); + expect(ALL_PERMISSIONS).toContain('ui:contact-cryptokeys'); expect(ALL_PERMISSIONS).toContain('ui:composer-toolbar'); expect(ALL_PERMISSIONS).toContain('ui:sidebar-widget'); expect(ALL_PERMISSIONS).toContain('ui:settings-section'); diff --git a/lib/plugin-types.ts b/lib/plugin-types.ts index f7fb9442f..0755d5eb3 100644 --- a/lib/plugin-types.ts +++ b/lib/plugin-types.ts @@ -287,7 +287,8 @@ export type SlotName = | 'context-menu-email' | 'navigation-rail-bottom' | 'calendar-event-actions' - | 'admin-plugin-page'; + | 'admin-plugin-page' + | 'contact-cryptokeys'; export interface SlotRegistration { pluginId: string; @@ -1036,7 +1037,7 @@ export const ALL_PERMISSIONS = [ 'security:read', 'auth:observe', 'http:post', 'http:fetch', - 'ui:observe', 'ui:toolbar', 'ui:app-top-banner', 'ui:email-banner', 'ui:email-footer', + 'ui:observe', 'ui:toolbar', 'ui:app-top-banner', 'ui:email-banner', 'ui:email-footer', 'ui:contact-cryptokeys', 'ui:email-details', 'ui:download-file', // Register native message-list category tabs (Gmail-style inbox tabs).