diff --git a/apps/desktop/src/components/pro-gate-modal/index.tsx b/apps/desktop/src/components/pro-gate-modal/index.tsx index 73c0513e51..3c9b6f39d8 100644 --- a/apps/desktop/src/components/pro-gate-modal/index.tsx +++ b/apps/desktop/src/components/pro-gate-modal/index.tsx @@ -17,10 +17,14 @@ export function ProGateModal({ isOpen, onClose, type }: ProGateModalProps) { description: "You've reached the custom template limit for free users. Please upgrade your account to continue.", }; - } else { + } else if (type === "chat") { return { description: "4 messages are allowed per conversation for free users. Upgrade to pro for unlimited chat.", }; + } else { + return { + description: "Template duplication is only available for pro users. Please upgrade your account to continue.", + }; } }; diff --git a/apps/desktop/src/components/pro-gate-modal/types.ts b/apps/desktop/src/components/pro-gate-modal/types.ts index d3137feffb..46df87a403 100644 --- a/apps/desktop/src/components/pro-gate-modal/types.ts +++ b/apps/desktop/src/components/pro-gate-modal/types.ts @@ -1,7 +1,7 @@ export interface ProGateModalProps { isOpen: boolean; onClose: () => void; - type: "template" | "chat"; + type: "template" | "chat" | "template_duplicate"; } -export type ProGateType = "template" | "chat"; +export type ProGateType = "template" | "chat" | "template_duplicate"; diff --git a/apps/desktop/src/components/settings/views/template.tsx b/apps/desktop/src/components/settings/views/template.tsx index 44273b58ae..e4befede1c 100644 --- a/apps/desktop/src/components/settings/views/template.tsx +++ b/apps/desktop/src/components/settings/views/template.tsx @@ -1,18 +1,10 @@ import { TemplateService } from "@/utils/template-service"; import { type Template } from "@hypr/plugin-db"; import { Button } from "@hypr/ui/components/ui/button"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from "@hypr/ui/components/ui/dropdown-menu"; import { Input } from "@hypr/ui/components/ui/input"; import { Popover, PopoverContent, PopoverTrigger } from "@hypr/ui/components/ui/popover"; import { Textarea } from "@hypr/ui/components/ui/textarea"; import { Trans, useLingui } from "@lingui/react/macro"; -import { CopyIcon, MoreHorizontalIcon, TrashIcon } from "lucide-react"; import { useCallback, useEffect, useState } from "react"; import { SectionsList } from "../components/template-sections"; @@ -21,6 +13,7 @@ interface TemplateEditorProps { template: Template; onTemplateUpdate: (template: Template) => void; onDelete?: () => void; + onDuplicate?: (template: Template) => void; isCreator?: boolean; } @@ -72,6 +65,7 @@ export default function TemplateEditor({ template, onTemplateUpdate, onDelete, + onDuplicate, isCreator = true, }: TemplateEditorProps) { const { t } = useLingui(); @@ -138,8 +132,8 @@ export default function TemplateEditor({ ); const handleDuplicate = useCallback(() => { - // TODO: Implement duplicate functionality - }, []); + onDuplicate?.(template); + }, [onDuplicate, template]); const handleDelete = useCallback(() => { onDelete?.(); @@ -194,33 +188,24 @@ export default function TemplateEditor({ {isCreator && ( - - - - - - - - Duplicate - - - {/* Only show separator and delete option for custom templates */} - {!isBuiltinTemplate && ( - <> - - - - Delete - - +
+ {isBuiltinTemplate + ? ( + + ) + : ( + )} - - +
)} diff --git a/apps/desktop/src/components/settings/views/templates.tsx b/apps/desktop/src/components/settings/views/templates.tsx index 8cee686c13..bcf50a5a9c 100644 --- a/apps/desktop/src/components/settings/views/templates.tsx +++ b/apps/desktop/src/components/settings/views/templates.tsx @@ -196,6 +196,44 @@ export default function TemplatesView() { } }; + const handleDuplicateTemplate = async (template: Template) => { + try { + if (!getLicense.data?.valid) { + analyticsCommands.event({ + event: "pro_license_required_template", + distinct_id: userId, + }); + await showProGateModal("template_duplicate"); + return; + } + + const emojiMatch = template.title?.match(/^(\p{Emoji})\s*/u); + const originalEmoji = emojiMatch ? emojiMatch[1] : "📄"; + const titleWithoutEmoji = template.title?.replace(/^(\p{Emoji})\s*/u, "") || "Untitled"; + const duplicatedTemplate: Template = { + ...template, + id: crypto.randomUUID(), + user_id: userId, + title: `${originalEmoji} ${titleWithoutEmoji} (Copy)`, + tags: template.tags?.filter(tag => tag !== "builtin") || [], + }; + + await TemplateService.saveTemplate(duplicatedTemplate); + + await loadTemplates(); + + setSelectedTemplate(duplicatedTemplate); + setViewState("editor"); + + analyticsCommands.event({ + event: "template_duplicated", + distinct_id: userId, + }); + } catch (error) { + console.error("Failed to duplicate template:", error); + } + }; + // Check if current template is being viewed (read-only) const isViewingTemplate = selectedTemplate && !TemplateService.canEditTemplate(selectedTemplate.id); @@ -221,6 +259,7 @@ export default function TemplatesView() { template={selectedTemplate} onTemplateUpdate={handleTemplateUpdate} onDelete={handleTemplateDeleteFromEditor} + onDuplicate={handleDuplicateTemplate} isCreator={true} /> )} diff --git a/apps/desktop/src/locales/en/messages.po b/apps/desktop/src/locales/en/messages.po index 8a3d292f7e..bdfdcafacd 100644 --- a/apps/desktop/src/locales/en/messages.po +++ b/apps/desktop/src/locales/en/messages.po @@ -14,7 +14,7 @@ msgstr "" "Plural-Forms: \n" #. js-lingui-explicit-id -#: src/components/settings/views/general.tsx:430 +#: src/components/settings/views/general.tsx:434 msgid "Type terms separated by commas (e.g., Blitz Meeting, PaC Squad)" msgstr "Type terms separated by commas (e.g., Blitz Meeting, PaC Squad)" @@ -271,7 +271,7 @@ msgstr "(Optional)" #: src/components/editor-area/note-header/listen-button.tsx:217 #: src/components/editor-area/note-header/listen-button.tsx:241 #: src/components/editor-area/note-header/listen-button.tsx:261 -#: src/components/settings/views/templates.tsx:214 +#: src/components/settings/views/templates.tsx:252 msgid "{0}" msgstr "{0}" @@ -332,7 +332,7 @@ msgstr "Access multiple AI models through OpenRouter with your API key" #~ msgid "Add a description..." #~ msgstr "Add a description..." -#: src/components/settings/views/template.tsx:236 +#: src/components/settings/views/template.tsx:221 msgid "Add a system instruction..." msgstr "Add a system instruction..." @@ -356,7 +356,7 @@ msgstr "Add more quotes" msgid "Add participant" msgstr "Add participant" -#: src/components/settings/views/general.tsx:421 +#: src/components/settings/views/general.tsx:425 msgid "Add specific terms or jargon for improved transcription accuracy" msgstr "Add specific terms or jargon for improved transcription accuracy" @@ -465,7 +465,7 @@ msgstr "Base URL" #~ msgstr "Billing features are currently under development and will be available in a future update." #: src/components/settings/components/templates-sidebar.tsx:68 -#: src/components/settings/views/templates.tsx:316 +#: src/components/settings/views/templates.tsx:355 msgid "Built-in Templates" msgstr "Built-in Templates" @@ -647,7 +647,7 @@ msgstr "Create new note" msgid "Create Note" msgstr "Create Note" -#: src/components/settings/views/templates.tsx:306 +#: src/components/settings/views/templates.tsx:345 msgid "Create your first template to get started" msgstr "Create your first template to get started" @@ -672,7 +672,7 @@ msgstr "Custom" #~ msgid "Custom Endpoints" #~ msgstr "Custom Endpoints" -#: src/components/settings/views/general.tsx:418 +#: src/components/settings/views/general.tsx:422 msgid "Custom Vocabulary" msgstr "Custom Vocabulary" @@ -687,7 +687,7 @@ msgstr "Default" #: src/components/left-sidebar/notes-list.tsx:336 #: src/components/settings/views/team.tsx:165 -#: src/components/settings/views/template.tsx:218 +#: src/components/settings/views/template.tsx:205 msgid "Delete" msgstr "Delete" @@ -707,7 +707,7 @@ msgstr "Describe the content and purpose of this section" #~ msgid "Did you get consent from everyone in the meeting?" #~ msgstr "Did you get consent from everyone in the meeting?" -#: src/components/settings/views/general.tsx:308 +#: src/components/settings/views/general.tsx:312 msgid "Display language" msgstr "Display language" @@ -727,7 +727,7 @@ msgstr "Downloading AI Models" msgid "Draft follow up" msgstr "Draft follow up" -#: src/components/settings/views/template.tsx:206 +#: src/components/settings/views/template.tsx:195 msgid "Duplicate" msgstr "Duplicate" @@ -743,7 +743,7 @@ msgstr "Email addresses" msgid "Email separated by commas" msgstr "Email separated by commas" -#: src/components/settings/views/template.tsx:168 +#: src/components/settings/views/template.tsx:162 msgid "Emoji" msgstr "Emoji" @@ -949,7 +949,7 @@ msgstr "Join meeting" #~ msgid "Language" #~ msgstr "Language" -#: src/components/settings/views/general.tsx:275 +#: src/components/settings/views/general.tsx:279 msgid "Language for AI-generated summaries" msgstr "Language for AI-generated summaries" @@ -965,7 +965,7 @@ msgstr "Learn more about AI autonomy" #~ msgid "Learn more about our pricing plans" #~ msgstr "Learn more about our pricing plans" -#: src/components/settings/views/templates.tsx:266 +#: src/components/settings/views/templates.tsx:305 msgid "Learn more about templates" msgstr "Learn more about templates" @@ -1001,7 +1001,7 @@ msgstr "Loading events..." msgid "Loading models..." msgstr "Loading models..." -#: src/components/settings/views/templates.tsx:237 +#: src/components/settings/views/templates.tsx:276 msgid "Loading templates..." msgstr "Loading templates..." @@ -1143,7 +1143,7 @@ msgstr "No recent notes with this organization" msgid "No Template (Default)" msgstr "No Template (Default)" -#: src/components/settings/views/templates.tsx:303 +#: src/components/settings/views/templates.tsx:342 msgid "No templates yet" msgstr "No templates yet" @@ -1171,7 +1171,7 @@ msgstr "Obsidian" msgid "Official Templates" msgstr "Official Templates" -#: src/components/settings/views/general.tsx:195 +#: src/components/settings/views/general.tsx:199 msgid "Only starts at the background for notification purposes." msgstr "Only starts at the background for notification purposes." @@ -1247,7 +1247,7 @@ msgstr "people" #~ msgid "Play video" #~ msgstr "Play video" -#: src/components/settings/views/general.tsx:311 +#: src/components/settings/views/general.tsx:315 msgid "Primary language for the interface" msgstr "Primary language for the interface" @@ -1323,7 +1323,7 @@ msgstr "Role" #~ msgid "Save and close" #~ msgstr "Save and close" -#: src/components/settings/views/general.tsx:221 +#: src/components/settings/views/general.tsx:225 msgid "Save audio recording locally alongside the transcript." msgstr "Save audio recording locally alongside the transcript." @@ -1335,7 +1335,7 @@ msgstr "Save current recording" msgid "Save Date" msgstr "Save Date" -#: src/components/settings/views/general.tsx:218 +#: src/components/settings/views/general.tsx:222 msgid "Save recordings" msgstr "Save recordings" @@ -1364,7 +1364,7 @@ msgstr "Search..." #~ msgid "Searching..." #~ msgstr "Searching..." -#: src/components/settings/views/template.tsx:243 +#: src/components/settings/views/template.tsx:228 msgid "Sections" msgstr "Sections" @@ -1376,7 +1376,7 @@ msgstr "Select a model from the dropdown (if available) or manually enter the mo msgid "Select a provider above to configure" msgstr "Select a provider above to configure" -#: src/components/settings/views/templates.tsx:271 +#: src/components/settings/views/templates.tsx:310 msgid "Select a template to enhance your meeting notes" msgstr "Select a template to enhance your meeting notes" @@ -1404,7 +1404,7 @@ msgstr "Select Calendars" msgid "Select how you want to process your meeting notes" msgstr "Select how you want to process your meeting notes" -#: src/components/settings/views/general.tsx:340 +#: src/components/settings/views/general.tsx:344 msgid "Select languages you speak for better transcription" msgstr "Select languages you speak for better transcription" @@ -1428,7 +1428,7 @@ msgstr "Set up Your AI Provider" msgid "Settings" msgstr "Settings" -#: src/components/settings/views/general.tsx:242 +#: src/components/settings/views/general.tsx:246 msgid "Share usage data" msgstr "Share usage data" @@ -1460,7 +1460,7 @@ msgstr "Sound" #~ msgid "Speech to Text Model" #~ msgstr "Speech to Text Model" -#: src/components/settings/views/general.tsx:337 +#: src/components/settings/views/general.tsx:341 msgid "Spoken languages" msgstr "Spoken languages" @@ -1468,7 +1468,7 @@ msgstr "Spoken languages" #~ msgid "Start Annual Plan" #~ msgstr "Start Annual Plan" -#: src/components/settings/views/general.tsx:192 +#: src/components/settings/views/general.tsx:196 msgid "Start automatically at login" msgstr "Start automatically at login" @@ -1496,7 +1496,7 @@ msgstr "Stop" #~ msgid "Summarize meeting" #~ msgstr "Summarize meeting" -#: src/components/settings/views/general.tsx:272 +#: src/components/settings/views/general.tsx:276 msgid "Summary language" msgstr "Summary language" @@ -1509,7 +1509,7 @@ msgstr "Summary language" msgid "System Audio Access" msgstr "System Audio Access" -#: src/components/settings/views/template.tsx:230 +#: src/components/settings/views/template.tsx:215 msgid "System Instruction" msgstr "System Instruction" @@ -1621,7 +1621,7 @@ msgstr "Type to search..." msgid "Untitled" msgstr "Untitled" -#: src/components/settings/views/template.tsx:192 +#: src/components/settings/views/template.tsx:186 msgid "Untitled Template" msgstr "Untitled Template" @@ -1743,6 +1743,6 @@ msgid "Your Name" msgstr "Your Name" #: src/components/settings/components/templates-sidebar.tsx:45 -#: src/components/settings/views/templates.tsx:252 +#: src/components/settings/views/templates.tsx:291 msgid "Your Templates" msgstr "Your Templates" diff --git a/apps/desktop/src/locales/ko/messages.po b/apps/desktop/src/locales/ko/messages.po index 31a3460bcd..7708be4ed9 100644 --- a/apps/desktop/src/locales/ko/messages.po +++ b/apps/desktop/src/locales/ko/messages.po @@ -14,7 +14,7 @@ msgstr "" "Plural-Forms: \n" #. js-lingui-explicit-id -#: src/components/settings/views/general.tsx:430 +#: src/components/settings/views/general.tsx:434 msgid "Type terms separated by commas (e.g., Blitz Meeting, PaC Squad)" msgstr "" @@ -271,7 +271,7 @@ msgstr "" #: src/components/editor-area/note-header/listen-button.tsx:217 #: src/components/editor-area/note-header/listen-button.tsx:241 #: src/components/editor-area/note-header/listen-button.tsx:261 -#: src/components/settings/views/templates.tsx:214 +#: src/components/settings/views/templates.tsx:252 msgid "{0}" msgstr "" @@ -332,7 +332,7 @@ msgstr "" #~ msgid "Add a description..." #~ msgstr "" -#: src/components/settings/views/template.tsx:236 +#: src/components/settings/views/template.tsx:221 msgid "Add a system instruction..." msgstr "" @@ -356,7 +356,7 @@ msgstr "" msgid "Add participant" msgstr "" -#: src/components/settings/views/general.tsx:421 +#: src/components/settings/views/general.tsx:425 msgid "Add specific terms or jargon for improved transcription accuracy" msgstr "" @@ -465,7 +465,7 @@ msgstr "" #~ msgstr "" #: src/components/settings/components/templates-sidebar.tsx:68 -#: src/components/settings/views/templates.tsx:316 +#: src/components/settings/views/templates.tsx:355 msgid "Built-in Templates" msgstr "" @@ -647,7 +647,7 @@ msgstr "" msgid "Create Note" msgstr "" -#: src/components/settings/views/templates.tsx:306 +#: src/components/settings/views/templates.tsx:345 msgid "Create your first template to get started" msgstr "" @@ -672,7 +672,7 @@ msgstr "" #~ msgid "Custom Endpoints" #~ msgstr "" -#: src/components/settings/views/general.tsx:418 +#: src/components/settings/views/general.tsx:422 msgid "Custom Vocabulary" msgstr "" @@ -687,7 +687,7 @@ msgstr "" #: src/components/left-sidebar/notes-list.tsx:336 #: src/components/settings/views/team.tsx:165 -#: src/components/settings/views/template.tsx:218 +#: src/components/settings/views/template.tsx:205 msgid "Delete" msgstr "" @@ -707,7 +707,7 @@ msgstr "" #~ msgid "Did you get consent from everyone in the meeting?" #~ msgstr "" -#: src/components/settings/views/general.tsx:308 +#: src/components/settings/views/general.tsx:312 msgid "Display language" msgstr "" @@ -727,7 +727,7 @@ msgstr "" msgid "Draft follow up" msgstr "" -#: src/components/settings/views/template.tsx:206 +#: src/components/settings/views/template.tsx:195 msgid "Duplicate" msgstr "" @@ -743,7 +743,7 @@ msgstr "" msgid "Email separated by commas" msgstr "" -#: src/components/settings/views/template.tsx:168 +#: src/components/settings/views/template.tsx:162 msgid "Emoji" msgstr "" @@ -949,7 +949,7 @@ msgstr "" #~ msgid "Language" #~ msgstr "" -#: src/components/settings/views/general.tsx:275 +#: src/components/settings/views/general.tsx:279 msgid "Language for AI-generated summaries" msgstr "" @@ -965,7 +965,7 @@ msgstr "" #~ msgid "Learn more about our pricing plans" #~ msgstr "" -#: src/components/settings/views/templates.tsx:266 +#: src/components/settings/views/templates.tsx:305 msgid "Learn more about templates" msgstr "" @@ -1001,7 +1001,7 @@ msgstr "" msgid "Loading models..." msgstr "" -#: src/components/settings/views/templates.tsx:237 +#: src/components/settings/views/templates.tsx:276 msgid "Loading templates..." msgstr "" @@ -1143,7 +1143,7 @@ msgstr "" msgid "No Template (Default)" msgstr "" -#: src/components/settings/views/templates.tsx:303 +#: src/components/settings/views/templates.tsx:342 msgid "No templates yet" msgstr "" @@ -1171,7 +1171,7 @@ msgstr "" msgid "Official Templates" msgstr "" -#: src/components/settings/views/general.tsx:195 +#: src/components/settings/views/general.tsx:199 msgid "Only starts at the background for notification purposes." msgstr "" @@ -1247,7 +1247,7 @@ msgstr "" #~ msgid "Play video" #~ msgstr "" -#: src/components/settings/views/general.tsx:311 +#: src/components/settings/views/general.tsx:315 msgid "Primary language for the interface" msgstr "" @@ -1323,7 +1323,7 @@ msgstr "" #~ msgid "Save and close" #~ msgstr "" -#: src/components/settings/views/general.tsx:221 +#: src/components/settings/views/general.tsx:225 msgid "Save audio recording locally alongside the transcript." msgstr "" @@ -1335,7 +1335,7 @@ msgstr "" msgid "Save Date" msgstr "" -#: src/components/settings/views/general.tsx:218 +#: src/components/settings/views/general.tsx:222 msgid "Save recordings" msgstr "" @@ -1364,7 +1364,7 @@ msgstr "" #~ msgid "Searching..." #~ msgstr "" -#: src/components/settings/views/template.tsx:243 +#: src/components/settings/views/template.tsx:228 msgid "Sections" msgstr "" @@ -1376,7 +1376,7 @@ msgstr "" msgid "Select a provider above to configure" msgstr "" -#: src/components/settings/views/templates.tsx:271 +#: src/components/settings/views/templates.tsx:310 msgid "Select a template to enhance your meeting notes" msgstr "" @@ -1404,7 +1404,7 @@ msgstr "" msgid "Select how you want to process your meeting notes" msgstr "" -#: src/components/settings/views/general.tsx:340 +#: src/components/settings/views/general.tsx:344 msgid "Select languages you speak for better transcription" msgstr "" @@ -1428,7 +1428,7 @@ msgstr "" msgid "Settings" msgstr "" -#: src/components/settings/views/general.tsx:242 +#: src/components/settings/views/general.tsx:246 msgid "Share usage data" msgstr "" @@ -1460,7 +1460,7 @@ msgstr "" #~ msgid "Speech to Text Model" #~ msgstr "" -#: src/components/settings/views/general.tsx:337 +#: src/components/settings/views/general.tsx:341 msgid "Spoken languages" msgstr "" @@ -1468,7 +1468,7 @@ msgstr "" #~ msgid "Start Annual Plan" #~ msgstr "" -#: src/components/settings/views/general.tsx:192 +#: src/components/settings/views/general.tsx:196 msgid "Start automatically at login" msgstr "" @@ -1496,7 +1496,7 @@ msgstr "" #~ msgid "Summarize meeting" #~ msgstr "" -#: src/components/settings/views/general.tsx:272 +#: src/components/settings/views/general.tsx:276 msgid "Summary language" msgstr "" @@ -1509,7 +1509,7 @@ msgstr "" msgid "System Audio Access" msgstr "" -#: src/components/settings/views/template.tsx:230 +#: src/components/settings/views/template.tsx:215 msgid "System Instruction" msgstr "" @@ -1621,7 +1621,7 @@ msgstr "" msgid "Untitled" msgstr "" -#: src/components/settings/views/template.tsx:192 +#: src/components/settings/views/template.tsx:186 msgid "Untitled Template" msgstr "" @@ -1743,6 +1743,6 @@ msgid "Your Name" msgstr "" #: src/components/settings/components/templates-sidebar.tsx:45 -#: src/components/settings/views/templates.tsx:252 +#: src/components/settings/views/templates.tsx:291 msgid "Your Templates" msgstr ""