Skip to content

Comments

Add copy/paste specific attributes for nodes and edges#1316

Open
Copilot wants to merge 8 commits intomainfrom
copilot/copy-paste-specific-attributes
Open

Add copy/paste specific attributes for nodes and edges#1316
Copilot wants to merge 8 commits intomainfrom
copilot/copy-paste-specific-attributes

Conversation

Copy link
Contributor

Copilot AI commented Jan 31, 2026

  • Explore codebase to understand clipboard, details panel, and context menu structure
  • Add new ClipboardData type field to distinguish "specific attributes" copy mode
  • Create utility functions for extracting specific attributes from nodes and edges
  • Create utility functions for pasting specific attributes to nodes and edges
  • Add "Copy Specific Attributes" / "Paste Specific Attributes" buttons to details panel footer
  • Add "Copy Specific Attributes" / "Paste Specific Attributes" menu items to context menu
  • Add translations for new UI elements (en, zh-Hans, zh-Hant, ja, ko)
  • Add unit tests for the new clipboard utility functions
  • Address review feedback:
    • Add saveVersion field to all clipboard data types
    • Add CLIPBOARD_VERSION constant for clipboard format versioning
    • Make type field non-optional (no backward compatibility)
    • Validate both version and saveVersion on paste
    • For edges: only require style type match for paste; apply roundCornerFactor if target path supports it
    • Update tests to include saveVersion validation
  • Add keyboard shortcuts (Ctrl+Shift+C/V or Cmd+Shift+C/V on Mac) for copy/paste specific attributes
  • Add keyboard shortcuts to settings shortcuts documentation
  • Fix missing copyAttrs translation key in panel.details.footer
  • Update translations to use "独特属性" (specific attributes) prefix in Chinese translations
  • Run tests and linting to verify changes
  • Code review and address feedback
  • Run CodeQL security check

Summary of Changes

Keyboard shortcuts (src/components/svg-wrapper.tsx)

  • Added Ctrl+Shift+C (Cmd+Shift+C on Mac) to copy specific attributes
  • Added Ctrl+Shift+V (Cmd+Shift+V on Mac) to paste specific attributes

Settings shortcuts documentation (src/components/page-header/settings-modal.tsx)

  • Added new shortcut rows for copy/paste specific attributes

Translations (all 5 language files)

  • Fixed missing copyAttrs key in panel.details.footer
  • Updated all translations to use "specific attributes" terminology:
    • English: "Copy/Paste Specific Attributes"
    • Chinese Simplified: "复制/粘贴独特属性"
    • Chinese Traditional: "複製/貼上獨特屬性"
    • Japanese: "独自属性をコピー/貼り付け"
    • Korean: "고유 속성 복사/붙여넣기"
  • Added shortcut descriptions to all language files

Screenshots

Keyboard shortcuts in settings:

Original prompt

This section details on the original issue you should resolve

<issue_title>Copy and paste specific attributes</issue_title>
<issue_description>当用户仅选择了一个节点或线段时,允许用户在右侧详情页面的最下方和右键菜单中拷贝其独特属性
接着在剪贴板中写入其独特属性的信息,在当前ClipboardData中添加额外的type字段以与当前单选或多选拷贝区分
最后,在用户单选或者多选但是所有元素类型相同时,允许用户在右侧详情页面的最下方和右键菜单中粘贴其独特属性
特别地,对于线段,仅有path的roundCornerFactor和style的所有独特属性会被拷贝和粘贴,如果path没有roundCornerFactor的话那么仅有style的所有独特属性会被拷贝和粘贴</issue_description>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits January 31, 2026 14:24
Co-authored-by: thekingofcity <3353040+thekingofcity@users.noreply.github.com>
Co-authored-by: thekingofcity <3353040+thekingofcity@users.noreply.github.com>
Copilot AI changed the title [WIP] Add functionality to copy and paste unique attributes Add copy/paste specific attributes for nodes and edges Jan 31, 2026
Copilot AI requested a review from thekingofcity January 31, 2026 14:34
Copy link
Member

@thekingofcity thekingofcity left a comment

Choose a reason for hiding this comment

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

