Skip to content

feat: html预览新增尺寸切换 #618

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open

Conversation

Yealove
Copy link

@Yealove Yealove commented Jul 17, 2025

新增了HTML预览的尺寸切换,尺寸边界可拖动。
测试平台:

  • wsl2 Ubuntu 24.04.2
  • Vindows11专业版 26100.4652

界面如下:

桌面尺寸:
image
平板尺寸:
image
手机尺寸:
image

Summary by CodeRabbit

  • New Features
    • Added device viewport simulation controls for HTML artifact previews, allowing users to toggle between desktop, tablet, and mobile views.
    • Enabled interactive resizing of HTML previews with draggable handles for tablet and mobile modes, including custom width and height adjustments.
  • Localization
    • Added translations for new device types and dimension labels in English, Korean, Russian, Simplified Chinese, Traditional Chinese, Persian, French, and Japanese.

Copy link
Contributor

coderabbitai bot commented Jul 17, 2025

Walkthrough

This update adds a viewport simulation feature for HTML artifact previews, allowing users to toggle between desktop, tablet, and mobile views with customizable dimensions. The ArtifactDialog and HTMLArtifact components are enhanced to support interactive resizing, device controls, and localized UI labels in multiple languages. No existing logic is removed.

Changes

File(s) Change Summary
Artifact Dialog Component
src/renderer/src/components/artifacts/ArtifactDialog.vue
Added viewport size toggle and dimension controls for HTML previews; introduced reactive refs and methods to manage viewport state and pass props to preview component.
HTML Artifact Component
src/renderer/src/components/artifacts/HTMLArtifact.vue
Replaced static iframe with resizable, draggable iframe container supporting desktop, tablet, and mobile viewports; added drag handles, event handlers, computed styles, and iframe setup logic including viewport meta tag injection and CSS reset.
Localization Files
src/renderer/src/i18n/en-US/artifacts.json, src/renderer/src/i18n/ko-KR/artifacts.json, src/renderer/src/i18n/ru-RU/artifacts.json, src/renderer/src/i18n/zh-CN/artifacts.json, src/renderer/src/i18n/zh-HK/artifacts.json, src/renderer/src/i18n/zh-TW/artifacts.json, src/renderer/src/i18n/fa-IR/artifacts.json, src/renderer/src/i18n/fr-FR/artifacts.json, src/renderer/src/i18n/ja-JP/artifacts.json
Added new localization keys and values for device types ("desktop", "tablet", "mobile") and dimension labels ("width", "height") in multiple languages.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ArtifactDialog
    participant HTMLArtifact

    User->>ArtifactDialog: Opens HTML artifact
    ArtifactDialog->>ArtifactDialog: Show viewport toggle (desktop/tablet/mobile)
    User->>ArtifactDialog: Selects viewport/device
    ArtifactDialog->>HTMLArtifact: Pass viewport size and dimensions as props
    HTMLArtifact->>HTMLArtifact: Render iframe with appropriate size/style
    User->>HTMLArtifact: Drags resize handles (if tablet/mobile)
    HTMLArtifact->>HTMLArtifact: Update width/height, emit changes
    HTMLArtifact->>ArtifactDialog: Sync updated dimensions (v-model)
    User->>ArtifactDialog: Adjusts dimension inputs (optional)
    ArtifactDialog->>HTMLArtifact: Update props with new dimensions
    HTMLArtifact->>HTMLArtifact: Rerender iframe with new dimensions
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~15 minutes

Poem

🐇
Hop, hop! A preview anew,
Resize and switch your device view.
Tablet, mobile, desktop—choose,
Drag the corners, set your muse.
Now in every tongue and size,
HTML artifacts surprise!
—A rabbit’s pixel-perfect delight.

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ac97458 and 231f69c.

📒 Files selected for processing (4)
  • src/renderer/src/components/artifacts/ArtifactDialog.vue (4 hunks)
  • src/renderer/src/i18n/fa-IR/artifacts.json (1 hunks)
  • src/renderer/src/i18n/fr-FR/artifacts.json (1 hunks)
  • src/renderer/src/i18n/ja-JP/artifacts.json (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • src/renderer/src/i18n/fr-FR/artifacts.json
  • src/renderer/src/i18n/ja-JP/artifacts.json
  • src/renderer/src/i18n/fa-IR/artifacts.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/renderer/src/components/artifacts/ArtifactDialog.vue
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🔭 Outside diff range comments (1)
src/renderer/src/components/artifacts/HTMLArtifact.vue (1)

520-529: Security: Restore HTML content sanitization

I wasn’t able to find any other DOMPurify usage in the codebase, and the sanitizedContent computed property in HTMLArtifact.vue (lines 520–529) is commented out. Rendering raw props.block.content into the iframe’s srcdoc can still allow XSS—even with sandbox attributes. Please address this by either:

  • Uncommenting/reinstating the DOMPurify sanitization in HTMLArtifact.vue and using sanitizedContent for the iframe’s srcdoc, for example:

    -// const sanitizedContent = computed(() => {
    -//   if (!props.block.content) return ''
    -//   return DOMPurify.sanitize(props.block.content, { … })
    -// })
    +const sanitizedContent = computed(() => {
    +  if (!props.block.content) return ''
    +  return DOMPurify.sanitize(props.block.content, {
    +    WHOLE_DOCUMENT: true,
    +    ADD_TAGS: ['script', 'style'],
    +    ADD_ATTR: ['src', 'style', 'onclick'],
    +    ALLOWED_URI_REGEXP:
    +      /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp|xxx):|[^a-z]|[a-z+.]+(?:[^a-z+.:]|$))/i
    +  })
    +})

    …and swap the iframe’s srcdoc="props.block.content" to srcdoc="sanitizedContent".

  • Or ensure that all HTML content passed into this component has already been sanitized upstream—and document where that happens.

