screen shot test
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
"axios": "^1.10.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"dom-to-image": "^2.6.0",
|
||||
"html2canvas": "^1.4.1",
|
||||
"i18next": "^25.0.1",
|
||||
"iconsax-react": "^0.0.8",
|
||||
"js-cookie": "^3.0.5",
|
||||
@@ -51,6 +53,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.22.0",
|
||||
"@types/dom-to-image": "^2.6.7",
|
||||
"@types/html2canvas": "^1.0.0",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/moment-jalaali": "^0.7.9",
|
||||
"@types/react": "^19.0.10",
|
||||
|
||||
Generated
+66
@@ -38,6 +38,12 @@ importers:
|
||||
clsx:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1
|
||||
dom-to-image:
|
||||
specifier: ^2.6.0
|
||||
version: 2.6.0
|
||||
html2canvas:
|
||||
specifier: ^1.4.1
|
||||
version: 1.4.1
|
||||
i18next:
|
||||
specifier: ^25.0.1
|
||||
version: 25.2.1(typescript@5.7.3)
|
||||
@@ -123,6 +129,12 @@ importers:
|
||||
'@eslint/js':
|
||||
specifier: ^9.22.0
|
||||
version: 9.27.0
|
||||
'@types/dom-to-image':
|
||||
specifier: ^2.6.7
|
||||
version: 2.6.7
|
||||
'@types/html2canvas':
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0
|
||||
'@types/js-cookie':
|
||||
specifier: ^3.0.6
|
||||
version: 3.0.6
|
||||
@@ -1070,6 +1082,9 @@ packages:
|
||||
'@types/babel__traverse@7.20.7':
|
||||
resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==}
|
||||
|
||||
'@types/dom-to-image@2.6.7':
|
||||
resolution: {integrity: sha512-me5VbCv+fcXozblWwG13krNBvuEOm6kA5xoa4RrjDJCNFOZSWR3/QLtOXimBHk1Fisq69Gx3JtOoXtg1N1tijg==}
|
||||
|
||||
'@types/draco3d@1.4.10':
|
||||
resolution: {integrity: sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw==}
|
||||
|
||||
@@ -1082,6 +1097,10 @@ packages:
|
||||
'@types/hast@3.0.4':
|
||||
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
|
||||
|
||||
'@types/html2canvas@1.0.0':
|
||||
resolution: {integrity: sha512-BJpVf+FIN9UERmzhbtUgpXj6XBZpG67FMgBLLoj9HZKd9XifcCpSV+UnFcwTZfEyun4U/KmCrrVOG7829L589w==}
|
||||
deprecated: This is a stub types definition. html2canvas provides its own type definitions, so you do not need this installed.
|
||||
|
||||
'@types/js-cookie@3.0.6':
|
||||
resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==}
|
||||
|
||||
@@ -1285,6 +1304,10 @@ packages:
|
||||
balanced-match@1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
|
||||
base64-arraybuffer@1.0.2:
|
||||
resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
|
||||
engines: {node: '>= 0.6.0'}
|
||||
|
||||
base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
|
||||
@@ -1400,6 +1423,9 @@ packages:
|
||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
css-line-break@2.1.0:
|
||||
resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==}
|
||||
|
||||
csstype@3.1.3:
|
||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||
|
||||
@@ -1458,6 +1484,9 @@ packages:
|
||||
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
dom-to-image@2.6.0:
|
||||
resolution: {integrity: sha512-Dt0QdaHmLpjURjU7Tnu3AgYSF2LuOmksSGsUcE6ItvJoCWTBEmiMXcqBdNSAm9+QbbwD7JMoVsuuKX6ZVQv1qA==}
|
||||
|
||||
draco3d@1.5.7:
|
||||
resolution: {integrity: sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==}
|
||||
|
||||
@@ -1802,6 +1831,10 @@ packages:
|
||||
html-parse-stringify@3.0.1:
|
||||
resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==}
|
||||
|
||||
html2canvas@1.4.1:
|
||||
resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
|
||||
http2-client@1.3.5:
|
||||
resolution: {integrity: sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==}
|
||||
|
||||
@@ -2795,6 +2828,9 @@ packages:
|
||||
resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
text-segmentation@1.0.3:
|
||||
resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==}
|
||||
|
||||
three-mesh-bvh@0.8.3:
|
||||
resolution: {integrity: sha512-4G5lBaF+g2auKX3P0yqx+MJC6oVt6sB5k+CchS6Ob0qvH0YIhuUk1eYr7ktsIpY+albCqE80/FVQGV190PmiAg==}
|
||||
peerDependencies:
|
||||
@@ -2960,6 +2996,9 @@ packages:
|
||||
resolution: {integrity: sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
utrie@1.0.2:
|
||||
resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==}
|
||||
|
||||
uuid@11.1.0:
|
||||
resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==}
|
||||
hasBin: true
|
||||
@@ -4107,6 +4146,8 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/types': 7.27.3
|
||||
|
||||
'@types/dom-to-image@2.6.7': {}
|
||||
|
||||
'@types/draco3d@1.4.10': {}
|
||||
|
||||
'@types/es-aggregate-error@1.0.6':
|
||||
@@ -4119,6 +4160,10 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/unist': 3.0.3
|
||||
|
||||
'@types/html2canvas@1.0.0':
|
||||
dependencies:
|
||||
html2canvas: 1.4.1
|
||||
|
||||
'@types/js-cookie@3.0.6': {}
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
@@ -4350,6 +4395,8 @@ snapshots:
|
||||
|
||||
balanced-match@1.0.2: {}
|
||||
|
||||
base64-arraybuffer@1.0.2: {}
|
||||
|
||||
base64-js@1.5.1: {}
|
||||
|
||||
bidi-js@1.0.3:
|
||||
@@ -4463,6 +4510,10 @@ snapshots:
|
||||
shebang-command: 2.0.0
|
||||
which: 2.0.2
|
||||
|
||||
css-line-break@2.1.0:
|
||||
dependencies:
|
||||
utrie: 1.0.2
|
||||
|
||||
csstype@3.1.3: {}
|
||||
|
||||
data-view-buffer@1.0.2:
|
||||
@@ -4524,6 +4575,8 @@ snapshots:
|
||||
dependencies:
|
||||
path-type: 4.0.0
|
||||
|
||||
dom-to-image@2.6.0: {}
|
||||
|
||||
draco3d@1.5.7: {}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
@@ -4960,6 +5013,11 @@ snapshots:
|
||||
dependencies:
|
||||
void-elements: 3.1.0
|
||||
|
||||
html2canvas@1.4.1:
|
||||
dependencies:
|
||||
css-line-break: 2.1.0
|
||||
text-segmentation: 1.0.3
|
||||
|
||||
http2-client@1.3.5: {}
|
||||
|
||||
human-signals@2.1.0: {}
|
||||
@@ -5968,6 +6026,10 @@ snapshots:
|
||||
mkdirp: 3.0.1
|
||||
yallist: 5.0.0
|
||||
|
||||
text-segmentation@1.0.3:
|
||||
dependencies:
|
||||
utrie: 1.0.2
|
||||
|
||||
three-mesh-bvh@0.8.3(three@0.177.0):
|
||||
dependencies:
|
||||
three: 0.177.0
|
||||
@@ -6134,6 +6196,10 @@ snapshots:
|
||||
|
||||
utility-types@3.11.0: {}
|
||||
|
||||
utrie@1.0.2:
|
||||
dependencies:
|
||||
base64-arraybuffer: 1.0.2
|
||||
|
||||
uuid@11.1.0: {}
|
||||
|
||||
validator@13.15.15: {}
|
||||
|
||||
@@ -13,26 +13,28 @@ import Button from '@/components/Button'
|
||||
import { TickCircle } from 'iconsax-react'
|
||||
import { usePersonalityStore } from './personality/store/Store'
|
||||
import { exportPersonalityToHTML } from './personality/utils/ExportHTML'
|
||||
import { capturePersonalityScreenshot } from './personality/utils/screenshotHelper'
|
||||
import Input from '@/components/Input'
|
||||
import { useSaveTemplate, useUpdateTemplate, useGetTemplate } from './personality/hooks/usePersonalityData'
|
||||
import { useSaveTemplate, useUpdateTemplate, useGetTemplate, useSingleUpload } from './personality/hooks/usePersonalityData'
|
||||
import { toast } from '@/components/Toast'
|
||||
|
||||
const Setting: FC = () => {
|
||||
|
||||
const { t } = useTranslation()
|
||||
const { id } = useParams()
|
||||
const { data } = usePersonalityStore()
|
||||
const location = useLocation()
|
||||
const [activeTab, setActiveTab] = useState<SettingTabEnum>(SettingTabEnum.SETTING_DOMAIN)
|
||||
const [templateName, setTemplateName] = useState('')
|
||||
const [isCapturingScreenshot, setIsCapturingScreenshot] = useState(false)
|
||||
|
||||
const { mutate: saveTemplate, isPending: isSaving } = useSaveTemplate()
|
||||
const { mutate: updateTemplate, isPending: isUpdating } = useUpdateTemplate()
|
||||
const { data: template } = useGetTemplate(id || '')
|
||||
const { mutateAsync: singleUpload, isPending: isUploading } = useSingleUpload()
|
||||
|
||||
const isEditMode = !!id
|
||||
const isLoading = isSaving || isUpdating
|
||||
const isLoading = isSaving || isUpdating || isUploading || isCapturingScreenshot
|
||||
|
||||
// پر کردن نام قالب در حالت edit
|
||||
useEffect(() => {
|
||||
if (isEditMode && template?.data?.template?.name) {
|
||||
setTemplateName(template.data.template.name)
|
||||
@@ -52,7 +54,6 @@ const Setting: FC = () => {
|
||||
case Paths.settingSignature:
|
||||
return SettingTabEnum.SETTING_SIGNATURE
|
||||
default:
|
||||
// بررسی personality با id
|
||||
if (pathname.startsWith(Paths.settingPersonality + '/')) {
|
||||
return SettingTabEnum.SETTING_PERSONALITY
|
||||
}
|
||||
@@ -60,9 +61,6 @@ const Setting: FC = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// Map setting tabs to URL paths
|
||||
|
||||
// Update active tab when URL changes
|
||||
useEffect(() => {
|
||||
const tabFromPath = getTabFromPath(location.pathname)
|
||||
setActiveTab(tabFromPath)
|
||||
@@ -80,7 +78,7 @@ const Setting: FC = () => {
|
||||
return <Signture />;
|
||||
case SettingTabEnum.SETTING_PERSONALITY:
|
||||
return (
|
||||
<div className='flex xl:flex-row-reverse gap-2 md:gap-6 mt-6 md:mt-8'>
|
||||
<div className='flex xl:flex-row-reverse gap-2 md:gap-6 mt-6 md:mt-8'>
|
||||
<div className="xl:w-auto">
|
||||
<PersonalitySidebar />
|
||||
</div>
|
||||
@@ -100,16 +98,31 @@ const Setting: FC = () => {
|
||||
return
|
||||
}
|
||||
|
||||
if (activeTab !== SettingTabEnum.SETTING_PERSONALITY) {
|
||||
return
|
||||
}
|
||||
|
||||
const html = await exportPersonalityToHTML(data)
|
||||
|
||||
setIsCapturingScreenshot(true)
|
||||
const screenshotFile = await capturePersonalityScreenshot(templateName)
|
||||
setIsCapturingScreenshot(false)
|
||||
|
||||
if (!screenshotFile) {
|
||||
toast('خطا در گرفتن اسکرینشات', 'error')
|
||||
return
|
||||
}
|
||||
|
||||
const thumbnailUrl = await singleUpload(screenshotFile)
|
||||
|
||||
if (isEditMode) {
|
||||
// حالت edit - استفاده از updateTemplate
|
||||
updateTemplate({
|
||||
id: id!,
|
||||
params: {
|
||||
name: templateName,
|
||||
rawHtml: html,
|
||||
structure: data
|
||||
structure: data,
|
||||
thumbnailUrl: thumbnailUrl?.data?.url
|
||||
}
|
||||
}, {
|
||||
onSuccess: (data) => {
|
||||
@@ -120,11 +133,11 @@ const Setting: FC = () => {
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// حالت جدید - استفاده از saveTemplate
|
||||
saveTemplate({
|
||||
name: templateName,
|
||||
rawHtml: html,
|
||||
structure: data
|
||||
structure: data,
|
||||
thumbnailUrl: thumbnailUrl?.data?.url
|
||||
}, {
|
||||
onSuccess: (data) => {
|
||||
toast(data?.data?.message || 'قالب با موفقیت ایجاد شد', 'success')
|
||||
@@ -136,43 +149,31 @@ const Setting: FC = () => {
|
||||
}
|
||||
}
|
||||
|
||||
// const handleExportHTML = async () => {
|
||||
// try {
|
||||
// const html = await exportPersonalityToHTML(data)
|
||||
// const success = await copyHTMLToClipboard(html)
|
||||
|
||||
// if (success) {
|
||||
// toast(t('export_success'), 'success')
|
||||
// } else {
|
||||
// toast(t('export_error'), 'error')
|
||||
// }
|
||||
// } catch {
|
||||
// toast(t('export_error'), 'error')
|
||||
// }
|
||||
// }
|
||||
|
||||
return (
|
||||
<div className='mt-2 md:mt-4 px-2 md:px-0'>
|
||||
<div className='flex justify-between items-center'>
|
||||
<h1 className='text-lg mb-4 md:mb-0'>{t('setting.title')}</h1>
|
||||
<div className='flex gap-2'>
|
||||
<Input
|
||||
placeholder='نام قالب'
|
||||
value={templateName}
|
||||
onChange={(e) => setTemplateName(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
variant='secondary'
|
||||
className='border border-black w-fit px-7'
|
||||
onClick={handleSave}
|
||||
loading={isLoading}
|
||||
>
|
||||
<div className='flex items-center gap-2'>
|
||||
<TickCircle size={18} color='black' />
|
||||
{isEditMode ? 'بروزرسانی' : t('save')}
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
{
|
||||
activeTab === SettingTabEnum.SETTING_PERSONALITY &&
|
||||
<div className='flex gap-2'>
|
||||
<Input
|
||||
placeholder='نام قالب'
|
||||
value={templateName}
|
||||
onChange={(e) => setTemplateName(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
variant='secondary'
|
||||
className='border border-black w-fit px-7'
|
||||
onClick={handleSave}
|
||||
loading={isLoading}
|
||||
>
|
||||
<div className='flex items-center gap-2'>
|
||||
<TickCircle size={18} color='black' />
|
||||
{isEditMode ? 'بروزرسانی' : t('save')}
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
@@ -18,7 +18,7 @@ const Personality: FC = () => {
|
||||
}, [id, template, setData])
|
||||
|
||||
return (
|
||||
<div className='flex-1 bg-white rounded-4xl p-8'>
|
||||
<div className='flex-1 bg-white rounded-4xl p-8 personality-template'>
|
||||
<table width="100%" cellPadding="0" cellSpacing="0" border={0} style={{ borderCollapse: 'collapse' }}>
|
||||
<tbody>
|
||||
<HeaderSection />
|
||||
|
||||
@@ -50,3 +50,9 @@ export const useDeleteTemplate = () => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useSingleUpload = () => {
|
||||
return useMutation({
|
||||
mutationFn: (file: File) => api.singleUpload(file),
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import axios from "@/config/axios";
|
||||
import { TemplateType, TemplatesResponseType } from "../types/Types";
|
||||
import axiosDanak from "@/config/axiosDanak";
|
||||
|
||||
export const saveTemplate = async (params: TemplateType) => {
|
||||
const { data } = await axios.post("/templates", params);
|
||||
@@ -36,3 +37,12 @@ export const deleteTemplate = async (id: string) => {
|
||||
const { data } = await axios.delete(`/templates/${id}`);
|
||||
return data;
|
||||
};
|
||||
|
||||
export const singleUpload = async (file: File) => {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
||||
const { data } = await axiosDanak.post("/uploader/single-file", formData);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
@@ -269,6 +269,7 @@ export type TemplateType = {
|
||||
name: string;
|
||||
rawHtml: string;
|
||||
structure: PersonalityDataType;
|
||||
thumbnailUrl: string;
|
||||
};
|
||||
|
||||
export type GetTemplateResponse = {
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
import domtoimage from "dom-to-image";
|
||||
|
||||
/**
|
||||
* گرفتن اسکرینشات با dom-to-image و برگرداندن فایل برای آپلود
|
||||
*/
|
||||
export const captureScreenshotAsFile = async (
|
||||
templateName: string
|
||||
): Promise<File | null> => {
|
||||
try {
|
||||
console.log("📸 Starting screenshot capture for upload...");
|
||||
|
||||
const element = await findAndValidateElement();
|
||||
if (!element) {
|
||||
console.error("❌ Element not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
// آمادهسازی element
|
||||
const htmlElement = element as HTMLElement;
|
||||
const originalTransform = htmlElement.style.transform;
|
||||
const originalPosition = htmlElement.style.position;
|
||||
|
||||
htmlElement.style.transform = "scale(1)";
|
||||
htmlElement.style.position = "relative";
|
||||
|
||||
// صبر برای render کامل
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
|
||||
const options = {
|
||||
quality: 1,
|
||||
bgcolor: "#ffffff",
|
||||
width: element.offsetWidth,
|
||||
height: element.offsetHeight,
|
||||
style: {
|
||||
transform: "scale(1)",
|
||||
transformOrigin: "top left",
|
||||
},
|
||||
};
|
||||
|
||||
const dataUrl = await domtoimage.toPng(element, options);
|
||||
|
||||
// بازگردانی استایلهای اصلی
|
||||
htmlElement.style.transform = originalTransform;
|
||||
htmlElement.style.position = originalPosition;
|
||||
|
||||
// تبدیل dataURL به File
|
||||
const response = await fetch(dataUrl);
|
||||
const blob = await response.blob();
|
||||
const file = new File([blob], `${templateName}-template.png`, {
|
||||
type: "image/png",
|
||||
});
|
||||
|
||||
console.log("✅ Screenshot file created successfully:", file);
|
||||
return file;
|
||||
} catch (error) {
|
||||
console.error("❌ Screenshot capture failed:", error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* تابع اصلی - استفاده از dom-to-image و برگرداندن فایل
|
||||
*/
|
||||
export const capturePersonalityScreenshot = async (
|
||||
templateName: string
|
||||
): Promise<File | null> => {
|
||||
console.log("🎯 Starting screenshot capture...");
|
||||
|
||||
try {
|
||||
const screenshotFile = await captureScreenshotAsFile(templateName);
|
||||
if (screenshotFile) {
|
||||
console.log("✅ Screenshot captured successfully");
|
||||
return screenshotFile;
|
||||
} else {
|
||||
console.error("❌ Screenshot capture failed");
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("❌ Screenshot error:", error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* پیدا کردن و بررسی element
|
||||
*/
|
||||
const findAndValidateElement = async (): Promise<HTMLElement | null> => {
|
||||
console.log("🔍 Looking for personality element...");
|
||||
|
||||
const selectors = [
|
||||
".personality-template",
|
||||
'[class*="personality-template"]',
|
||||
".flex-1.bg-white.rounded-4xl.p-8",
|
||||
".bg-white.rounded-4xl.p-8",
|
||||
'div[class*="bg-white"][class*="rounded-4xl"]',
|
||||
];
|
||||
|
||||
for (let i = 0; i < selectors.length; i++) {
|
||||
const selector = selectors[i];
|
||||
console.log(`🔍 Trying selector ${i + 1}/${selectors.length}: ${selector}`);
|
||||
|
||||
const elements = document.querySelectorAll(selector);
|
||||
console.log(` Found ${elements.length} elements`);
|
||||
|
||||
for (let j = 0; j < elements.length; j++) {
|
||||
const element = elements[j] as HTMLElement;
|
||||
|
||||
const rect = element.getBoundingClientRect();
|
||||
const isVisible = rect.width > 0 && rect.height > 0;
|
||||
const hasContent = element.innerHTML.trim().length > 0;
|
||||
|
||||
console.log(` Element ${j + 1}:`, {
|
||||
visible: isVisible,
|
||||
hasContent,
|
||||
dimensions: `${rect.width}x${rect.height}`,
|
||||
className: element.className.slice(0, 50) + "...",
|
||||
});
|
||||
|
||||
if (isVisible && hasContent) {
|
||||
console.log(`✅ Found valid element with selector: ${selector}`);
|
||||
return element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log("❌ No valid elements found");
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* تابع debug برای بررسی element
|
||||
*/
|
||||
export const debugPersonalityElement = () => {
|
||||
console.log("🔍 === DEBUG: Personality Element Detection ===");
|
||||
|
||||
const selectors = [
|
||||
".personality-template",
|
||||
'[class*="personality-template"]',
|
||||
".flex-1.bg-white.rounded-4xl.p-8",
|
||||
".bg-white.rounded-4xl",
|
||||
"table",
|
||||
];
|
||||
|
||||
let foundElements = 0;
|
||||
|
||||
selectors.forEach((selector, index) => {
|
||||
const elements = document.querySelectorAll(selector);
|
||||
console.log(`${index + 1}. "${selector}": ${elements.length} elements`);
|
||||
|
||||
elements.forEach((el, elIndex) => {
|
||||
const htmlEl = el as HTMLElement;
|
||||
const rect = htmlEl.getBoundingClientRect();
|
||||
|
||||
console.log(` [${elIndex + 1}]`, {
|
||||
visible: rect.width > 0 && rect.height > 0,
|
||||
size: `${rect.width}x${rect.height}`,
|
||||
hasContent: htmlEl.innerHTML.trim().length > 0,
|
||||
className: htmlEl.className.slice(0, 40) + "...",
|
||||
});
|
||||
|
||||
if (rect.width > 0 && rect.height > 0) {
|
||||
foundElements++;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
console.log(`📊 Summary: ${foundElements} visible elements found`);
|
||||
console.log("=========================================");
|
||||
|
||||
return {
|
||||
found: foundElements > 0,
|
||||
totalElements: foundElements,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user