diff --git a/src/config/user.config.ts b/src/config/user.config.ts index 80beae3..4a86dad 100644 --- a/src/config/user.config.ts +++ b/src/config/user.config.ts @@ -108,6 +108,12 @@ export const settingsConfig = [ }) }, }, + { + key: 'autoOpenCopiedLink', + label: i18n.global.t('settings.autoOpenCopiedLink'), + type: 'toggle', + value: 'off', + }, { key: 'exportLogs', label: i18n.global.t('settings.exportLogs'), diff --git a/src/i18n/de.ts b/src/i18n/de.ts index d46cf83..c7f53f5 100644 --- a/src/i18n/de.ts +++ b/src/i18n/de.ts @@ -122,6 +122,7 @@ export default { settings: 'Einstellungen', general: 'Allgemein', debugger: 'Protokolle sammeln', + autoOpenCopiedLink: 'Kopierte Werk-/Benutzerlinks automatisch öffnen', exportLogs: 'Fehlerprotokolle exportieren', languageChangeTitle: 'Sprache geändert', languageChangeContent: diff --git a/src/i18n/en.ts b/src/i18n/en.ts index eabfd6c..0ce40c3 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -122,6 +122,7 @@ export default { settings: 'settings', general: 'General', debugger: 'collect logs', + autoOpenCopiedLink: 'Auto-open copied work/user links', exportLogs: 'Export Error Logs', languageChangeTitle: 'Language Changed', languageChangeContent: 'Some features need to re-login to apply the new language completely', diff --git a/src/i18n/fr.ts b/src/i18n/fr.ts index 05b88d3..eada7a3 100644 --- a/src/i18n/fr.ts +++ b/src/i18n/fr.ts @@ -122,6 +122,7 @@ export default { settings: 'Paramètres', general: 'Général', debugger: 'Collecter les journaux', + autoOpenCopiedLink: 'Ouvrir automatiquement les liens œuvre/utilisateur copiés', exportLogs: "Exporter les journaux d'erreurs", languageChangeTitle: 'Langue modifiée', languageChangeContent: diff --git a/src/i18n/ja.ts b/src/i18n/ja.ts index 8466b66..54bc43a 100644 --- a/src/i18n/ja.ts +++ b/src/i18n/ja.ts @@ -122,6 +122,7 @@ export default { settings: '設定', general: '一般', debugger: 'ログを収集', + autoOpenCopiedLink: 'コピーした作品/ユーザーリンクを自動で開く', exportLogs: 'エラーログをエクスポート', languageChangeTitle: '言語が変更されました', languageChangeContent: diff --git a/src/i18n/zh.ts b/src/i18n/zh.ts index 677d8b7..5ff0c35 100644 --- a/src/i18n/zh.ts +++ b/src/i18n/zh.ts @@ -119,6 +119,7 @@ export default { settings: '应用设置', general: '通用设置', debugger: '收集调试信息', + autoOpenCopiedLink: '粘贴后自动打开作品/用户链接', exportLogs: '导出错误日志', languageChangeTitle: '语言已切换', languageChangeContent: '部分功能需要重新登录才能完全应用新语言', diff --git a/src/main.ts b/src/main.ts index 074b4dc..41f8059 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,6 +5,8 @@ import i18n from '@i18n/index' import ErrorLogger from './services/errorLogger.ts' import { LogManager } from '@api/logWriter.ts' import { getPath } from '@services/utils' +import storageManager from '@storage/index' +import { showMessage } from '@popup/naiveui' import type { DirectiveBinding } from 'vue' import 'highlight.js/styles/github.css' @@ -56,3 +58,50 @@ document.addEventListener( }, true, ) + +function parseCopiedRouteTarget(input: string): { path: string; needLogin: boolean } | null { + const text = input.trim() + + const experimentTag = text.match(//i) + if (experimentTag?.[1]) return { path: `/p/Experiment/${experimentTag[1]}`, needLogin: false } + + const discussionHash = text.match(/#\/p\/Discussion\/([a-f0-9]{24})/i) + if (discussionHash?.[1]) return { path: `/p/Discussion/${discussionHash[1]}`, needLogin: false } + + const discussionQuery = text.match(/\?[\w-]+-([a-f0-9]{24})\?/i) + if (discussionQuery?.[1]) return { path: `/p/Discussion/${discussionQuery[1]}`, needLogin: false } + + const userTag = text.match(//i) + if (userTag?.[1]) return { path: `/u/${userTag[1]}`, needLogin: true } + + return null +} + +async function handlePasteAutoOpen(event: ClipboardEvent) { + const isEnabled = storageManager.getObj('userConfig').value?.autoOpenCopiedLink === 'on' + if (!isEnabled) return + + const pastedText = event.clipboardData?.getData('text/plain')?.trim() + if (!pastedText) return + + const target = parseCopiedRouteTarget(pastedText) + if (!target) return + + if (target.needLogin && !storageManager.getObj('userInfo').value?.User?.ID) { + showMessage('warning', 'Please login first', { duration: 2000 }) + return + } + + try { + await router.push(target.path) + } catch (error) { + window.$ErrorLogger?.captureError({ + type: 'custom', + message: 'Failed to auto-open pasted link', + context: { pastedText, targetPath: target.path, error }, + }) + showMessage('error', 'Failed to open link', { duration: 2500 }) + } +} + +document.addEventListener('paste', handlePasteAutoOpen)