Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/config/user.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'),
Expand Down
1 change: 1 addition & 0 deletions src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
1 change: 1 addition & 0 deletions src/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions src/i18n/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ export default {
settings: '設定',
general: '一般',
debugger: 'ログを収集',
autoOpenCopiedLink: 'コピーした作品/ユーザーリンクを自動で開く',
exportLogs: 'エラーログをエクスポート',
languageChangeTitle: '言語が変更されました',
languageChangeContent:
Expand Down
1 change: 1 addition & 0 deletions src/i18n/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export default {
settings: '应用设置',
general: '通用设置',
debugger: '收集调试信息',
autoOpenCopiedLink: '粘贴后自动打开作品/用户链接',
exportLogs: '导出错误日志',
languageChangeTitle: '语言已切换',
languageChangeContent: '部分功能需要重新登录才能完全应用新语言',
Expand Down
49 changes: 49 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -56,3 +58,50 @@ document.addEventListener(
},
true,
)

function parseCopiedRouteTarget(input: string): { path: string; needLogin: boolean } | null {
const text = input.trim()

const experimentTag = text.match(/<experiment=([a-f0-9]{24})>/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(/<user=([a-f0-9]{24})>/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)