diff --git a/electron/components/file.js b/electron/components/file.js index fa79cb3c1a2613e35f9f70a4fbf19d475b160bad..787f04378bfebc22eebbea63fa2396c130abbda1 100644 --- a/electron/components/file.js +++ b/electron/components/file.js @@ -235,10 +235,15 @@ const writeEpocData = async function (workdir, data) { * Copy the imported file to the workdir * @param {string} workdir * @param {string} filepath + * @param {boolean} isIcon * @return {string} the path of the copied file */ -const copyFileToWorkdir = async function (workdir, filepath) { - const assetsPath = path.join(workdir, 'assets'); +const copyFileToWorkdir = async function (workdir, filepath, isIcon) { + const pathEnd = isIcon ? path.join('assets', 'icons') : 'assets'; + const assetsPath = path.join(workdir, pathEnd); + + if(!fs.existsSync(assetsPath)) fs.mkdirSync(assetsPath, {recursive: true}); + const copyPath = path.join(assetsPath, path.basename(filepath).replace(/[^a-z0-9.]/gi, '_')); if (!fs.existsSync(assetsPath)) fs.mkdirSync(assetsPath); fs.copyFileSync(filepath, copyPath); diff --git a/electron/components/ipc.js b/electron/components/ipc.js index a3e34e4c9f4b610cd0a20b0603ff425531f17b34..16421600b36769a353724efb4ef781c9bef3fb67 100644 --- a/electron/components/ipc.js +++ b/electron/components/ipc.js @@ -102,10 +102,11 @@ const setupIpcListener = function (targetWindow) { await writeEpocData(store.state.projects[targetWindow.id].workdir, data); }); - ipcMain.on('importFile', async (event, filepath) => { + ipcMain.on('importFile', async (event, data) => { + const { filepath, isIcon } = data; if(event.sender !== targetWindow.webContents) return; - sendToFrontend(event.sender, 'fileImported', await copyFileToWorkdir(store.state.projects[targetWindow.id].workdir, filepath)); + sendToFrontend(event.sender, 'fileImported', await copyFileToWorkdir(store.state.projects[targetWindow.id].workdir, filepath, isIcon)); }); diff --git a/src/features/badge/components/BadgeItem.vue b/src/features/badge/components/BadgeItem.vue index d5b6cfbc461630bc06249922a9d8ffac845fb4b1..86851e0e54c4ceb88dcb834fa88e214b356b6b53 100644 --- a/src/features/badge/components/BadgeItem.vue +++ b/src/features/badge/components/BadgeItem.vue @@ -30,7 +30,8 @@ const badgeItem = computed(() => { function getIconPath() { const icon = props.badge ? props.badge.icon : props.icon; - return icon.endsWith('.svg') ? icon : `${iconsPath}/${icon}.svg`; + if(icon.startsWith('blob')) return icon; + return icon.endsWith('.svg') ? `assets://${icon}` : `${iconsPath}/${icon}.svg`; } </script> diff --git a/src/features/badge/components/BadgePreview.vue b/src/features/badge/components/BadgePreview.vue index b51cbdf50b5289dafb627402878b551d2bc2ca93..ce24a2bf652ea42e171030d31026d27af22bad23 100644 --- a/src/features/badge/components/BadgePreview.vue +++ b/src/features/badge/components/BadgePreview.vue @@ -1,7 +1,6 @@ <script setup lang="ts"> import BadgeItem from '@/src/features/badge/components/BadgeItem.vue'; import { ref } from 'vue'; -import { graphService } from '@/src/shared/services'; const emit = defineEmits<{ (e: 'click', icon: string): void; @@ -21,13 +20,15 @@ async function changeIcon(event: Event) { const file = target.files[0]; if (!file) return; fileInput.value.value = ''; - url.value = await graphService.importFile(file.path); + url.value = file.path; + blob.value = URL.createObjectURL(file); } function deleteFile() { url.value = ''; } const url = ref(''); +const blob = ref(''); const fileInput = ref(null); </script> @@ -35,7 +36,7 @@ const fileInput = ref(null); <template> <div class="new-icon"> <BadgeItem - :icon="url" + :icon="blob" :inactive="!url" @click="onClick" /> diff --git a/src/features/badge/components/IconModal.vue b/src/features/badge/components/IconModal.vue index b0205377034296f17eb384003c402c2d3d85ad5b..f658ee0446ace8a65f32b09bb12675603e099530 100644 --- a/src/features/badge/components/IconModal.vue +++ b/src/features/badge/components/IconModal.vue @@ -5,6 +5,7 @@ import { saveState } from '@/src/shared/services/undoRedo.service'; import BadgeItem from '@/src/features/badge/components/BadgeItem.vue'; import BadgePreview from '@/src/features/badge/components/BadgePreview.vue'; +import { saveCustomIcon } from '@/src/shared/services'; const editorStore = useEditorStore(); const projectStore = useProjectStore(); @@ -24,9 +25,10 @@ function chooseIcon(icon: string) { close(); } -function chooseCustomIcon(icon: string) { - projectStore.addCustomIcon(icon); - chooseIcon(icon); +async function chooseCustomIcon(icon: string) { + const iconPath = await saveCustomIcon(icon); + + chooseIcon(iconPath); } </script> diff --git a/src/shared/services/badge.service.ts b/src/shared/services/badge.service.ts index d54d3e4ce0da723ba53d129d79c088f62ade3d3a..62eac53f8d835e987ce480b77714b3119d5719b1 100644 --- a/src/shared/services/badge.service.ts +++ b/src/shared/services/badge.service.ts @@ -1,10 +1,10 @@ import { Verbs, ElementType, Condition, Badge } from '@/src/shared/interfaces'; import { Operand, Operands, Rule } from '@epoc/epoc-types/src/v2'; -import { useEditorStore } from '@/src/shared/stores'; +import { useEditorStore, useProjectStore } from '@/src/shared/stores'; import { useVueFlow} from '@vue-flow/core'; import { saveState } from '@/src/shared/services/undoRedo.service'; import { elementVerbs, verbs } from '@/src/shared/data'; -import { generateContentId } from '@/src/shared/services'; +import { generateContentId, graphService } from '@/src/shared/services'; const { findNode } = useVueFlow({id: 'main'}); @@ -200,4 +200,13 @@ export function addNewBadge() { }; openBadge(id); +} + +export async function saveCustomIcon(icon: string) { + const projectStore = useProjectStore(); + + const iconPath = await graphService.importFile(icon, true); + projectStore.addCustomIcon(iconPath); + + return iconPath; } \ No newline at end of file diff --git a/src/shared/services/graph.service.ts b/src/shared/services/graph.service.ts index 14ac4e52db376456a0e48cb9335dc2952540d53d..3c38677a3e2a81f0c46acd925b9935c23e309206 100644 --- a/src/shared/services/graph.service.ts +++ b/src/shared/services/graph.service.ts @@ -27,8 +27,8 @@ function writeProjectData(): void { }); } -function importFile(filepath: string): Promise<string> { - api.send('importFile', filepath); +function importFile(filepath: string, isIcon?: boolean): Promise<string> { + api.send('importFile', { filepath, isIcon: Boolean(isIcon) }); return new Promise((resolve) => { api.receiveOnce('fileImported', (data) => {