From f765a4fd393eb3115ecab5cb20cf6cd577e3f196 Mon Sep 17 00:00:00 2001 From: linshen <32978552+linshenkx@users.noreply.github.com> Date: Fri, 8 May 2026 22:46:41 +0800 Subject: [PATCH] feat(ui): improve output actions and link handling - Clear stale history chain metadata when workspace state changes - Centralize external URL opening behind a shared helper - Add copy-and-open AI platform actions with localized labels - Cover workspace and output action behavior with unit tests --- .../ui/src/components/FavoriteImportPanel.vue | 20 +- packages/ui/src/components/MainLayout.vue | 16 +- .../ui/src/components/OutputDisplayCore.vue | 217 ++++++++++++-- .../app-layout/PromptOptimizerApp.vue | 14 +- .../common/WorkspaceUtilityMenu.vue | 20 +- .../image-mode/ImageText2ImageWorkspace.vue | 20 +- .../workspaces/useBasicWorkspaceLogic.ts | 15 + packages/ui/src/i18n/locales/en-US/core.ts | 12 + packages/ui/src/i18n/locales/zh-CN/core.ts | 12 + packages/ui/src/i18n/locales/zh-TW/core.ts | 12 + packages/ui/src/utils/copy-open-action.ts | 64 ++++ packages/ui/src/utils/copy-open-icons.ts | 65 +++++ packages/ui/src/utils/open-external-url.ts | 28 ++ .../integration/basic-workspace-logic.spec.ts | 78 +++++ .../OutputDisplayCore.copy-open.spec.ts | 276 ++++++++++++++++++ .../components/WorkspaceUtilityMenu.spec.ts | 2 +- .../unit/utils/open-external-url.spec.ts | 77 +++++ 17 files changed, 842 insertions(+), 106 deletions(-) create mode 100644 packages/ui/src/utils/copy-open-action.ts create mode 100644 packages/ui/src/utils/copy-open-icons.ts create mode 100644 packages/ui/src/utils/open-external-url.ts create mode 100644 packages/ui/tests/unit/components/OutputDisplayCore.copy-open.spec.ts create mode 100644 packages/ui/tests/unit/utils/open-external-url.spec.ts diff --git a/packages/ui/src/components/FavoriteImportPanel.vue b/packages/ui/src/components/FavoriteImportPanel.vue index f1b84cca..fa7c2f4f 100644 --- a/packages/ui/src/components/FavoriteImportPanel.vue +++ b/packages/ui/src/components/FavoriteImportPanel.vue @@ -173,6 +173,7 @@ import { getEnvVar } from '@prompt-optimizer/core' import { useToast } from '../composables/ui/useToast' import type { AppServices } from '../types/services' import { getI18nErrorMessage } from '../utils/error' +import { openExternalUrl } from '../utils/open-external-url' import { parsePromptGardenImportInput } from '../utils/prompt-garden-import' import { importFavoriteResourcePackage, @@ -230,25 +231,8 @@ const handleFileChange = (options: UploadChangeParam) => { fileList.value = options.fileList.slice(0, 1) } -const openExternalUrl = async (url: string) => { - if (!url) return - - if (typeof window !== 'undefined' && window.electronAPI?.shell) { - try { - await window.electronAPI.shell.openExternal(url) - return - } catch (error) { - console.error('[PromptGarden] Failed to open external URL in Electron:', error) - } - } - - if (typeof window !== 'undefined') { - window.open(url, '_blank') - } -} - const handlePromptGardenDiscover = () => { - void openExternalUrl(promptGardenBaseUrl.value) + void openExternalUrl(promptGardenBaseUrl.value, { logPrefix: 'PromptGarden' }) } const readFileAsArrayBuffer = (file: File) => diff --git a/packages/ui/src/components/MainLayout.vue b/packages/ui/src/components/MainLayout.vue index cec8aa1e..155d10d8 100644 --- a/packages/ui/src/components/MainLayout.vue +++ b/packages/ui/src/components/MainLayout.vue @@ -76,6 +76,7 @@ import { NLayout, NLayoutHeader, NLayoutContent, NFlex, NText } from 'naive-ui' import ToastUI from './Toast.vue' import logoImage from '../assets/logo.png' import AppPreviewImage from './media/AppPreviewImage.vue' +import { openExternalUrl } from '../utils/open-external-url' const { t } = useI18n() @@ -125,20 +126,7 @@ const logoSize = computed(() => { }) const openBrandWebsite = async () => { - const url = 'https://always200.com' - - if (typeof window !== 'undefined' && window.electronAPI?.shell) { - try { - await window.electronAPI.shell.openExternal(url) - return - } catch (error) { - console.error('Failed to open brand website in Electron:', error) - } - } - - if (typeof window !== 'undefined') { - window.open(url, '_blank') - } + await openExternalUrl('https://always200.com', { logPrefix: 'MainLayout' }) } diff --git a/packages/ui/src/components/OutputDisplayCore.vue b/packages/ui/src/components/OutputDisplayCore.vue index 3d1bbc5d..2a5b1fda 100644 --- a/packages/ui/src/components/OutputDisplayCore.vue +++ b/packages/ui/src/components/OutputDisplayCore.vue @@ -40,7 +40,6 @@ - - - - + + + + + + + + + - @@ -193,15 +221,19 @@