File needing changes:
src/renderer/src/components/artifacts/HTMLArtifact.vue (around lines 520–529)

🧹 Nitpick comments (2)
src/renderer/src/i18n/en-US/artifacts.json (1)

39-39: Inconsistent punctuation with sibling keys

copyImageFailedDesc ends with a period, whereas copyFailedDesc and most other descriptions do not. Align punctuation to avoid UI inconsistency.

-  "copyImageFailedDesc": "Could not copy image to clipboard.",
+  "copyImageFailedDesc": "Could not copy image to clipboard"
src/renderer/src/components/artifacts/HTMLArtifact.vue (1)

297-307: Consider adjusting throttle rate for better performance balance.

While the throttling implementation is good, 125fps (8ms) might be excessive. Most displays run at 60Hz, so 60fps (16ms) would provide smooth updates while reducing CPU usage.

-const UPDATE_THROTTLE = 8 // 约125fps,比60fps更流畅
+const UPDATE_THROTTLE = 16 // 60fps - matches typical display refresh rates
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6fdf288 and ac97458.

📒 Files selected for processing (8)
  • src/renderer/src/components/artifacts/ArtifactDialog.vue (4 hunks)
  • src/renderer/src/components/artifacts/HTMLArtifact.vue (4 hunks)
  • src/renderer/src/i18n/en-US/artifacts.json (1 hunks)
  • src/renderer/src/i18n/ko-KR/artifacts.json (1 hunks)
  • src/renderer/src/i18n/ru-RU/artifacts.json (1 hunks)
  • src/renderer/src/i18n/zh-CN/artifacts.json (1 hunks)
  • src/renderer/src/i18n/zh-HK/artifacts.json (1 hunks)
  • src/renderer/src/i18n/zh-TW/artifacts.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/renderer/src/**/*

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • .cursor/rules/i18n.mdc
src/renderer/src/i18n/**/*.json

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • .cursor/rules/i18n.mdc
src/renderer/**

Instructions used from:

Sources:
📄 CodeRabbit Inference Engine

  • .cursor/rules/project-structure.mdc
🧠 Learnings (8)
src/renderer/src/i18n/ko-KR/artifacts.json (6)
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Keep the structure of translation files consistent across all languages
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : When adding a new translation, add shared translations to common.json and language-specific translations to the respective language file; keep all language files' keys consistent
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Each language must have a separate JSON file in src/renderer/src/i18n/, and shared translation keys must be placed in common.json
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Regularly check for and remove unused translation keys from translation files
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Translation key naming must use dot-separated hierarchy, lowercase letters, and meaningful descriptive names (e.g., 'common.button.submit')
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/**/* : All user-facing strings in the renderer must use i18n keys (do not hardcode user-visible text in code; use vue-i18n translation keys instead)
src/renderer/src/i18n/en-US/artifacts.json (7)
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Keep the structure of translation files consistent across all languages
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : When adding a new translation, add shared translations to common.json and language-specific translations to the respective language file; keep all language files' keys consistent
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Each language must have a separate JSON file in src/renderer/src/i18n/, and shared translation keys must be placed in common.json
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Translation key naming must use dot-separated hierarchy, lowercase letters, and meaningful descriptive names (e.g., 'common.button.submit')
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Regularly check for and remove unused translation keys from translation files
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/**/* : All user-facing strings in the renderer must use i18n keys (do not hardcode user-visible text in code; use vue-i18n translation keys instead)
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/**/* : Do not hardcode user-facing text in code; always use the translation system (vue-i18n) for all user-visible strings
src/renderer/src/i18n/zh-HK/artifacts.json (5)
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Keep the structure of translation files consistent across all languages
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : When adding a new translation, add shared translations to common.json and language-specific translations to the respective language file; keep all language files' keys consistent
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Each language must have a separate JSON file in src/renderer/src/i18n/, and shared translation keys must be placed in common.json
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Regularly check for and remove unused translation keys from translation files
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Translation key naming must use dot-separated hierarchy, lowercase letters, and meaningful descriptive names (e.g., 'common.button.submit')
src/renderer/src/i18n/zh-TW/artifacts.json (7)
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Keep the structure of translation files consistent across all languages
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : When adding a new translation, add shared translations to common.json and language-specific translations to the respective language file; keep all language files' keys consistent
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Each language must have a separate JSON file in src/renderer/src/i18n/, and shared translation keys must be placed in common.json
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Regularly check for and remove unused translation keys from translation files
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Translation key naming must use dot-separated hierarchy, lowercase letters, and meaningful descriptive names (e.g., 'common.button.submit')
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/**/* : All user-facing strings in the renderer must use i18n keys (do not hardcode user-visible text in code; use vue-i18n translation keys instead)
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/**/* : Do not hardcode user-facing text in code; always use the translation system (vue-i18n) for all user-visible strings
src/renderer/src/i18n/zh-CN/artifacts.json (7)
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Keep the structure of translation files consistent across all languages
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : When adding a new translation, add shared translations to common.json and language-specific translations to the respective language file; keep all language files' keys consistent
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Each language must have a separate JSON file in src/renderer/src/i18n/, and shared translation keys must be placed in common.json
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Regularly check for and remove unused translation keys from translation files
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Translation key naming must use dot-separated hierarchy, lowercase letters, and meaningful descriptive names (e.g., 'common.button.submit')
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/**/* : All user-facing strings in the renderer must use i18n keys (do not hardcode user-visible text in code; use vue-i18n translation keys instead)
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/**/* : Do not hardcode user-facing text in code; always use the translation system (vue-i18n) for all user-visible strings
src/renderer/src/i18n/ru-RU/artifacts.json (5)
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Keep the structure of translation files consistent across all languages
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : When adding a new translation, add shared translations to common.json and language-specific translations to the respective language file; keep all language files' keys consistent
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Each language must have a separate JSON file in src/renderer/src/i18n/, and shared translation keys must be placed in common.json
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Translation key naming must use dot-separated hierarchy, lowercase letters, and meaningful descriptive names (e.g., 'common.button.submit')
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/i18n.mdc:0-0
Timestamp: 2025-06-30T12:23:45.479Z
Learning: Applies to src/renderer/src/i18n/**/*.json : Regularly check for and remove unused translation keys from translation files
src/renderer/src/components/artifacts/ArtifactDialog.vue (5)
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/pinia-best-practices.mdc:0-0
Timestamp: 2025-06-30T12:24:10.749Z
Learning: Applies to src/renderer/src/stores/**/*.{vue,ts,tsx,js,jsx} : Use modules to organize related state and actions
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/pinia-best-practices.mdc:0-0
Timestamp: 2025-06-30T12:24:10.749Z
Learning: Applies to src/renderer/src/stores/**/*.{vue,ts,tsx,js,jsx} : Keep the store focused on global state, not component-specific data
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/pinia-best-practices.mdc:0-0
Timestamp: 2025-06-30T12:24:10.749Z
Learning: Applies to src/renderer/src/stores/**/*.{vue,ts,tsx,js,jsx} : Implement proper state persistence for maintaining data across sessions
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-06-23T13:06:15.335Z
Learning: Use VueUse for common composables and utility functions to promote code reuse.
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/error-logging.mdc:0-0
Timestamp: 2025-06-30T12:23:33.814Z
Learning: Applies to **/*.tsx : 使用错误边界捕获渲染错误
src/renderer/src/components/artifacts/HTMLArtifact.vue (8)
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-best-practices.mdc:0-0
Timestamp: 2025-06-23T13:06:02.806Z
Learning: In Vue.js applications, prefer the Composition API for better code organization and reusability.
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-06-23T13:06:15.336Z
Learning: Use <script setup> syntax for concise Vue 3 component definitions.
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-06-23T13:06:15.336Z
Learning: Implement custom composables for reusable logic in Vue 3/Nuxt 3 projects.
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-06-23T13:06:15.335Z
Learning: Use template syntax for declarative rendering in Vue components.
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-06-23T13:06:15.336Z
Learning: Leverage ref, reactive, and computed for reactive state management in the Composition API.
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/error-logging.mdc:0-0
Timestamp: 2025-06-30T12:23:33.814Z
Learning: Applies to **/*.tsx : 使用错误边界捕获渲染错误
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-06-23T13:06:15.335Z
Learning: Leverage defineComponent and PropType for strong typing in Vue 3 components.
Learnt from: CR
PR: ThinkInAIXYZ/deepchat#0
File: .cursor/rules/vue-shadcn.mdc:0-0
Timestamp: 2025-06-23T13:06:15.335Z
Learning: Use VueUse for common composables and utility functions to promote code reuse.
🔇 Additional comments (7)
src/renderer/src/components/artifacts/HTMLArtifact.vue (2)