@copilot 有两个问题
第一,粘贴特殊属性的时候,一定要确保当前的节点类型和剪贴板中的一致。对于线段,只要确保style一致即可,对于roundedCornerFactor,只要path有这个属性就能粘贴。
第二,特殊属性的剪贴板中要包含当前的存档版本,如果粘贴时发现存档版本saveVersion不一致,那么有可能即使类型相同特殊属性也不同,那么就不能粘贴。特殊属性的剪贴板数据中还要包含固定的version编号,以确保特殊属性的格式没变但是剪贴板的数据格式变了的情况,粘贴时也要检查。同理,之前就有的复制粘贴节点和线段的功能,除了version外还要保存saveVersion确保数据格式一致,那么type?就没必要可能undefined了,因为我们不向后兼容。

Copilot AI and others added 2 commits February 1, 2026 04:00
Co-authored-by: thekingofcity <3353040+thekingofcity@users.noreply.github.com>
…eview

Co-authored-by: thekingofcity <3353040+thekingofcity@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 1, 2026

@copilot 有两个问题
第一,粘贴特殊属性的时候,一定要确保当前的节点类型和剪贴板中的一致。对于线段,只要确保style一致即可,对于roundedCornerFactor�...

Fixed in commits e7adc5d and a977d8e:

  1. Type matching for paste:

    • For nodes: now validates exact nodeType match
    • For edges: validates styleType match; roundCornerFactor is applied only if target path supports it (diagonal, perpendicular, or rotate-perpendicular) via the new hasRoundCornerFactor() helper
  2. Version checking:

    • Added saveVersion field (set to CURRENT_VERSION) to all clipboard data types
    • Added CLIPBOARD_VERSION constant for clipboard format versioning
    • Made type field non-optional - returns null if missing/invalid
    • Validates both version === CLIPBOARD_VERSION and saveVersion === CURRENT_VERSION on paste

@thekingofcity
Copy link
Member

@copilot 用户应该可以通过快捷键ctrl+shift+c/v拷贝或粘贴独特属性,并且在设置的快捷键提示中一并标明。另外我还注意到有些地方的本地化文本没有准备好,比如panel.details.footer.copyAttrs,并且翻译时保留现有的独特前缀为独特属性而非单独的属性。

…pdate translations

Co-authored-by: thekingofcity <3353040+thekingofcity@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 1, 2026

@copilot 用户应该可以通过快捷键ctrl+shift+c/v拷贝或粘贴独特属性,并且在设置的快捷键提示中一并标明。另外我还注意到有些地方的本地化文本没有准备...

Fixed in commit 74217ed:

  1. Keyboard shortcuts: Added Ctrl+Shift+C/V (Cmd+Shift+C/V on Mac) for copy/paste specific attributes in svg-wrapper.tsx

  2. Settings shortcuts hint: Added new rows in the shortcuts table in settings-modal.tsx showing the new keyboard shortcuts

  3. Missing translations: Added the missing copyAttrs key to panel.details.footer in all language files

  4. Translation terminology: Updated to use "独特属性" (specific attributes) prefix:

    • zh-Hans: "复制独特属性" / "粘贴独特属性"
    • zh-Hant: "複製獨特屬性" / "貼上獨特屬性"
    • ja: "独自属性をコピー" / "独自属性を貼り付け"
    • ko: "고유 속성 복사" / "고유 속성 붙여넣기"
    • en: "Copy Specific Attributes" / "Paste Specific Attributes"

Keyboard shortcuts in settings

@thekingofcity thekingofcity marked this pull request as ready for review February 1, 2026 12:29
; Conflicts:
;	src/components/context-menu.tsx
;	src/i18n/translations/en.json
;	src/i18n/translations/ja.json
;	src/i18n/translations/ko.json
;	src/i18n/translations/zh-Hans.json
;	src/i18n/translations/zh-Hant.json
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds the ability to copy and paste specific attributes for nodes and edges in the Rail Map Painter application. Users can now copy type-specific attributes (e.g., station names, line colors) from one element and apply them to multiple elements of the same type, separate from copying the entire element.

