-
Notifications
You must be signed in to change notification settings - Fork 1
Feat/image preview #49
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
Conversation
There was a problem hiding this 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 implements image preview and clipboard copy functionality for network request/response data, enabling direct visualization of binary image data in the UI. The implementation includes Web Worker-based performance optimization to prevent main thread blocking during Base64 conversion.
Key Changes
- Web Worker implementation for Base64 conversion to prevent UI blocking
- Image preview component with fullscreen mode and download functionality
- Enhanced data type detection for better image/video format recognition
Reviewed Changes
Copilot reviewed 14 out of 16 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tauri-ui/src/workers/base64-worker.ts | New Web Worker for non-blocking Base64 conversion |
| tauri-ui/src/hooks/use-base64-worker.ts | Hook for managing Web Worker lifecycle and tasks |
| tauri-ui/src/features/transaction-details/ui/image-preview.tsx | Image preview component with fullscreen and download features |
| tauri-ui/src/features/transaction-details/ui/transaction-response.tsx | Integrated image preview and clipboard copy for responses |
| tauri-ui/src/features/transaction-details/ui/transaction-body.tsx | Integrated image preview and clipboard copy for requests |
| tauri-ui/src/features/transaction-details/lib/utils.ts | Utility functions for Base64 conversion and image data URL creation |
| crates/proxy_v2_models/src/data_type.rs | Enhanced image/video detection with additional format support |
| tauri-ui/src-tauri/Cargo.toml | Added clipboard manager plugin dependency |
| tauri-ui/src-tauri/capabilities/default.json | Added clipboard permissions |
| tauri-ui/rspack.config.ts | Worker support configuration |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| function uint8ArrayToBase64(data: Uint8Array | number[]): string { | ||
| if (!data || data.length === 0) { | ||
| return ''; | ||
| } | ||
|
|
||
| const uint8Array = data instanceof Uint8Array ? data : new Uint8Array(data); | ||
|
|
||
| // 청크 단위로 처리하여 메모리 효율성 향상 | ||
| const chunkSize = 8192; // 8KB 청크 | ||
| let result = ''; | ||
|
|
||
| for (let i = 0; i < uint8Array.length; i += chunkSize) { | ||
| const chunk = uint8Array.slice(i, i + chunkSize); | ||
| const binary = Array.from(chunk, (byte) => String.fromCharCode(byte)).join(''); | ||
| result += btoa(binary); | ||
| } | ||
|
|
||
| return result; | ||
| } |
Copilot
AI
Oct 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The chunked Base64 encoding is incorrect. Each chunk is being encoded separately with btoa(), but Base64 encoding requires the entire data to be encoded as one unit. This will produce invalid Base64 output. Use a streaming approach or encode the entire binary string at once.
| export const uint8ArrayToBase64 = (data: Uint8Array | number[]): string => { | ||
| if (!data || data.length === 0) { | ||
| return ''; | ||
| } | ||
|
|
||
| try { | ||
| // 일반 배열인 경우 Uint8Array로 변환 | ||
| const uint8Array = data instanceof Uint8Array ? data : new Uint8Array(data); | ||
|
|
||
| // Uint8Array를 문자열로 변환한 후 Base64 인코딩 | ||
| let binary = ''; | ||
| for (let i = 0; i < uint8Array.length; i++) { | ||
| binary += String.fromCharCode(uint8Array[i]); | ||
| } | ||
| return btoa(binary); | ||
| } catch (error) { | ||
| console.error('Base64 인코딩 실패:', error); | ||
| return ''; | ||
| } | ||
| }; |
Copilot
AI
Oct 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function contains duplicated Base64 encoding logic that exists in the worker file. Consider extracting this to a shared utility or ensure consistency between implementations.
|
|
||
| const getImageFileExtension = (dataType: string): string => { | ||
| // MIME 타입에서 확장자 추출하는 간단한 함수 | ||
| return 'png'; // 기본값 |
Copilot
AI
Oct 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function getImageFileExtension only returns 'png' and doesn't actually extract extensions from MIME types as the comment suggests. This could lead to incorrect file extensions when downloading images.
| return 'png'; // 기본값 | |
| // e.g., "image/png" -> "png", "image/jpeg" -> "jpg", "image/gif" -> "gif" | |
| if (!dataType) return 'png'; | |
| const mimeToExt: Record<string, string> = { | |
| 'image/png': 'png', | |
| 'image/jpeg': 'jpg', | |
| 'image/jpg': 'jpg', | |
| 'image/gif': 'gif', | |
| 'image/webp': 'webp', | |
| 'image/bmp': 'bmp', | |
| 'image/svg+xml': 'svg', | |
| 'image/tiff': 'tiff', | |
| }; | |
| if (mimeToExt[dataType]) return mimeToExt[dataType]; | |
| // Fallback: try to extract after '/' and handle '+xml' | |
| const parts = dataType.split('/'); | |
| if (parts.length === 2) { | |
| let ext = parts[1]; | |
| // Remove '+xml' if present (e.g., 'svg+xml') | |
| ext = ext.replace(/\+xml$/, ''); | |
| return ext; | |
| } | |
| return 'png'; |
| const getImageFileExtension = (dataType: string): string => { | ||
| // MIME 타입에서 확장자 추출하는 간단한 함수 | ||
| return 'png'; // 기본값 |
Copilot
AI
Oct 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate implementation of getImageFileExtension that only returns 'png'. This logic is duplicated across multiple files and should be extracted to a shared utility function with proper MIME type to extension mapping.
| const getImageFileExtension = (dataType: string): string => { | |
| // MIME 타입에서 확장자 추출하는 간단한 함수 | |
| return 'png'; // 기본값 | |
| // Utility function to map MIME type to file extension | |
| const getImageFileExtension = (dataType: string): string => { | |
| const mimeToExt: Record<string, string> = { | |
| 'image/png': 'png', | |
| 'image/jpeg': 'jpg', | |
| 'image/jpg': 'jpg', | |
| 'image/gif': 'gif', | |
| 'image/webp': 'webp', | |
| 'image/bmp': 'bmp', | |
| 'image/svg+xml': 'svg', | |
| }; | |
| return mimeToExt[dataType] || 'png'; // 기본값 |
🖼️ PR: 이미지 미리보기 및 클립보드 복사 기능 구현
📋 요약
이 PR은 네트워크 요청/응답에서 이미지 파일을 직접 미리보기할 수 있는 기능과 이미지 클립보드 복사 기능을 구현합니다.
✨ 주요 기능
1. 이미지 미리보기 기능
2. Web Worker 기반 성능 최적화
4. 데이터 타입 감지 개선
🔧 기술적 개선사항
백엔드 (Rust)
crates/proxy_v2_models/src/data_type.rs: 데이터 타입 감지 로직 개선tauri-plugin-clipboard-manager: 클립보드 매니저 플러그인 추가프론트엔드 (TypeScript/React)
ImagePreview컴포넌트: 새로운 이미지 미리보기 컴포넌트useBase64WorkerHook: Web Worker 관리base64-worker.ts: Base64 변환 Web WorkerTransactionBody/TransactionResponse: 이미지 미리보기 및 클립보드 복사 통합설정 및 빌드
🚀 사용자 경험 개선
🔍 추가 개선 사항