610-623: Excellent event listener cleanup implementation.

The cleanup logic properly handles:

  • Removing all event listeners on unmount
  • Clearing timers to prevent memory leaks
  • Resetting body styles if unmounting during drag operation

15-21: Smart solution for iframe interaction during resize.

The iframe mask overlay elegantly prevents the iframe from capturing mouse events during drag operations. The implementation using Vue's reactivity system is clean and efficient.

Also applies to: 319-328

src/renderer/src/components/artifacts/ArtifactDialog.vue (5)

52-93: Device viewport toggle implementation looks good with proper i18n usage.

The device size toggle buttons are well-structured with conditional rendering, proper styling, and correct i18n key usage. The implementation follows Vue best practices with reactive state binding.


95-135: Dimension input controls are well-implemented with appropriate constraints.

The dimension input section provides good UX with:

  • Proper min/max constraints for each device type
  • Responsive design with conditional rendering
  • Correct v-model bindings with number modifier
  • Proper i18n usage for labels

The input ranges are appropriate:

  • Tablet: 320-1200px width, 426-1400px height
  • Mobile: 320-480px width, 426-1000px height

247-251: Reactive state variables are properly typed and initialized.

The viewport state management is well-designed with:

  • Proper TypeScript typing for viewportSize
  • Reasonable default dimensions for tablet and mobile
  • Consistent naming conventions