Changes:

  • Added clipboard data types and versioning system for specific attribute copy/paste operations
  • Implemented keyboard shortcuts (Ctrl+Shift+C/V or Cmd+Shift+C/V) for copying and pasting specific attributes
  • Added UI buttons in the details panel and context menu for specific attribute operations
  • Added comprehensive unit tests for the new clipboard utility functions
  • Updated all language translations (English, Chinese Simplified, Chinese Traditional, Japanese, Korean) with new UI labels

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/util/clipboard.ts Core implementation of specific attribute export/import functions, clipboard data types, version validation, and helper utilities
src/util/clipboard.test.ts Comprehensive unit tests covering all new clipboard functions with version validation
src/components/svg-wrapper.tsx Keyboard shortcuts (Ctrl+Shift+C/V) for copy/paste specific attributes
src/components/panels/details/details.tsx Added buttons in details panel footer for copy/paste specific attributes
src/components/context-menu.tsx Added menu items for copy/paste specific attributes in the context menu
src/components/page-header/settings-modal.tsx Updated keyboard shortcuts documentation with new shortcuts
src/i18n/translations/*.json Added translations for new UI elements across all 5 supported languages
package-lock.json Dependency lock file updates (peer dependency flag changes, likely from npm version update)

const parsed = JSON.parse(result) as NodeSpecificAttrsClipboardData;

expect(parsed.app).toBe('rmp');
expect(parsed.version).toBe(1);
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

The test should verify the version using the CLIPBOARD_VERSION constant instead of the hardcoded value 1. This ensures the test remains correct if the clipboard version is incremented in the future. Change this to expect(parsed.version).toBe(CLIPBOARD_VERSION);

Suggested change
expect(parsed.version).toBe(1);
expect(parsed.version).toBe(CLIPBOARD_VERSION);

Copilot uses AI. Check for mistakes.
const parsed = JSON.parse(result) as EdgeSpecificAttrsClipboardData;

expect(parsed.app).toBe('rmp');
expect(parsed.version).toBe(1);
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

The test should verify the version using the CLIPBOARD_VERSION constant instead of the hardcoded value 1. This ensures the test remains correct if the clipboard version is incremented in the future. Change this to expect(parsed.version).toBe(CLIPBOARD_VERSION);

Suggested change
expect(parsed.version).toBe(1);
expect(parsed.version).toBe(CLIPBOARD_VERSION);

Copilot uses AI. Check for mistakes.
const allElements = structuredClone(nodes) as Set<Id>;
edges.forEach(s => allElements.add(s));
dispatch(setSelected(allElements));
} else if (e.key === 'C' && (isMacClient ? e.metaKey && e.shiftKey : e.ctrlKey && e.shiftKey)) {
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

The keyboard shortcut implementation is inconsistent with the existing pattern in this file. Line 386 uses lowercase 'z' with an explicit shiftKey check for the Cmd+Shift+Z shortcut. For consistency with the codebase conventions, consider using lowercase 'c' here: e.key === 'c' && (isMacClient ? e.metaKey && e.shiftKey : e.ctrlKey && e.shiftKey). Note that using uppercase 'C' is technically more correct according to the KeyboardEvent spec, but lowercase with explicit shiftKey check matches the existing pattern in this file.

Copilot uses AI. Check for mistakes.
navigator.clipboard.writeText(s);
}
}
} else if (e.key === 'V' && (isMacClient ? e.metaKey && e.shiftKey : e.ctrlKey && e.shiftKey)) {
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

The keyboard shortcut implementation is inconsistent with the existing pattern in this file. Line 386 uses lowercase 'z' with an explicit shiftKey check for the Cmd+Shift+Z shortcut. For consistency with the codebase conventions, consider using lowercase 'v' here: e.key === 'v' && (isMacClient ? e.metaKey && e.shiftKey : e.ctrlKey && e.shiftKey). Note that using uppercase 'V' is technically more correct according to the KeyboardEvent spec, but lowercase with explicit shiftKey check matches the existing pattern in this file.

Copilot uses AI. Check for mistakes.
Comment on lines +14 to +15
ExternalLinePathAttributes,
ExternalLineStyleAttributes,
Copy link

Copilot AI Feb 1, 2026

Choose a reason for hiding this comment

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

Unused imports ExternalLinePathAttributes, ExternalLineStyleAttributes.

Suggested change
ExternalLinePathAttributes,
ExternalLineStyleAttributes,

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Copy and paste specific attributes

2 participants