iOS 웹뷰 이미지 저장 기능 추가 (네이티브 브릿지)
- iOS 환경에서 이미지 다운로드가 안 되는 문제 해결 - 네이티브 앱 브릿지를 통한 이미지 저장 기능 구현 - iOS만 네이티브 브릿지 사용, Android/웹은 기존 방식 유지 변경사항: - BridgeMessageType에 SAVE_IMAGE 타입 추가 - SaveImageRequest, SaveImageResponse 인터페이스 정의 - appBridge.saveImage() 메서드 구현 - cash-receipt-sample.tsx에서 iOS 환경 감지 및 네이티브 저장 처리 - 네이티브 앱 개발자를 위한 구현 가이드 문서 추가 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { IMAGE_ROOT } from '@/shared/constants/common';
|
||||
import { snackBar } from '@/shared/lib';
|
||||
import { snackBar, appBridge } from '@/shared/lib';
|
||||
import { toPng } from 'html-to-image';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import '@/shared/ui/assets/css/style-tax-invoice.css';
|
||||
@@ -31,17 +31,46 @@ export const CashReceiptSample = ({
|
||||
}: CashReceiptSampleProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const downloadImage = () => {
|
||||
const downloadImage = async () => {
|
||||
const section = document.getElementById('image-section') as HTMLElement;
|
||||
toPng(section).then((image) => {
|
||||
const link = document.createElement('a');
|
||||
link.download = 'downloadImage.png';
|
||||
link.href = image;
|
||||
link.click();
|
||||
snackBar(t('common.imageRequested'), function(){
|
||||
//onClickToClose();
|
||||
});
|
||||
});
|
||||
|
||||
try {
|
||||
const imageDataUrl = await toPng(section);
|
||||
|
||||
// iOS 네이티브 환경인 경우 네이티브 브릿지 사용
|
||||
if (appBridge.isIOS()) {
|
||||
try {
|
||||
// data:image/png;base64, 부분 제거하고 순수 base64 데이터만 추출
|
||||
const base64Data = imageDataUrl.split(',')[1];
|
||||
const fileName = `cash_receipt_${moment().format('YYYYMMDDHHmmss')}.png`;
|
||||
|
||||
const result = await appBridge.saveImage({
|
||||
imageData: base64Data,
|
||||
fileName: fileName,
|
||||
mimeType: 'image/png'
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
snackBar(t('common.imageSaved'));
|
||||
} else {
|
||||
throw new Error(result.error || 'Failed to save image');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Native image save failed:', error);
|
||||
snackBar(t('common.imageSaveFailed'));
|
||||
}
|
||||
} else {
|
||||
// Android 또는 웹 환경인 경우 기존 방식 사용 (다운로드 링크)
|
||||
const link = document.createElement('a');
|
||||
link.download = `cash_receipt_${moment().format('YYYYMMDDHHmmss')}.png`;
|
||||
link.href = imageDataUrl;
|
||||
link.click();
|
||||
snackBar(t('common.imageRequested'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Image generation failed:', error);
|
||||
snackBar(t('common.imageGenerationFailed'));
|
||||
}
|
||||
};
|
||||
const onClickToClose = () => {
|
||||
setCashReceiptSampleOn(false);
|
||||
|
||||
@@ -3,7 +3,9 @@ import {
|
||||
AppBridgeResponse,
|
||||
BridgeMessageType,
|
||||
DeviceInfo,
|
||||
ShareContent
|
||||
ShareContent,
|
||||
SaveImageRequest,
|
||||
SaveImageResponse
|
||||
} from '@/types';
|
||||
|
||||
class AppBridge {
|
||||
@@ -171,6 +173,11 @@ class AppBridge {
|
||||
return this.sendMessage(BridgeMessageType.UPDATE_ALARM_COUNT, { count });
|
||||
}
|
||||
|
||||
// 이미지 저장 (iOS/Android 네이티브)
|
||||
async saveImage(request: SaveImageRequest): Promise<SaveImageResponse> {
|
||||
return this.sendMessage<SaveImageResponse>(BridgeMessageType.SAVE_IMAGE, request);
|
||||
}
|
||||
|
||||
// 네이티브 환경 체크
|
||||
isNativeEnvironment(): boolean {
|
||||
return !!(
|
||||
|
||||
@@ -82,7 +82,10 @@ export enum BridgeMessageType {
|
||||
SET_NOTIFICATION_SETTING = 'setNotificationSetting',
|
||||
|
||||
// 알림 링크 확인
|
||||
CHECK_ALARM_LINK = 'checkAlarmLink'
|
||||
CHECK_ALARM_LINK = 'checkAlarmLink',
|
||||
|
||||
// 이미지 저장
|
||||
SAVE_IMAGE = 'saveImage'
|
||||
}
|
||||
|
||||
export interface DeviceInfo {
|
||||
@@ -118,4 +121,16 @@ export interface NotificationSettingResponse {
|
||||
enabled: boolean;
|
||||
needsPermission?: boolean;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export interface SaveImageRequest {
|
||||
imageData: string; // base64 encoded image data
|
||||
fileName?: string; // 파일명 (optional, default: timestamp)
|
||||
mimeType?: string; // MIME 타입 (optional, default: 'image/png')
|
||||
}
|
||||
|
||||
export interface SaveImageResponse {
|
||||
success: boolean;
|
||||
filePath?: string; // 저장된 파일 경로
|
||||
error?: string;
|
||||
}
|
||||
Reference in New Issue
Block a user