The default dimensions follow common device standards:

  • Tablet: 768x1024 (iPad-like dimensions)
  • Mobile: 375x667 (iPhone-like dimensions)

322-324: setViewportSize method is simple and correct.

The method properly updates the viewport size state with appropriate typing.


204-208: Props binding to HTMLArtifact component is correctly implemented.

The component properly passes all viewport-related props and v-model bindings to the HTMLArtifact component:

  • viewport-size as a prop
  • v-model bindings for all dimension variables

This follows Vue 3 patterns correctly and enables two-way data binding for the dimension controls.

Comment on lines +39 to +44
"copyImageFailedDesc": "이미지를 클립보드에 복사할 수 없습니다",
"desktop": "데스크톱",
"tablet": "태블릿",
"mobile": "모바일",
"width": "너비",
"height": "높이"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Generic terms should live in common.json and follow hierarchical keys

desktop, tablet, mobile, width, and height are generic UI words, not artifact-specific.
Per i18n guidelines, shared strings must be placed under src/renderer/src/i18n/**/common.json using dot-separated, lower-case keys (e.g., common.device.desktop, common.dimension.width). Keeping them here duplicates data and will drift across modules/languages.

Suggest moving these entries to common.json (all languages) and updating components to reference the new keys.


🏁 Script executed:

#!/bin/bash
# Locate all common.json files in the i18n directory
find src/renderer/src/i18n -type f -name 'common.json'

# Check for existing definitions of the generic keys in those common.json files
rg '"desktop"' -g 'src/renderer/src/i18n/**/common.json' -A2 || echo "desktop not found in any common.json"
rg '"tablet"' -g 'src/renderer/src/i18n/**/common.json' -A2 || echo "tablet not found in any common.json"
rg '"mobile"' -g 'src/renderer/src/i18n/**/common.json' -A2 || echo "mobile not found in any common.json"
rg '"width"'  -g 'src/renderer/src/i18n/**/common.json' -A2 || echo "width not found in any common.json"
rg '"height"' -g 'src/renderer/src/i18n/**/common.json' -A2 || echo "height not found in any common.json"

Length of output: 1129


Move shared UI terms into common.json

These generic keys—desktop, tablet, mobile, width, and height—belong in your shared translations, not in the artifact-specific file. Please:

• Remove these entries from each src/renderer/src/i18n/*/artifacts.json (e.g. lines 39–44 in ko-KR/artifacts.json).
• Add them under logical, dot-separated keys in every src/renderer/src/i18n/*/common.json, for example:

{
  …,
+ "device": {
+   "desktop": "Desktop translation",
+   "tablet":  "Tablet translation",
+   "mobile":  "Mobile translation"
+ },
+ "dimension": {
+   "width":  "Width translation",
+   "height": "Height translation"
+ }
}

• Update all component references:

  • Change $t('artifacts.desktop')$t('common.device.desktop')
  • Similarly for tablet, mobile, width, and height

This ensures consistency across modules and prevents drift.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/renderer/src/i18n/ko-KR/artifacts.json lines 39 to 44, remove the keys
desktop, tablet, mobile, width, and height as they are generic UI terms. Add
these keys instead to src/renderer/src/i18n/ko-KR/common.json under a logical
namespace like common.device for desktop, tablet, and mobile, and
common.dimension for width and height. Then update all component code to replace
references from $t('artifacts.desktop') to $t('common.device.desktop') and
similarly for the other keys to ensure consistent shared translations.

