This commit is contained in:
focp212@naver.com
2025-11-12 14:54:35 +09:00
4 changed files with 517 additions and 15 deletions

View File

@@ -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';
@@ -43,20 +43,52 @@ export const CashReceiptSample = ({
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');
let fileName = 'cash-receipt-' + moment().format('YYMMDDHHmmss');
link.download = fileName + '.png';
link.href = image + '#' + fileName + '.png';
link.click();
snackBar(t('common.imageRequested'), function(){
onClickToClose();
});
}).finally(() => {
try {
const imageDataUrl = await toPng(section);
const fileName = 'cash-receipt-' + moment().format('YYMMDDHHmmss');
// iOS 네이티브 환경인 경우 네이티브 브릿지 사용
if (appBridge.isIOS()) {
try {
// data:image/png;base64, 부분 제거하고 순수 base64 데이터만 추출
const base64Data = imageDataUrl.split(',')[1];
const result = await appBridge.saveImage({
imageData: base64Data,
fileName: fileName + '.png',
mimeType: 'image/png'
});
if (result.success) {
snackBar(t('common.imageSaved'), function(){
onClickToClose();
});
} 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 = fileName + '.png';
link.href = imageDataUrl + '#' + fileName + '.png';
link.click();
snackBar(t('common.imageRequested'), function(){
onClickToClose();
});
}
} catch (error) {
console.error('Image generation failed:', error);
snackBar(t('common.imageGenerationFailed'));
} finally {
setLoading(false);
});
}
};
const onClickToClose = () => {
setCashReceiptSampleOn(false);

View File

@@ -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 !!(

View File

@@ -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;
}