Comment on lines +39 to +44
"copyImageFailedDesc": "Could not copy image to clipboard.",
"desktop": "Desktop",
"tablet": "Tablet",
"mobile": "Mobile",
"width": "Width",
"height": "Height"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Move generic labels to common.json & adopt hierarchical naming

Same concern as other locales: these five labels are application-wide and should be under common.json using a dot-separated namespace (common.device.*, common.dimension.*) for consistency and re-use.


🏁 Script executed:

#!/bin/bash

# Locate common.json in the i18n directory
COMMON_JSON=$(fd --full-path 'common\.json' src/renderer/src/i18n | head -n1)
echo "common.json path: ${COMMON_JSON:-not found}"

# Check whether each generic key already lives in common.json
for KEY in desktop tablet mobile width height; do
  if [[ -z "$COMMON_JSON" ]]; then
    echo "Skipping check for '$KEY': common.json not found"
  else
    if grep -q "\"$KEY\"" "$COMMON_JSON"; then
      echo "✔ '$KEY' found in common.json"
    else
      echo "✘ '$KEY' not present in common.json"
    fi
  fi
done

# Search for these keys in each locale's artifacts.json
echo -e "\nScanning locale-specific artifacts.json files for generic labels..."
for FILE in src/renderer/src/i18n/*/artifacts.json; do
  echo "File: $FILE"
  grep -En '"(desktop|tablet|mobile|width|height)"' "$FILE" || echo "  – no generic labels here"
done

Length of output: 4813


Extract generic labels into common.json with hierarchical keys

These device and dimension labels are used application-wide and should live in each locale’s common.json with a dot-separated namespace, not under artifacts.json. Please:

• Add to src/renderer/src/i18n/<locale>/common.json (creating the file if missing):

  "common.device.desktop": "Desktop",
  "common.device.tablet": "Tablet",
  "common.device.mobile": "Mobile",
  "common.dimension.width": "Width",
  "common.dimension.height": "Height"

(adjust target translations in non-en locales)

• Remove from every artifacts.json where they currently appear:

  • src/renderer/src/i18n/en-US/artifacts.json (lines 39–44)
  • src/renderer/src/i18n/ko-KR/artifacts.json (lines 40–44)
  • src/renderer/src/i18n/ru-RU/artifacts.json (lines 40–44)
  • src/renderer/src/i18n/zh-CN/artifacts.json (lines 40–44)
  • src/renderer/src/i18n/zh-HK/artifacts.json (lines 40–44)
  • src/renderer/src/i18n/zh-TW/artifacts.json (lines 40–44)

This keeps translation keys consistent, reusable, and aligned with our dot-hierarchy convention.

🤖 Prompt for AI Agents
In src/renderer/src/i18n/en-US/artifacts.json lines 39 to 44, the device and
dimension labels are incorrectly placed under artifacts.json. Move these keys to
src/renderer/src/i18n/en-US/common.json using a dot-separated namespace like
"common.device.desktop" and "common.dimension.width". Remove these keys from
artifacts.json and replicate this change for all other locale folders mentioned,
ensuring translations are updated accordingly. This will centralize common
labels and maintain consistency across locales.

Comment on lines +39 to +44
"copyFailedDesc": "无法复制内容到剪贴板",
"desktop": "桌面",
"tablet": "平板",
"mobile": "手机",
"width": "宽度",
"height": "高度"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

将通用词条迁移至 common.json 并使用分层命名

desktoptabletmobilewidthheight 属于全局共用词汇,应放入各语言的 common.json,并采用 common.device.desktopcommon.dimension.width 等点分层级命名,避免多处重复。


Here’s a quick check to locate your shared common.json and see if those keys already live there:


🏁 Script executed:

#!/bin/bash
# Find common.json under the i18n directory and verify global keys
common_paths=$(fd -HI common.json src/renderer/src/i18n)
if [ -z "$common_paths" ]; then
  echo "No common.json found under src/renderer/src/i18n"
  exit 0
fi
echo "common.json found at:"
echo "$common_paths"
for path in $common_paths; do
  echo "Checking keys in $path"
  for key in desktop tablet mobile width height; do
    echo -n "  $key: "
    grep -n "\"$key\"" "$path" || echo "Not found"
  done
done

Length of output: 10631


Move global translation keys into common.json with hierarchical naming

The keys "desktop", "tablet", "mobile", "width" and "height" are shared across multiple contexts and should live in each language’s common.json under dot-separated namespaces.

• Remove these entries from
src/renderer/src/i18n/zh-CN/artifacts.json (lines 39–44)
• In src/renderer/src/i18n/zh-CN/common.json, add:

+ "common.device.desktop": "桌面",
+ "common.device.tablet": "平板",
+ "common.device.mobile": "手机",
+ "common.dimension.width": "宽度",
+ "common.dimension.height": "高度"

• Repeat the same additions in every other language’s common.json to keep keys consistent.
• Update any code or templates that referenced artifacts.desktop/tablet/… to use common.device.desktop/common.dimension.width, etc.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/renderer/src/i18n/zh-CN/artifacts.json lines 39 to 44, remove the keys
"desktop", "tablet", "mobile", "width", and "height" as they are global
translation keys. Add these keys with appropriate hierarchical namespaces (e.g.,
device.desktop, device.tablet, device.mobile, dimension.width, dimension.height)
into src/renderer/src/i18n/zh-CN/common.json. Repeat this addition in all other
language common.json files to maintain consistency. Finally, update all code and
templates referencing these keys from artifacts to use the new paths under
common, such as common.device.desktop or common.dimension.width.

Comment on lines +39 to +44
"copyImageFailedDesc": "無法複製圖片到剪貼板",
"desktop": "桌面",
"tablet": "平板",
"mobile": "手機",
"width": "寬度",
"height": "高度"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

將共用字串移至 common.json 並使用階層式 key

同上:請把「desktop / tablet / mobile / width / height」移到 common.json,並使用如 common.device.desktop 的點分命名,以維持多語系一致性。

🤖 Prompt for AI Agents
In src/renderer/src/i18n/zh-HK/artifacts.json lines 39 to 44, the keys
"desktop", "tablet", "mobile", "width", and "height" should be moved to
src/renderer/src/i18n/zh-HK/common.json to centralize shared strings. After
moving, update their keys to use hierarchical dot notation like
"common.device.desktop" to maintain consistency across languages. Then, replace
their usage in artifacts.json with references to these new keys.

Comment on lines +39 to +44
"copyImageFailedDesc": "無法複製圖片到剪貼板",
"desktop": "桌面",
"tablet": "平板",
"mobile": "手機",
"width": "寬度",
"height": "高度"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

共用詞條應集中於 common.json

與其他語系一致,請將此處新增的五個通用詞條遷移至 common.json,並採用點分層級命名。

🤖 Prompt for AI Agents
In src/renderer/src/i18n/zh-TW/artifacts.json lines 39 to 44, the five common
terms added should be moved to the common.json file to maintain consistency
across languages. Relocate these entries to common.json and rename them using
dot-separated hierarchical keys to reflect their shared usage properly.

Comment on lines +40 to +44
"desktop": "Рабочий стол",
"tablet": "Планшет",
"mobile": "Мобильный",
"width": "Ширина",
"height": "Высота"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify translation consistency across all language files.

The new translation keys are properly formatted. However, according to the coding guidelines, we need to ensure these keys are added to all language files to maintain consistency.


🏁 Script executed:

#!/bin/bash
# Description: Verify that the new translation keys are present in all language files

# Find all artifacts.json files in different languages
echo "Checking for new keys in all language files..."
for file in $(fd -t f "artifacts.json" src/renderer/src/i18n/); do
  echo -e "\n=== $file ==="
  # Check for each new key
  for key in "desktop" "tablet" "mobile" "width" "height"; do
    if rg -q "\"$key\":" "$file"; then
      echo "✓ Key '$key' found"
    else
      echo "✗ Key '$key' missing"
    fi
  done
done

# Also check if these keys might be better suited for common.json
echo -e "\n=== Checking if similar keys exist in common.json files ==="
fd -t f "common.json" src/renderer/src/i18n/ -x rg -l "\"(desktop|tablet|mobile|width|height)\":" {} \;

Length of output: 10099


Add missing translation keys in artifacts.json for all languages

The new keys (desktop, tablet, mobile, width, height) are present in en-US, ko-KR, ru-RU, zh-CN, zh-HK, and zh-TW but are missing in several language files. They should remain in artifacts.json (no duplicates found in common.json).

Please add the following keys (with appropriate translations) to each of these files:

  • src/renderer/src/i18n/fa-IR/artifacts.json
  • src/renderer/src/i18n/fr-FR/artifacts.json
  • src/renderer/src/i18n/ja-JP/artifacts.json

Ensure the keys follow the existing structure and dot-separated naming (artifacts.desktop, etc.) so that all language files remain consistent.

🤖 Prompt for AI Agents
In src/renderer/src/i18n/fa-IR/artifacts.json, fr-FR/artifacts.json, and
ja-JP/artifacts.json, add the missing translation keys "desktop", "tablet",
"mobile", "width", and "height" with appropriate translations. Follow the
existing JSON structure and ensure the keys use the same dot-separated naming
convention as in other language files to maintain consistency across all
artifacts.json files.

Comment on lines +24 to +166
}"
@mousedown="handleTopDragStart"
:style="{
top: `calc(50% - ${(viewportSize === 'mobile' ? (mobileHeight || 844) : (tabletHeight || 800)) / 2}px - 1px)`,
width: `${viewportSize === 'mobile' ? (mobileWidth || 390) : (tabletWidth || 680)}px`
}"
>
<div class="absolute inset-x-0 top-1/2 transform -translate-y-1/2 h-0.5 bg-blue-500 opacity-0 group-hover:opacity-100 transition-opacity duration-200"
:class="{ 'opacity-100': isDragging }"></div>
</div>

<!-- 下侧拖动手柄 -->
<div
v-if="viewportSize !== 'desktop'"
class="absolute left-1/2 transform -translate-x-1/2 h-2 cursor-row-resize transition-all duration-200 group"
:class="{
'bg-blue-500 bg-opacity-30': isDragging,
'hover:bg-blue-500 hover:bg-opacity-20': !isDragging
}"
@mousedown="handleBottomDragStart"
:style="{
bottom: `calc(50% - ${(viewportSize === 'mobile' ? (mobileHeight || 844) : (tabletHeight || 800)) / 2}px - 1px)`,
width: `${viewportSize === 'mobile' ? (mobileWidth || 390) : (tabletWidth || 680)}px`
}"
>
<div class="absolute inset-x-0 top-1/2 transform -translate-y-1/2 h-0.5 bg-blue-500 opacity-0 group-hover:opacity-100 transition-opacity duration-200"
:class="{ 'opacity-100': isDragging }"></div>
</div>

<!-- 左上角拖动手柄 -->
<div
v-if="viewportSize !== 'desktop'"
class="absolute w-3 h-3 cursor-nw-resize transition-all duration-200 group"
:class="{
'bg-blue-500 bg-opacity-30': isDragging,
'hover:bg-blue-500 hover:bg-opacity-20': !isDragging
}"
@mousedown="(e) => handleCornerDragStart(e, 'nw')"
:style="{
left: `calc(50% - ${(viewportSize === 'mobile' ? (mobileWidth || 390) : (tabletWidth || 680)) / 2}px - 1px)`,
top: `calc(50% - ${(viewportSize === 'mobile' ? (mobileHeight || 844) : (tabletHeight || 800)) / 2}px - 1px)`
}"
>
<div class="absolute inset-0 border-l-2 border-t-2 border-blue-500 opacity-0 group-hover:opacity-100 transition-opacity duration-200"
:class="{ 'opacity-100': isDragging }"></div>
</div>

<!-- 右上角拖动手柄 -->
<div
v-if="viewportSize !== 'desktop'"
class="absolute w-3 h-3 cursor-ne-resize transition-all duration-200 group"
:class="{
'bg-blue-500 bg-opacity-30': isDragging,
'hover:bg-blue-500 hover:bg-opacity-20': !isDragging
}"
@mousedown="(e) => handleCornerDragStart(e, 'ne')"
:style="{
right: `calc(50% - ${(viewportSize === 'mobile' ? (mobileWidth || 390) : (tabletWidth || 680)) / 2}px - 1px)`,
top: `calc(50% - ${(viewportSize === 'mobile' ? (mobileHeight || 844) : (tabletHeight || 800)) / 2}px - 1px)`
}"
>
<div class="absolute inset-0 border-r-2 border-t-2 border-blue-500 opacity-0 group-hover:opacity-100 transition-opacity duration-200"
:class="{ 'opacity-100': isDragging }"></div>
</div>

<!-- 左下角拖动手柄 -->
<div
v-if="viewportSize !== 'desktop'"
class="absolute w-3 h-3 cursor-sw-resize transition-all duration-200 group"
:class="{
'bg-blue-500 bg-opacity-30': isDragging,
'hover:bg-blue-500 hover:bg-opacity-20': !isDragging
}"
@mousedown="(e) => handleCornerDragStart(e, 'sw')"
:style="{
left: `calc(50% - ${(viewportSize === 'mobile' ? (mobileWidth || 390) : (tabletWidth || 680)) / 2}px - 1px)`,
bottom: `calc(50% - ${(viewportSize === 'mobile' ? (mobileHeight || 844) : (tabletHeight || 800)) / 2}px - 1px)`
}"
>
<div class="absolute inset-0 border-l-2 border-b-2 border-blue-500 opacity-0 group-hover:opacity-100 transition-opacity duration-200"
:class="{ 'opacity-100': isDragging }"></div>
</div>

<!-- 右下角拖动手柄 -->
<div
v-if="viewportSize !== 'desktop'"
class="absolute w-3 h-3 cursor-se-resize transition-all duration-200 group"
:class="{
'bg-blue-500 bg-opacity-30': isDragging,
'hover:bg-blue-500 hover:bg-opacity-20': !isDragging
}"
@mousedown="(e) => handleCornerDragStart(e, 'se')"
:style="{
right: `calc(50% - ${(viewportSize === 'mobile' ? (mobileWidth || 390) : (tabletWidth || 680)) / 2}px - 1px)`,
bottom: `calc(50% - ${(viewportSize === 'mobile' ? (mobileHeight || 844) : (tabletHeight || 800)) / 2}px - 1px)`
}"
>
<div class="absolute inset-0 border-r-2 border-b-2 border-blue-500 opacity-0 group-hover:opacity-100 transition-opacity duration-200"
:class="{ 'opacity-100': isDragging }"></div>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add accessibility support for resize handles.

The resize handles lack keyboard support and ARIA attributes, making them inaccessible to users who rely on keyboards or screen readers.

Consider adding:

  1. ARIA labels for screen readers:
       <div
         v-if="viewportSize !== 'desktop'"
         class="absolute top-1/2 transform -translate-y-1/2 w-2 cursor-col-resize transition-all duration-200 group"
+        role="separator"
+        :aria-label="`Resize ${viewportSize} preview width from left`"
+        tabindex="0"
         :class="{ 
  1. Keyboard event handlers:
         @mousedown="handleLeftDragStart"
+        @keydown="handleKeyboardResize"
  1. Add a keyboard resize handler:
const handleKeyboardResize = (e: KeyboardEvent) => {
  if (props.viewportSize === 'desktop') return
  
  const step = e.shiftKey ? 10 : 1
  let currentWidth = props.viewportSize === 'mobile' 
    ? props.mobileWidth || 390
    : props.tabletWidth || 680
    
  switch(e.key) {
    case 'ArrowLeft':
      currentWidth -= step
      break
    case 'ArrowRight':
      currentWidth += step
      break
    default:
      return
  }
  
  e.preventDefault()
  // Apply constraints and emit updates
  const { minWidth, maxWidth } = dragConstraints.value
  currentWidth = Math.max(minWidth, Math.min(maxWidth, currentWidth))
  
  if (props.viewportSize === 'mobile') {
    emit('update:mobileWidth', currentWidth)
  } else {
    emit('update:tabletWidth', currentWidth)
  }
}
🤖 Prompt for AI Agents
In src/renderer/src/components/artifacts/HTMLArtifact.vue between lines 24 and
166, the resize handles lack accessibility features such as keyboard support and
ARIA attributes. To fix this, add appropriate ARIA labels to each resize handle
for screen reader clarity, implement keyboard event handlers to capture key
presses, and integrate a keyboard resize handler function that adjusts the width
based on arrow key inputs with shift key support for larger steps. Ensure the
handler respects viewport constraints and emits the updated width values
accordingly.

Copy link
Collaborator

@zerob13 zerob13 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix i18n

Run pnpm run i18n
pnpm run i18n
shell: /usr/bin/bash -e {0}
env:
PNPM_HOME: /home/runner/setup-pnpm/node_modules/.bin

[email protected] i18n /home/runner/work/deepchat/deepchat
i18n-check -s zh-CN -f i18next --locales src/renderer/src/i18n

i18n translations checker
Source: zh-CN
Selected format is: i18next

Found missing keys!
┌────────────────────────────────────────────┬─────────┐
│ file │ key │
├────────────────────────────────────────────┼─────────┤
│ src/renderer/src/i18n/fa-IR/artifacts.json │ desktop │
│ src/renderer/src/i18n/fa-IR/artifacts.json │ tablet │
│ src/renderer/src/i18n/fa-IR/artifacts.json │ mobile │
│ src/renderer/src/i18n/fa-IR/artifacts.json │ width │
│ src/renderer/src/i18n/fa-IR/artifacts.json │ height │
│ src/renderer/src/i18n/fr-FR/artifacts.json │ desktop │
│ src/renderer/src/i18n/fr-FR/artifacts.json │ tablet │
│ src/renderer/src/i18n/fr-FR/artifacts.json │ mobile │
│ src/renderer/src/i18n/fr-FR/artifacts.json │ width │
│ src/renderer/src/i18n/fr-FR/artifacts.json │ height │
│ src/renderer/src/i18n/ja-JP/artifacts.json │ desktop │
│ src/renderer/src/i18n/ja-JP/artifacts.json │ tablet │
│ src/renderer/src/i18n/ja-JP/artifacts.json │ mobile │
│ src/renderer/src/i18n/ja-JP/artifacts.json │ width │
│ src/renderer/src/i18n/ja-JP/artifacts.json │ height │
└────────────────────────────────────────────┴─────────┘

No invalid translations found!

Done in 0.06s.
 ELIFECYCLE  Command failed with exit code 1.

@zerob13
Copy link
Collaborator

zerob13 commented Aug 5, 2025

[email protected] format:check /home/runner/work/deepchat/deepchat
prettier --check .

Checking formatting...
[warn] src/renderer/src/components/artifacts/ArtifactDialog.vue
[warn] src/renderer/src/components/artifacts/HTMLArtifact.vue
[warn] Code style issues found in 2 files. Run Prettier with --write to fix.
 ELIFECYCLE  Command failed with exit code 1.
Error: Process completed with exit code 1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants